HsHyperEstraier-0.2: Text/HyperEstraier/Condition.hs
{-# OPTIONS_GHC -optc-D__GLASGOW_HASKELL__=606 #-}
{-# INCLUDE "estraier.h" #-}
{-# LINE 1 "Text/HyperEstraier/Condition.hsc" #-}
{-# LINE 2 "Text/HyperEstraier/Condition.hsc" #-}
-- #prune
-- |An interface to functions to manipulate search conditions.
module Text.HyperEstraier.Condition
( -- * Types
Condition
, ESTCOND -- private
, CondOption(..)
, SearchSpeed(..)
, SyntaxType(..)
, Eclipse(..)
, withCondPtr -- private
-- * Manipulating conditions
, newCondition
, setPhrase
, addAttrCond
, setOrder
, setMax
, setSkip
, setOptions
, setAuxiliary
, setEclipse
, setDistinct
, setMetaSearchMask
)
where
import Control.Exception
import Data.Bits
import Foreign.C.String
import Foreign.ForeignPtr
import Foreign.Ptr
import Text.HyperEstraier.Utils
-- |'Condition' is an opaque object representing a search condition.
newtype Condition = Condition (ForeignPtr ESTCOND)
data ESTCOND
-- |'CondOption' is an option to the search condition.
data CondOption
= Speed SearchSpeed -- ^ Choose a @'SearchSpeed'@.
| OmitTFIDF -- ^ Omit calculating TF-IDF weight.
| Syntax SyntaxType -- ^ Choose a @'SyntaxType'@.
deriving (Eq, Show)
-- |'SearchSpeed' is an option to the search condition.
data SearchSpeed
= Slow -- ^ Search for all N-gram keys.
| Normal -- ^ Search for N-gram keys alternately.
| Fast -- ^ Search for N-gram keys by skipping 2\/3 of them.
| EvenFaster -- ^ Search for N-gram keys by skipping 3\/4 of them.
deriving (Eq, Show)
-- |'SyntaxType' is an option to the search condition.
data SyntaxType
= Simplified -- ^ Interpret the condition phrase as the
-- simplified syntax. See the user's guide of the
-- HyperEstraier for explanation about the
-- simplified syntax.
| Rough -- ^ Interpret the condition phrase as the rough
-- syntax. See the user's guide for details.
| Union -- ^ Interpret the condition phrase as the union
-- syntax. See the user's guide for details.
| Intersection -- ^ Interpret the condition phrase as the
-- intersection syntax. See the user's guide for
-- details.
deriving (Eq, Show)
marshalCondOption :: CondOption -> Int
marshalCondOption (Speed Slow ) = (1)
{-# LINE 76 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Speed Normal ) = (2)
{-# LINE 77 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Speed Fast ) = (4)
{-# LINE 78 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Speed EvenFaster ) = (8)
{-# LINE 79 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption OmitTFIDF = (16)
{-# LINE 80 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Syntax Simplified ) = (1024)
{-# LINE 81 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Syntax Rough ) = (2048)
{-# LINE 82 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Syntax Union ) = (32768)
{-# LINE 83 "Text/HyperEstraier/Condition.hsc" #-}
marshalCondOption (Syntax Intersection) = (65536)
{-# LINE 84 "Text/HyperEstraier/Condition.hsc" #-}
-- |'Eclipse' represents how to hide documents from the search
-- result by their similarity.
data Eclipse
= Threshold Double -- ^ Threshold to cause eclipse to
-- documents. @'Threshold' x@ must satisfy
-- @0.0 <= x <= 1.0@.
| ThresholdWithURL Double -- ^ This is similar to @'Threshold'@
-- but this specifies that the document
-- URI is also used to calculate the
-- similarity.
| SameServer -- ^ Cause eclipse to the documents on the same
-- server.
| SameDirectory -- ^ Cause eclipse to the documents in the same
-- directory.
| SameFile -- ^ Cause eclipse to the documents whose file
-- name is the same.
deriving (Eq, Show)
marshalEclipse :: Eclipse -> Double
marshalEclipse (Threshold thr) = assertThreshold thr
marshalEclipse (ThresholdWithURL thr) = assertThreshold thr + (10)
{-# LINE 107 "Text/HyperEstraier/Condition.hsc" #-}
marshalEclipse SameServer = (100)
{-# LINE 108 "Text/HyperEstraier/Condition.hsc" #-}
marshalEclipse SameDirectory = (101)
{-# LINE 109 "Text/HyperEstraier/Condition.hsc" #-}
marshalEclipse SameFile = (102)
{-# LINE 110 "Text/HyperEstraier/Condition.hsc" #-}
assertThreshold :: Double -> Double
assertThreshold thr = assert (thr >= 0.0 && thr <= 1.0) thr
foreign import ccall unsafe "estraier.h est_cond_new"
_new :: IO (Ptr ESTCOND)
foreign import ccall unsafe "estraier.h &est_cond_delete"
_delete :: FunPtr (Ptr ESTCOND -> IO ())
foreign import ccall unsafe "estraier.h est_cond_set_phrase"
_set_phrase :: Ptr ESTCOND -> CString -> IO ()
foreign import ccall unsafe "estraier.h est_cond_add_attr"
_add_attr :: Ptr ESTCOND -> CString -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_order"
_set_order :: Ptr ESTCOND -> CString -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_max"
_set_max :: Ptr ESTCOND -> Int -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_skip"
_set_skip :: Ptr ESTCOND -> Int -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_options"
_set_options :: Ptr ESTCOND -> Int -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_auxiliary"
_set_auxiliary :: Ptr ESTCOND -> Int -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_eclipse"
_set_eclipse :: Ptr ESTCOND -> Double -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_distinct"
_set_distinct :: Ptr ESTCOND -> CString -> IO ()
foreign import ccall unsafe "estraier.h est_cond_set_mask"
_set_mask :: Ptr ESTCOND -> Int -> IO ()
wrapCond :: Ptr ESTCOND -> IO Condition
wrapCond condPtr = newForeignPtr _delete condPtr >>= return . Condition
withCondPtr :: Condition -> (Ptr ESTCOND -> IO a) -> IO a
withCondPtr (Condition cond) = withForeignPtr cond
-- |'newCondition' creates an empty search condition.
newCondition :: IO Condition
newCondition = _new >>= wrapCond
-- |@'setPhrase' cond phrase@ stores a condition phrase into
-- @cond@. The syntax of the phrase is assumed to be the normal
-- syntax, unless you specify a 'SyntaxType' explicitly with
-- 'setOptions'.
setPhrase :: Condition -> String -> IO ()
setPhrase cond phrase
= withCondPtr cond $ \ condPtr ->
withUTF8CString phrase $ \ phrasePtr ->
_set_phrase condPtr phrasePtr
-- |@'addAttrCond' cond expr@ appends an attribute search condition to
-- @cond@. See the user's guide for explanation about the attribute
-- search condition.
addAttrCond :: Condition -> String -> IO ()
addAttrCond cond attr
= withCondPtr cond $ \ condPtr ->
withUTF8CString attr $ \ attrPtr ->
_add_attr condPtr attrPtr
-- |@'setOrder' cond expr@ stores an ordering expression into
-- @cond@. See the user's guide for explanation about the ordering
-- expression. By default, the result is sorted in descending order of
-- score.
setOrder :: Condition -> String -> IO ()
setOrder cond order
= withCondPtr cond $ \ condPtr ->
withUTF8CString order $ \ orderPtr ->
_set_order condPtr orderPtr
-- |@'setMax' cond n@ specifies the maximum number of results. By
-- default, the number of results is unlimited.
setMax :: Condition -> Int -> IO ()
setMax cond n
= withCondPtr cond $ \ condPtr ->
_set_max condPtr n
-- |@'setSkip' cond n@ specifies how many documents should be skipped
-- from the beginning of result.
setSkip :: Condition -> Int -> IO ()
setSkip cond n
= withCondPtr cond $ \ condPtr ->
_set_skip condPtr n
-- |@'setOptions' cond opts@ specifies options to the search
-- condition.
setOptions :: Condition -> [CondOption] -> IO ()
setOptions cond options
= withCondPtr cond $ \ condPtr ->
_set_options condPtr (marshalOpts marshalCondOption options)
-- |@'setAuxiliary' cond min@ specifies how many documents should be
-- in the result to avoid using the auxiliary index to pad the result.
setAuxiliary :: Condition -> Int -> IO ()
setAuxiliary cond n
= withCondPtr cond $ \ condPtr ->
_set_auxiliary condPtr n
-- |@'setEclipse' cond ecl@ specifies how to hide documents from the
-- search result by their similarity.
setEclipse :: Condition -> Eclipse -> IO ()
setEclipse cond ecl
= withCondPtr cond $ \ condPtr ->
_set_eclipse condPtr (marshalEclipse ecl)
-- |@'setDistinct' cond attr@ specifies an attribute which must be
-- unique to the search result.
setDistinct :: Condition -> String -> IO ()
setDistinct cond attr
= withCondPtr cond $ \ condPtr ->
withUTF8CString attr $ \ attrPtr ->
_set_distinct condPtr attrPtr
-- |@'setMetaSearchMask' cond xs@ specifies that, in
-- 'Text.HyperEstraier.Database.metaSearch', some databases must be
-- excluded from the search result. e.g.
--
-- > main = withDatabase "db1" (Reader []) $ \ db1 ->
-- > withDatabase "db2" (Reader []) $ \ db2 ->
-- > withDatabase "db3" (Reader []) $ \ db3 ->
-- > do cond <- newCondition
-- > setPhrase cond "hello AND world"
-- > setMetaSearchMask cond [0, 2] -- zero-origin
-- >
-- > -- In this case, "db1" and "db3" are excluded from the meta search.
-- > result <- metaSearch [db1, db2, db3]
-- > print result
--
setMetaSearchMask :: Condition -> [Int] -> IO ()
setMetaSearchMask cond xs
= withCondPtr cond $ \ condPtr ->
_set_max condPtr (calculateMask xs)
where
calculateMask :: [Int] -> Int
calculateMask [] = 0
calculateMask (x:xs) = assert (x >= 0 && x <= 28)
$ (1 `shiftL` x) .|. calculateMask xs