{-# LINE 1 "Data/Text/ICU/Enumerator.hsc" #-}
{-# LANGUAGE EmptyDataDecls, BangPatterns, ForeignFunctionInterface, RecordWildCards #-}
-- |
-- Module      : Data.Text.ICU.Calendar
-- Copyright   : (c) 2021 Torsten Kemps-Benedix
--
-- License     : BSD-style
-- Maintainer  : bos@serpentine.com
-- Stability   : experimental
-- Portability : GHC
--
-- Calendar functions implemented as bindings to
-- the International Components for Unicode (ICU) libraries.

module Data.Text.ICU.Enumerator
    (next, toList, createEnumerator, Enumerator, UEnumerator,
    ) where



import Data.Int (Int32)
import Data.Text (Text)
import Data.Text.ICU.Error.Internal (UErrorCode, handleError)
import Data.Text.ICU.Internal (UChar, newICUPtr, fromUCharPtr)
import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr (FunPtr, Ptr, nullPtr)
import Foreign.Storable (peek)
import Prelude hiding (last)

data UEnumerator

newtype Enumerator = Enumerator {Enumerator -> ForeignPtr UEnumerator
enumeratorToForeignPtr :: ForeignPtr UEnumerator}

createEnumerator :: IO (Ptr UEnumerator) -> IO Enumerator
createEnumerator :: IO (Ptr UEnumerator) -> IO Enumerator
createEnumerator = (ForeignPtr UEnumerator -> Enumerator)
-> FinalizerPtr UEnumerator
-> IO (Ptr UEnumerator)
-> IO Enumerator
forall a i.
(ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
newICUPtr ForeignPtr UEnumerator -> Enumerator
Enumerator FinalizerPtr UEnumerator
uenum_close

next :: Enumerator -> IO (Maybe Text)
next :: Enumerator -> IO (Maybe Text)
next Enumerator
enum = ForeignPtr UEnumerator
-> (Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (Enumerator -> ForeignPtr UEnumerator
enumeratorToForeignPtr Enumerator
enum) ((Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text))
-> (Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text)
forall a b. (a -> b) -> a -> b
$ \Ptr UEnumerator
enumPtr ->
  (Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text))
-> (Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text)
forall a b. (a -> b) -> a -> b
$ \Ptr Int32
lenPtr -> do
    textPtr <- (Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar)
forall a. (Ptr UErrorCode -> IO a) -> IO a
handleError ((Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar))
-> (Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar)
forall a b. (a -> b) -> a -> b
$ Ptr UEnumerator -> Ptr Int32 -> Ptr UErrorCode -> IO (Ptr UChar)
uenum_unext Ptr UEnumerator
enumPtr Ptr Int32
lenPtr
    if textPtr == nullPtr
      then pure Nothing
      else do
          n <- peek lenPtr
          t <- fromUCharPtr textPtr (fromIntegral n)
          pure $ Just t

toList :: Enumerator -> IO [Text]
toList :: Enumerator -> IO [Text]
toList Enumerator
enum = [Text] -> [Text]
forall a. [a] -> [a]
reverse ([Text] -> [Text]) -> IO [Text] -> IO [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text] -> IO [Text]
go []
  where
    go :: [Text] -> IO [Text]
go [Text]
l = do
      mx <- Enumerator -> IO (Maybe Text)
next Enumerator
enum
      case mx of
        Maybe Text
Nothing -> [Text] -> IO [Text]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text]
l
        Just Text
x -> [Text] -> IO [Text]
go (Text
xText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
l)

foreign import ccall unsafe "hs_text_icu.h &__hs_uenum_close" uenum_close
    :: FunPtr (Ptr UEnumerator -> IO ())
foreign import ccall unsafe "hs_text_icu.h __hs_uenum_unext" uenum_unext
    :: Ptr UEnumerator -> Ptr Int32 -> Ptr UErrorCode
    -> IO (Ptr UChar)