/
metadata_processor.cr
84 lines (72 loc) · 2.42 KB
/
metadata_processor.cr
1
2
3
4
5
6
7
8
9
10
11
12
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
#
# extractor.cr - Crystal bindings for libextractor
#
# Copyright (c) 2020 - Hal Brodigan (postmodern.mod3 at gmail.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
module Extractor
module MetadataProcessor
alias Char = LibC::Char
alias SizeT = LibC::SizeT
alias MetaType = LibExtractor::MetaType
alias MetaFormat = LibExtractor::MetaFormat
alias MetaData = String | Bytes
alias Callback = (String, MetaType, MetaFormat, String, MetaData) ->
class Abort < RuntimeError
end
# Mapping of plugin paths to names
PLUGIN_NAMES = Hash(String, String).new do |plugin_names,plugin|
libname = File.basename(plugin,File.extname(plugin))
plugin_names[plugin] = libname.sub("libextractor_","")
end
CALLBACK = ->(cls : Void *, plugin : Char *, type : MetaType, format : MetaFormat, mime_type : Char *, data : Char *, size : SizeT) {
callback = unbox(cls)
plugin_name = PLUGIN_NAMES[String.new(plugin)]
mime_type = String.new(mime_type)
value = case format
when MetaFormat::UTF8
String.new(Bytes.new(data,size - 1),"UTF-8")
when MetaFormat::C_STRING
String.new(Bytes.new(data,size - 1),"ASCII")
else
Bytes.new(data,size)
end
begin
callback.call(plugin_name,type,format,mime_type,value)
0
rescue Abort
1
end
}
#
# Wraps a closure in a box.
#
def self.box(closure : Callback) : Pointer(Void)
boxed_closure = Box.box(closure)
end
#
# Unwraps a boxed closure.
#
def self.unbox(cls : Void *) : Callback
Box(Callback).unbox(cls)
end
#
# Returns a proc literal for the `call` method.
#
def self.to_unsafe
CALLBACK
end
end
end