yakischloba-drizzle-ffi 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +42 -0
- data/Rakefile +11 -0
- data/drizzle.gemspec +20 -0
- data/lib/drizzle/drizzle.rb +229 -0
- data/lib/drizzle.rb +3 -0
- data/tests/basic.rb +104 -0
- metadata +78 -0
data/README.rdoc
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
Currently a simple client-oriented hookup to libdrizzle with ffi, for querying drizzle and mysql servers.
|
2
|
+
|
3
|
+
Not really sure where I'm going with this. Ping me if you have input.
|
4
|
+
|
5
|
+
== Synopsis
|
6
|
+
|
7
|
+
=== Normal synchronous query
|
8
|
+
|
9
|
+
irb(main):001:0> require 'rubygems'
|
10
|
+
=> true
|
11
|
+
irb(main):002:0> require 'lib/drizzle'
|
12
|
+
=> true
|
13
|
+
irb(main):003:0> c = Drizzle::Connection.new("127.0.0.1", "root", "password", nil, :DRIZZLE_CON_MYSQL)
|
14
|
+
=> #<Native Pointer address=0x0>
|
15
|
+
irb(main):004:0> r = c.query("select now()")
|
16
|
+
=> #<Drizzle::Result:0x12f4dc8 @rows=[["2009-05-21 07:41:26"]], @columns=[:"now()"], @affected_rows=0, @insert_id=0>
|
17
|
+
irb(main):005:0> r.each {|row| puts row[0] }
|
18
|
+
2009-05-21 07:41:26
|
19
|
+
=> [["2009-05-21 07:41:26"]]
|
20
|
+
irb(main):006:0> r.columns
|
21
|
+
=> [:"now()"]
|
22
|
+
|
23
|
+
=== Async query with EventMachine
|
24
|
+
|
25
|
+
irb(main):001:0> require 'rubygems'
|
26
|
+
=> true
|
27
|
+
irb(main):002:0> require 'lib/drizzle'
|
28
|
+
r=> true
|
29
|
+
irb(main):003:0> require 'eventmachine'
|
30
|
+
=> true
|
31
|
+
irb(main):004:0> c = Drizzle::Connection.new("127.0.0.1", "root", "password", "mysql", :DRIZZLE_CON_MYSQL)
|
32
|
+
=> #<Native Pointer address=0x0>
|
33
|
+
irb(main):005:0> EM.run {
|
34
|
+
irb(main):006:1* c.em_query("show tables") do |result|
|
35
|
+
irb(main):007:2* p result.columns
|
36
|
+
irb(main):008:2> p result.rows
|
37
|
+
irb(main):009:2> end
|
38
|
+
irb(main):010:1> }
|
39
|
+
|
40
|
+
[:Tables_in_mysql]
|
41
|
+
|
42
|
+
[["columns_priv"], ["db"], ["func"], ["help_category"], ["help_keyword"], ["help_relation"], ["help_topic"], ["host"], ["proc"], ["procs_priv"], ["tables_priv"], ["time_zone"], ["time_zone_leap_second"], ["time_zone_name"], ["time_zone_transition"], ["time_zone_transition_type"], ["user"], ["user_info"]]
|
data/Rakefile
ADDED
data/drizzle.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "drizzle-ffi"
|
3
|
+
s.version = "0.0.2"
|
4
|
+
s.date = "2009-08-07"
|
5
|
+
s.authors = ["Jake Douglas"]
|
6
|
+
s.email = "jakecdouglas@gmail.com"
|
7
|
+
s.has_rdoc = false
|
8
|
+
s.add_dependency('ffi')
|
9
|
+
s.add_dependency('bacon')
|
10
|
+
s.summary = "libdrizzle ffi"
|
11
|
+
s.homepage = "http://www.github.com/yakischloba/libdrizzle-ruby-ffi"
|
12
|
+
s.description = "libdrizzle ffi"
|
13
|
+
s.files =
|
14
|
+
["drizzle.gemspec",
|
15
|
+
"README.rdoc",
|
16
|
+
"Rakefile",
|
17
|
+
"lib/drizzle.rb",
|
18
|
+
"lib/drizzle/drizzle.rb",
|
19
|
+
"tests/basic.rb"]
|
20
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
module Drizzle
|
2
|
+
extend FFI::Library
|
3
|
+
ffi_lib "libdrizzle"
|
4
|
+
|
5
|
+
class DrizzleException < RuntimeError; end
|
6
|
+
|
7
|
+
enum :drizzle_return_t, [
|
8
|
+
:DRIZZLE_RETURN_OK,
|
9
|
+
:DRIZZLE_RETURN_IO_WAIT,
|
10
|
+
:DRIZZLE_RETURN_PAUSE,
|
11
|
+
:DRIZZLE_RETURN_ROW_BREAK,
|
12
|
+
:DRIZZLE_RETURN_MEMORY,
|
13
|
+
:DRIZZLE_RETURN_ERRNO,
|
14
|
+
:DRIZZLE_RETURN_INTERNAL_ERROR,
|
15
|
+
:DRIZZLE_RETURN_GETADDRINFO,
|
16
|
+
:DRIZZLE_RETURN_NOT_READY,
|
17
|
+
:DRIZZLE_RETURN_BAD_PACKET_NUMBER,
|
18
|
+
:DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET,
|
19
|
+
:DRIZZLE_RETURN_BAD_PACKET,
|
20
|
+
:DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED,
|
21
|
+
:DRIZZLE_RETURN_UNEXPECTED_DATA,
|
22
|
+
:DRIZZLE_RETURN_NO_SCRAMBLE,
|
23
|
+
:DRIZZLE_RETURN_AUTH_FAILED,
|
24
|
+
:DRIZZLE_RETURN_NULL_SIZE,
|
25
|
+
:DRIZZLE_RETURN_ERROR_CODE,
|
26
|
+
:DRIZZLE_RETURN_TOO_MANY_COLUMNS,
|
27
|
+
:DRIZZLE_RETURN_ROW_END,
|
28
|
+
:DRIZZLE_RETURN_EOF,
|
29
|
+
:DRIZZLE_RETURN_COULD_NOT_CONNECT,
|
30
|
+
:DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS,
|
31
|
+
:DRIZZLE_RETURN_SERVER_GONE,
|
32
|
+
:DRIZZLE_RETURN_MAX
|
33
|
+
]
|
34
|
+
|
35
|
+
enum :drizzle_con_options_t, [
|
36
|
+
:DRIZZLE_CON_NONE, 0,
|
37
|
+
:DRIZZLE_CON_ALLOCATED, (1 << 0),
|
38
|
+
:DRIZZLE_CON_MYSQL, (1 << 1),
|
39
|
+
:DRIZZLE_CON_RAW_PACKET, (1 << 2),
|
40
|
+
:DRIZZLE_CON_RAW_SCRAMBLE, (1 << 3),
|
41
|
+
:DRIZZLE_CON_READY, (1 << 4),
|
42
|
+
:DRIZZLE_CON_NO_RESULT_READ, (1 << 5)
|
43
|
+
]
|
44
|
+
|
45
|
+
enum :drizzle_options_t, [
|
46
|
+
:DRIZZLE_NONE, 0,
|
47
|
+
:DRIZZLE_ALLOCATED, (1 << 0),
|
48
|
+
:DRIZZLE_NON_BLOCKING, (1 << 1)
|
49
|
+
]
|
50
|
+
|
51
|
+
def self.options
|
52
|
+
enum_type(:drizzle_options_t)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.return_codes
|
56
|
+
enum_type(:drizzle_return_t)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.con_options
|
60
|
+
enum_type(:drizzle_con_options_t)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Misc
|
64
|
+
attach_function :version, :drizzle_version, [], :string
|
65
|
+
|
66
|
+
# Drizzle objects
|
67
|
+
attach_function :create, :drizzle_create, [:pointer], :pointer
|
68
|
+
attach_function :free, :drizzle_free, [:pointer], :void
|
69
|
+
attach_function :error, :drizzle_error, [:pointer], :string
|
70
|
+
attach_function :add_options, :drizzle_add_options, [:pointer, :drizzle_options_t], :void
|
71
|
+
callback :event_watch_callback, [:pointer, :short, :pointer], :drizzle_return_t
|
72
|
+
|
73
|
+
attach_function :set_event_watch, :drizzle_set_event_watch, [:pointer, :event_watch_callback, :pointer], :void
|
74
|
+
|
75
|
+
# Connection objects
|
76
|
+
attach_function :con_create, :drizzle_con_create, [:pointer, :pointer], :pointer
|
77
|
+
attach_function :con_free, :drizzle_con_free, [:pointer], :void
|
78
|
+
attach_function :con_set_db, :drizzle_con_set_db, [:pointer, :string], :void
|
79
|
+
attach_function :con_set_auth, :drizzle_con_set_auth, [:pointer, :string, :string], :void
|
80
|
+
attach_function :con_add_options, :drizzle_con_add_options, [:pointer, :drizzle_con_options_t], :void
|
81
|
+
attach_function :con_status, :drizzle_con_status, [:pointer], :int
|
82
|
+
attach_function :con_fd, :drizzle_con_fd, [:pointer], :int
|
83
|
+
attach_function :con_clone, :drizzle_con_clone, [:pointer, :pointer, :pointer], :pointer
|
84
|
+
attach_function :con_set_revents, :drizzle_con_set_revents, [:pointer, :short], :void
|
85
|
+
|
86
|
+
# Querying
|
87
|
+
attach_function :query_str, :drizzle_query_str, [:pointer, :pointer, :string, :pointer], :pointer
|
88
|
+
|
89
|
+
# Results
|
90
|
+
attach_function :result_create, :drizzle_result_create, [:pointer, :pointer], :pointer
|
91
|
+
attach_function :result_buffer, :drizzle_result_buffer, [:pointer], :int
|
92
|
+
attach_function :result_free, :drizzle_result_free, [:pointer], :drizzle_return_t
|
93
|
+
attach_function :result_affected_rows, :drizzle_result_affected_rows, [:pointer], :uint64
|
94
|
+
attach_function :result_insert_id, :drizzle_result_insert_id, [:pointer], :uint64
|
95
|
+
attach_function :row_next, :drizzle_row_next, [:pointer], :pointer
|
96
|
+
attach_function :result_read, :drizzle_result_read, [:pointer, :pointer, :pointer], :pointer
|
97
|
+
|
98
|
+
# Columns
|
99
|
+
attach_function :column_next, :drizzle_column_next, [:pointer], :pointer
|
100
|
+
attach_function :column_name, :drizzle_column_name, [:pointer], :string
|
101
|
+
|
102
|
+
class Result
|
103
|
+
attr_reader :columns, :affected_rows, :insert_id, :rows
|
104
|
+
|
105
|
+
def initialize(ptr)
|
106
|
+
@columns, @rows = [], []
|
107
|
+
|
108
|
+
@insert_id = Drizzle.result_insert_id(ptr)
|
109
|
+
@affected_rows = Drizzle.result_affected_rows(ptr)
|
110
|
+
|
111
|
+
# Get columns
|
112
|
+
until (column = Drizzle.column_next(ptr)).null?
|
113
|
+
@columns << Drizzle.column_name(column).to_sym
|
114
|
+
end
|
115
|
+
|
116
|
+
# Get rows
|
117
|
+
until (row = Drizzle.row_next(ptr)).null?
|
118
|
+
@rows << row.get_array_of_string(0, @columns.size)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Free the underlying buffers since we just copied it all to Ruby
|
122
|
+
Drizzle.result_free(ptr)
|
123
|
+
end
|
124
|
+
|
125
|
+
def each
|
126
|
+
@rows.each do |row|
|
127
|
+
yield row if block_given?
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Drizzleptr < FFI::AutoPointer
|
133
|
+
def self.release(ptr)
|
134
|
+
Drizzle.free(ptr)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Connptr < FFI::AutoPointer
|
139
|
+
def self.release(ptr)
|
140
|
+
Drizzle.conn_free(ptr)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Connection
|
145
|
+
attr_accessor :host, :user, :pass, :db, :opts, :fd
|
146
|
+
|
147
|
+
def initialize(host, user, pass, db=nil, opts=[], drizzle=nil)
|
148
|
+
opts = opts.is_a?(Array) ? opts : [opts]
|
149
|
+
@host, @user, @pass, @db, @opts = host, user, pass, db, opts
|
150
|
+
@from_pool = true if drizzle
|
151
|
+
@drizzle = drizzle || Drizzleptr.new(Drizzle.create(nil))
|
152
|
+
@conn = Connptr.new(Drizzle.con_create(@drizzle, nil))
|
153
|
+
Drizzle.con_add_options(@conn, opts.inject(0){|i,o| i | Drizzle.enum_value(o)} | Drizzle.enum_value(:DRIZZLE_CON_NO_RESULT_READ))
|
154
|
+
Drizzle.con_set_auth(@conn, @user, @pass)
|
155
|
+
Drizzle.con_set_db(@conn, @db) if @db
|
156
|
+
@retptr = FFI::MemoryPointer.new(:int)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Indicates whether or not this connection was created using a drizzle_st object from somewhere else.
|
160
|
+
def from_pool?
|
161
|
+
@from_pool
|
162
|
+
end
|
163
|
+
|
164
|
+
# This executes a normal synchronous query. We simply call the async methods together.
|
165
|
+
def query(query, proc=nil, &blk)
|
166
|
+
proc ||= blk
|
167
|
+
async_query(query, proc)
|
168
|
+
async_result
|
169
|
+
end
|
170
|
+
|
171
|
+
# Sends off a query to the server. The return value is the file descriptor number of the socket used for this connection, for monitoring with an event loop etc.
|
172
|
+
def async_query(query, proc=nil, &blk)
|
173
|
+
proc ||= blk
|
174
|
+
Drizzle.query_str(@conn, nil, query, @retptr)
|
175
|
+
# Make sure it was successful
|
176
|
+
check_error
|
177
|
+
@callback = proc
|
178
|
+
# return fd to caller
|
179
|
+
@fd ||= Drizzle.con_fd(@conn)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Do a blocking read for the result of an outstanding query. This results the Result object as well as fires a callback associated with it.
|
183
|
+
def async_result
|
184
|
+
# Do a partial blocking read into the the packet struct
|
185
|
+
result = Drizzle.result_read(@conn, nil, @retptr)
|
186
|
+
|
187
|
+
# See if the read was successful
|
188
|
+
check_error
|
189
|
+
|
190
|
+
# Buffer the result and check
|
191
|
+
ret = Drizzle.result_buffer(result)
|
192
|
+
if Drizzle.return_codes[ret] != :DRIZZLE_RETURN_OK
|
193
|
+
# Free the result struct if we fail.
|
194
|
+
Drizzle.result_free(result)
|
195
|
+
raise DrizzleException.new("Query failed: #{Drizzle.error(@drizzle)}")
|
196
|
+
end
|
197
|
+
|
198
|
+
# Fire and return
|
199
|
+
r = Result.new(result)
|
200
|
+
@callback.call(r) if @callback
|
201
|
+
@callback = nil
|
202
|
+
r
|
203
|
+
end
|
204
|
+
|
205
|
+
def em_query(query, proc=nil, &blk)
|
206
|
+
proc ||= blk
|
207
|
+
fd = async_query(query, proc)
|
208
|
+
EM.watch(fd, EMHandler, self) {|c| c.notify_readable = true}
|
209
|
+
end
|
210
|
+
|
211
|
+
def check_error
|
212
|
+
if Drizzle.return_codes[@retptr.get_int(0)] != :DRIZZLE_RETURN_OK
|
213
|
+
raise DrizzleException.new("Query failed: #{Drizzle.error(@drizzle)}")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
module EMHandler
|
220
|
+
def initialize(conn)
|
221
|
+
@conn = conn
|
222
|
+
end
|
223
|
+
def notify_readable
|
224
|
+
detach
|
225
|
+
@conn.async_result
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
data/lib/drizzle.rb
ADDED
data/tests/basic.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'set'
|
2
|
+
begin
|
3
|
+
require 'eventmachine'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
HOST = "127.0.0.1"
|
8
|
+
USER = "root"
|
9
|
+
PASS = "password"
|
10
|
+
|
11
|
+
describe "Basic libdrizzle operation" do
|
12
|
+
|
13
|
+
it "perform a simple synchronous query on a MySQL server" do
|
14
|
+
c = Drizzle::Connection.new(HOST, USER, PASS, "information_schema", :DRIZZLE_CON_MYSQL)
|
15
|
+
schemas, tables = Set.new, Set.new
|
16
|
+
result = c.query("SELECT table_schema,table_name FROM tables")
|
17
|
+
result.class.should.equal Drizzle::Result
|
18
|
+
result.affected_rows.should.equal 0
|
19
|
+
result.insert_id.should.equal 0
|
20
|
+
result.columns.size.should.equal 2
|
21
|
+
result.columns.should.include :table_schema
|
22
|
+
result.columns.should.include :table_name
|
23
|
+
|
24
|
+
result.each do |row|
|
25
|
+
schemas << row[0]
|
26
|
+
tables << row[1]
|
27
|
+
end
|
28
|
+
|
29
|
+
schemas.should.include "information_schema"
|
30
|
+
tables.should.include "COLUMNS"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "send and receive a query asynchronously" do
|
34
|
+
c = Drizzle::Connection.new(HOST, USER, PASS, "information_schema", :DRIZZLE_CON_MYSQL)
|
35
|
+
fd = c.async_query("SELECT table_schema,table_name FROM tables")
|
36
|
+
|
37
|
+
schemas, tables = Set.new, Set.new
|
38
|
+
result = c.async_result
|
39
|
+
result.class.should.equal Drizzle::Result
|
40
|
+
result.affected_rows.should.equal 0
|
41
|
+
result.insert_id.should.equal 0
|
42
|
+
|
43
|
+
result.columns.size.should.equal 2
|
44
|
+
result.columns.should.include :table_schema
|
45
|
+
result.columns.should.include :table_name
|
46
|
+
|
47
|
+
result.each do |row|
|
48
|
+
schemas << row[0]
|
49
|
+
tables << row[1]
|
50
|
+
end
|
51
|
+
|
52
|
+
schemas.should.include "information_schema"
|
53
|
+
tables.should.include "COLUMNS"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "send and receive a query asynchronously using a callback" do
|
57
|
+
c = Drizzle::Connection.new(HOST, USER, PASS, "information_schema", :DRIZZLE_CON_MYSQL)
|
58
|
+
schemas, tables = Set.new, Set.new
|
59
|
+
columns = []
|
60
|
+
fd = c.async_query("SELECT table_schema,table_name FROM tables") do |result|
|
61
|
+
result.columns.each {|col| columns << col}
|
62
|
+
result.each do |row|
|
63
|
+
schemas << row[0]
|
64
|
+
tables << row[1]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
schemas.should.be.empty
|
69
|
+
tables.should.be.empty
|
70
|
+
columns.should.be.empty
|
71
|
+
|
72
|
+
c.async_result
|
73
|
+
|
74
|
+
schemas.should.include "information_schema"
|
75
|
+
tables.should.include "COLUMNS"
|
76
|
+
columns.size.should.equal 2
|
77
|
+
columns.should.include :table_schema
|
78
|
+
columns.should.include :table_name
|
79
|
+
end
|
80
|
+
|
81
|
+
if defined?(EventMachine)
|
82
|
+
it "perform an async query with evented receive using EventMachine" do
|
83
|
+
schemas, tables = Set.new, Set.new
|
84
|
+
columns = []
|
85
|
+
EM.run {
|
86
|
+
c = Drizzle::Connection.new(HOST, USER, PASS, "information_schema", :DRIZZLE_CON_MYSQL)
|
87
|
+
c.em_query("SELECT table_schema,table_name FROM tables") do |result|
|
88
|
+
result.columns.each {|col| columns << col}
|
89
|
+
result.each do |row|
|
90
|
+
schemas << row[0]
|
91
|
+
tables << row[1]
|
92
|
+
end
|
93
|
+
EM.stop
|
94
|
+
end
|
95
|
+
}
|
96
|
+
schemas.should.include "information_schema"
|
97
|
+
tables.should.include "COLUMNS"
|
98
|
+
columns.size.should.equal 2
|
99
|
+
columns.should.include :table_schema
|
100
|
+
columns.should.include :table_name
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yakischloba-drizzle-ffi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jake Douglas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-07 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ffi
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bacon
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: libdrizzle ffi
|
36
|
+
email: jakecdouglas@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- drizzle.gemspec
|
45
|
+
- README.rdoc
|
46
|
+
- Rakefile
|
47
|
+
- lib/drizzle.rb
|
48
|
+
- lib/drizzle/drizzle.rb
|
49
|
+
- tests/basic.rb
|
50
|
+
has_rdoc: false
|
51
|
+
homepage: http://www.github.com/yakischloba/libdrizzle-ruby-ffi
|
52
|
+
licenses:
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 2
|
76
|
+
summary: libdrizzle ffi
|
77
|
+
test_files: []
|
78
|
+
|