snappy_ffi 0.1.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/lib/snappy_ffi.rb +137 -0
- metadata +73 -0
data/lib/snappy_ffi.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi'
|
3
|
+
|
4
|
+
#:nodoc
|
5
|
+
module Snappy; end
|
6
|
+
|
7
|
+
module Snappy::FFI
|
8
|
+
Version = "0.1.2"
|
9
|
+
|
10
|
+
#:nodoc
|
11
|
+
module Snappy::FFI::Lib
|
12
|
+
extend FFI::Library
|
13
|
+
|
14
|
+
# Find the library in the normal places, or the file specified by SNAPPY_LIB if set
|
15
|
+
paths =
|
16
|
+
Array(
|
17
|
+
ENV['SNAPPY_LIB'] ||
|
18
|
+
Dir['/{opt,usr}/{,local/}lib{,64}/libsnappy.{dylib,so*}']
|
19
|
+
)
|
20
|
+
begin
|
21
|
+
ffi_lib(*paths)
|
22
|
+
rescue LoadError
|
23
|
+
raise LoadError,
|
24
|
+
"didn't find libsnappy on your system. " +
|
25
|
+
"Please install (http://code.google.com/p/snappy/)"
|
26
|
+
end
|
27
|
+
|
28
|
+
# What should we look for?
|
29
|
+
ExportSets = [
|
30
|
+
{
|
31
|
+
:description => "g++ 4",
|
32
|
+
:max_compressed_length => '_ZN6snappy19MaxCompressedLengthEm',
|
33
|
+
:get_uncompressed_length => '_ZN6snappy21GetUncompressedLengthEPKcmPm',
|
34
|
+
:raw_compress => '_ZN6snappy11RawCompressEPKcmPcPm',
|
35
|
+
:raw_uncompress => '_ZN6snappy13RawUncompressEPKcmPc'
|
36
|
+
}
|
37
|
+
]
|
38
|
+
|
39
|
+
# Let you add extra entries to this list without hacking at this file
|
40
|
+
if Snappy::FFI.const_defined?(:LocalExportSet)
|
41
|
+
ExportSets << Snappy::FFI::LocalExportSet
|
42
|
+
end
|
43
|
+
|
44
|
+
# Walk FunctionSets until we find something that works
|
45
|
+
libsnappy = ffi_libraries.first
|
46
|
+
ChosenExportSet = ExportSets.find { |set|
|
47
|
+
libsnappy.find_function(set[:max_compressed_length])
|
48
|
+
}
|
49
|
+
|
50
|
+
if ChosenExportSet.nil?
|
51
|
+
raise LoadError, "snappy_ffi couldn't identify your libsnappy's function exports. " +
|
52
|
+
"You'll need to determine what these functions are called, then tell Snappy::FFI. " +
|
53
|
+
"Please see http://github.com/delta407/snappy-ruby/ for more information."
|
54
|
+
end
|
55
|
+
|
56
|
+
attach_function :max_compressed_length, ChosenExportSet[:max_compressed_length],
|
57
|
+
[:size_t], :size_t
|
58
|
+
attach_function :get_uncompressed_length, ChosenExportSet[:get_uncompressed_length],
|
59
|
+
[:buffer_in, :size_t, :pointer], :bool
|
60
|
+
attach_function :raw_compress, ChosenExportSet[:raw_compress],
|
61
|
+
[:buffer_in, :size_t, :buffer_out, :pointer], :void
|
62
|
+
attach_function :raw_uncompress, ChosenExportSet[:raw_uncompress],
|
63
|
+
[:buffer_in, :size_t, :buffer_out], :bool
|
64
|
+
|
65
|
+
# We deal in *size_t quite a lot
|
66
|
+
# Make it a struct, so it's easy to convert from pointers to values and back
|
67
|
+
class SizeT < FFI::Struct
|
68
|
+
layout :value, :size_t
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Compresses a string, returning the compressed value
|
73
|
+
def self.compress(input)
|
74
|
+
# Set up our input
|
75
|
+
input = input.to_s
|
76
|
+
input_size = input.bytesize rescue input.size
|
77
|
+
|
78
|
+
# Make a place to record our compressed size
|
79
|
+
output_size = Lib::SizeT.new
|
80
|
+
|
81
|
+
# Make a buffer big enough to hold the worst case
|
82
|
+
max = Lib.max_compressed_length(input_size)
|
83
|
+
FFI::MemoryPointer.new(max) { |output_buffer|
|
84
|
+
# Compress
|
85
|
+
Lib.raw_compress(input, input_size, output_buffer, output_size.pointer)
|
86
|
+
|
87
|
+
# Get our string
|
88
|
+
output = output_buffer.get_bytes(0, output_size[:value])
|
89
|
+
|
90
|
+
# Return, copying taint as needed
|
91
|
+
if input.tainted?
|
92
|
+
return output.taint
|
93
|
+
else
|
94
|
+
return output
|
95
|
+
end
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
# Decompresses a string, throwing ArgumentError if it's somehow corrupt
|
100
|
+
def self.uncompress(input)
|
101
|
+
# Set up our input
|
102
|
+
input = input.to_s
|
103
|
+
input_size = input.bytesize rescue input.size
|
104
|
+
|
105
|
+
# Make a place to record our uncompressed size
|
106
|
+
output_size = Lib::SizeT.new
|
107
|
+
|
108
|
+
# See how big our output will be
|
109
|
+
if !Lib.get_uncompressed_length(input, input_size, output_size.pointer)
|
110
|
+
# failure!
|
111
|
+
raise ArgumentError, "invalid compressed data"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Make the buffer
|
115
|
+
FFI::MemoryPointer.new(output_size[:value]) { |output_buffer|
|
116
|
+
# Decompress
|
117
|
+
if !Lib.raw_uncompress(input, input_size, output_buffer)
|
118
|
+
raise ArgumentError, "invalid compressed data"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Get our string
|
122
|
+
output = output_buffer.get_bytes(0, output_size[:value])
|
123
|
+
|
124
|
+
# Return, copying taint as needed
|
125
|
+
if input.tainted?
|
126
|
+
return output.taint
|
127
|
+
else
|
128
|
+
return output
|
129
|
+
end
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
module Snappy
|
135
|
+
def self.compress(string); Snappy::FFI.compress(string) end
|
136
|
+
def self.uncompress(string); Snappy::FFI.uncompress(string) end
|
137
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snappy_ffi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Will Glynn
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-03-24 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: ffi
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: FFI extension to to bring the Snappy compression library to Ruby. libsnappy must be installed.
|
33
|
+
email: will@willglynn.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files: []
|
39
|
+
|
40
|
+
files:
|
41
|
+
- lib/snappy_ffi.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/delta407/snappy-ruby
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
requirements:
|
66
|
+
- libsnappy
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.3.6
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: FFI extension for libsnappy.
|
72
|
+
test_files: []
|
73
|
+
|