lib/ffi-icu/lib.rb in ffi-icu-0.0.7 vs lib/ffi-icu/lib.rb in ffi-icu-0.0.8
- old
+ new
@@ -6,64 +6,73 @@
end
module Lib
extend FFI::Library
- VERSIONS = {
- "48" => "_48",
- "46" => "_46",
- "45" => "_45",
- "44" => "_44",
- "42" => "_4_2",
- }
-
- # FIXME: this is incredibly ugly, figure out some better way
- def self.find_icu
- suffix = ''
-
- # let the user tell us where the lib is
- if ENV['FFI_ICU_LIB']
- libs = ENV['FFI_ICU_LIB'].split(",")
- ffi_lib(*libs)
-
- if ENV['FFI_ICU_VERSION_SUFFIX']
- return ENV['FFI_ICU_VERSION_SUFFIX']
- elsif num = libs.first[/\d+$/]
- return num.split(//).join("_")
+ def self.search_paths
+ @search_paths ||= begin
+ if ENV['FFI_ICU_LIB']
+ [ ENV['FFI_ICU_LIB'] ]
+ elsif FFI::Platform::IS_WINDOWS
+ ENV['PATH'].split(File::PATH_SEPARATOR)
else
- return suffix
+ [ '/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}' ]
end
end
+ end
- libs = nil
- versions = VERSIONS.keys
+ def self.find_lib(lib)
+ Dir.glob(search_paths.map { |path|
+ File.expand_path(File.join(path, lib))
+ }).first
+ end
- # ok, try to find it
- case ICU.platform
- when :osx
- ffi_lib "icucore"
- when :linux
- libs = ffi_lib versions.map { |v| "libicui18n.so.#{v}" },
- versions.map { |v| "libicutu.so.#{v}" }
+ def self.load_icu
+ # First find the library
+ lib_names = case ICU.platform
+ when :osx
+ [find_lib("libicucore.#{FFI::Platform::LIBSUFFIX}")]
+ when :linux
+ [find_lib("libicui18n.#{FFI::Platform::LIBSUFFIX}.??"),
+ find_lib("libicutu.#{FFI::Platform::LIBSUFFIX}.??")]
+ when :windows
+ [find_lib("icuuc??.#{FFI::Platform::LIBSUFFIX}"),
+ find_lib("icuin??.#{FFI::Platform::LIBSUFFIX}")]
+ end
- when :windows
- libs = ffi_lib versions.map { |v| "icuin#{v}.dll" }
- else
- raise LoadError
+ lib_names.compact! if lib_names
+
+ if not lib_names or lib_names.length == 0
+ raise LoadError, "Could not find ICU on #{ICU.platform.inspect}, patches appreciated!"
end
- if libs
- lib_name = libs.first.name
- version = VERSIONS.find { |object, func| lib_name =~ /#{object}(\.dll)?$/ }
+ # And now try to load the library
+ begin
+ libs = ffi_lib(*lib_names)
+ rescue LoadError => ex
+ raise LoadError, "no idea how to load ICU on #{ICU.platform.inspect}, patches appreciated! (#{ex.message})"
+ end
- version or raise "unable to find suffix in #{lib_name}"
- suffix = version.last
+ # And last figure out the version we just loaded
+ icu_version(libs)
+ end
+
+ def self.icu_version(libs)
+ version = nil
+
+ libs.find do |lib|
+ # Get the version - sure would be nice if libicu exported this in a function
+ # we could just call cause this is super fugly!
+ match = lib.name.match(/(\d\d)\.#{FFI::Platform::LIBSUFFIX}/) ||
+ lib.name.match(/#{FFI::Platform::LIBSUFFIX}\.(\d\d)/)
+ if match
+ version = match[1]
+ end
end
- suffix
- rescue LoadError => ex
- raise LoadError, "no idea how to load ICU on #{ICU.platform.inspect}, patches appreciated! (#{ex.message})"
+ # Note this may return nil, like on OSX
+ version
end
def self.check_error
ptr = FFI::MemoryPointer.new(:int)
ret = yield(ptr)
@@ -99,13 +108,13 @@
self.class.send :define_method, func_name do |*args|
raise Error, "#{func_name} not available on platform #{ICU.platform.inspect}"
end
end
+ version = load_icu
+ suffix = version ? "_#{version}" : ""
- suffix = find_icu()
-
attach_function :u_errorName, "u_errorName#{suffix}", [:int], :string
attach_function :uenum_count, "uenum_count#{suffix}", [:pointer, :pointer], :int
attach_function :uenum_close, "uenum_close#{suffix}", [:pointer], :void
attach_function :uenum_next, "uenum_next#{suffix}", [:pointer, :pointer, :pointer], :string
attach_function :u_charsToUChars, "u_charsToUChars#{suffix}", [:string, :pointer, :int32_t], :void
@@ -188,11 +197,11 @@
:nfkd, 3,
:nfc, 4,
:default, 4,
:nfkc, 5,
:fcd, 6
- ]
+ ]
attach_function :unorm_normalize, "unorm_normalize#{suffix}", [:pointer, :int32_t, :normalization_mode, :int32_t, :pointer, :int32_t, :pointer], :int32_t
#
# Text Boundary Analysis
@@ -209,10 +218,10 @@
:letter_limit, 300,
:kana, 300,
:kana_limit, 400,
:ideo, 400,
:ideo_limit, 400
- ]
+ ]
attach_function :ubrk_countAvailable, "ubrk_countAvailable#{suffix}", [], :int32_t
attach_function :ubrk_getAvailable, "ubrk_getAvailable#{suffix}", [:int32_t], :string
attach_function :ubrk_open, "ubrk_open#{suffix}", [:iterator_type, :string, :pointer, :int32_t, :pointer], :pointer