-- -- Copyright © 2015 Christian Marie -- -- The code in this file, and the program it is a part of, is -- made available to you by its authors as open source software: -- you can redistribute it and/or modify it under the terms of -- the 3-clause BSD licence. -- {-# LANGUAGE ForeignFunctionInterface #-} -- | Provides a double metaphone algorithm extracted from the perl library -- Text-DoubleMetaphone-0.07. module Language.Phonetic.DoubleMetaphone ( -- * Types doubleMetaphoneBounded, doubleMetaphone ) where import Foreign.C.String (CString) import Foreign.C.Types (CInt (..)) import Foreign.Marshal.Array (allocaArray, peekArray) import Foreign.Ptr (Ptr) import Data.ByteString (ByteString, useAsCString) import Data.ByteString.Unsafe (unsafePackMallocCString) import System.IO.Unsafe (unsafePerformIO) -- | Thin wrapper around a C function, returns two metaphone representations. doubleMetaphoneBounded :: Int -- ^ Number of characters to stop computing the longest result at. -> ByteString -- ^ The input string, should be Latin-1 or Char7 encoded. -> (ByteString, ByteString) doubleMetaphoneBounded max_len input = unsafePerformIO $ useAsCString input $ \c_str -> allocaArray 2 $ \results_p -> do c_double_metaphone c_str results_p (fromIntegral max_len) rs <- peekArray 2 results_p >>= traverse unsafePackMallocCString case rs of [r1, r2] -> return (r1, r2) _ -> error "doubleMetaphone: |array| != 2, impossible?" -- | Thin wrapper around a C function, returns two metaphone representations. -- -- The output will be bounded at somewhere around 2 ^ (word size - 1) doubleMetaphone :: ByteString -- ^ The input string, should be Latin-1 or Char7 encoded. -> (ByteString, ByteString) doubleMetaphone = doubleMetaphoneBounded maxBound foreign import ccall unsafe "double-metaphones.h DoubleMetaphone" c_double_metaphone :: CString -> Ptr CString -> CInt -> IO ()