module ICU::Lib

Public Class Methods

check_error() { |ptr| ... } click to toggle source
# File lib/ffi-icu/lib.rb, line 121
def self.check_error
  ptr = FFI::MemoryPointer.new(:int)
  ret = yield(ptr)
  error_code = ptr.read_int

  if error_code > 0
    name = Lib.u_errorName error_code
    if name == "U_BUFFER_OVERFLOW_ERROR"
      raise BufferOverflowError
    else
      raise Error, name
    end
  elsif error_code < 0
    $stderr.puts "ffi-icu: #{Lib.u_errorName error_code}" if $DEBUG || $VERBOSE
  end

  ret
end
cldr_version() click to toggle source
# File lib/ffi-icu/lib.rb, line 183
def self.cldr_version
  @cldr_version ||= VersionInfo.new.tap do |version|
    check_error { |status| ulocdata_getCLDRVersion(version, status) }
  end
end
enum_ptr_to_array(enum_ptr) click to toggle source
# File lib/ffi-icu/lib.rb, line 140
def self.enum_ptr_to_array(enum_ptr)
  length = check_error do |status|
    uenum_count(enum_ptr, status)
  end

  len = FFI::MemoryPointer.new(:int)

  (0...length).map do |idx|
    check_error { |st| uenum_next(enum_ptr, len, st) }
  end
end
figure_suffix(version) click to toggle source
# File lib/ffi-icu/lib.rb, line 89
def self.figure_suffix(version)
  # For some reason libicu prepends its exported functions with version information,
  # which differs across all platforms.  Some examples:
  #
  # OSX:
  #   u_errorName
  #
  # CentOS 5
  #   u_errorName_3_6
  #
  # Fedora 14 and Windows (using mingw)
  #   u_errorName_44
  #
  # So we need to figure out which one it is.

  # Here are the possible suffixes
  suffixes = [""]
  if version
    suffixes << "_#{version}" << "_#{version[0].chr}_#{version[1].chr}" << "_#{version.split('.')[0]}"
  end

  # Try to find the u_errorName function using the possible suffixes
  suffixes.find do |suffix|
    function_name = "u_errorName#{suffix}"
    function_names(function_name, nil).find do |fname|
      ffi_libraries.find do |lib|
        lib.find_function(fname)
      end
    end
  end
end
find_lib(lib) click to toggle source
# File lib/ffi-icu/lib.rb, line 29
def self.find_lib(lib)
  Dir.glob(search_paths.map { |path|
    File.expand_path(File.join(path, lib))
  }).first
end
icu_version(libs) click to toggle source
# File lib/ffi-icu/lib.rb, line 72
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

  # Note this may return nil, like on OSX
  version
end
load_icu() click to toggle source
# File lib/ffi-icu/lib.rb, line 35
def self.load_icu
  # First find the library
  lib_names = case ICU.platform
              when :bsd
                [find_lib("libicui18n.#{FFI::Platform::LIBSUFFIX}.??"),
                 find_lib("libicutu.#{FFI::Platform::LIBSUFFIX}.??")]
              when :osx
                # See https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-release-notes (62986286)
                if Gem::Version.new(`sw_vers -productVersion`) >= Gem::Version.new('11')
                  ["libicucore.#{FFI::Platform::LIBSUFFIX}"]
                else
                  [find_lib("libicucore.#{FFI::Platform::LIBSUFFIX}")]
                end
              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

  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 welcome, or you can add the containing directory yourself: #{self}.search_paths << '/path/to/lib'"
  end

  # 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

  icu_version(libs)
end
not_available(func_name) click to toggle source
# File lib/ffi-icu/lib.rb, line 152
def self.not_available(func_name)
  self.class.send :define_method, func_name do |*args|
    raise Error, "#{func_name} not available on platform #{ICU.platform.inspect}"
  end
end
search_paths() click to toggle source
# File lib/ffi-icu/lib.rb, line 11
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
      [
        '/usr/local/{lib64,lib}',
        '/opt/local/{lib64,lib}',
        '/usr/{lib64,lib}',
        '/usr/lib/x86_64-linux-gnu', # for Debian Multiarch http://wiki.debian.org/Multiarch
        '/usr/lib/i386-linux-gnu',   # for Debian Multiarch
      ]
    end
  end
end
version() click to toggle source
# File lib/ffi-icu/lib.rb, line 189
def self.version
  @version ||= VersionInfo.new.tap { |version| u_getVersion(version) }
end