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.
Files changed (2) hide show
  1. data/lib/snappy_ffi.rb +137 -0
  2. 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
+