module BaseXClient.Utils where import Control.Applicative import Control.Exception import Data.Char import System.IO exec :: Int -> [String] -> Handle -> IO String exec code args h = do writeCode h code writeStrings h args info <- readString h result <- ok h <$$> \b -> if b then info else error info evaluate result readString :: Handle -> IO String readString h = do c <- hGetChar h if c /= '\0' then (:) <$> (if c == '\255' then hGetChar h else return c) <*> readString h else return [] writeCode :: Handle -> Int -> IO () writeCode h code = hPutChar h $ chr code writeString :: Handle -> String -> IO () writeString h str = do writeString' h str hFlush h writeStrings :: Handle -> [String] -> IO () writeStrings h strs = do mapM_ (writeString' h) strs hFlush h writeString' :: Handle -> String -> IO () writeString' h str = do hPutStr h $ foldr (\c cs -> if c == '\0' || c == '\255' then '\255' : c : cs else c : cs) [] str hPutChar h '\0' ok :: Handle -> IO Bool ok h = ('\0' ==) <$> hGetChar h untilM :: IO Bool -> IO a -> IO [a] untilM test = whileM (not <$> test) whileM :: IO Bool -> IO a -> IO [a] whileM test body = test >>= \succeeds -> if succeeds then (:) <$> body <*> whileM test body else return [] infixl 4 <$$> (<$$>) :: Functor f => f a -> (a -> b) -> f b (<$$>) = flip fmap