{-# 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
    Ptr UChar
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 Ptr UChar
textPtr Ptr UChar -> Ptr UChar -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr UChar
forall a. Ptr a
nullPtr
      then Maybe Text -> IO (Maybe Text)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Text
forall a. Maybe a
Nothing
      else do
          Int32
n <- Ptr Int32 -> IO Int32
forall a. Storable a => Ptr a -> IO a
peek Ptr Int32
lenPtr
          Text
t <- Ptr UChar -> I16 -> IO Text
fromUCharPtr Ptr UChar
textPtr (Int32 -> I16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
n)
          Maybe Text -> IO (Maybe Text)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Text -> IO (Maybe Text)) -> Maybe Text -> IO (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just Text
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
      Maybe Text
mx <- Enumerator -> IO (Maybe Text)
next Enumerator
enum
      case Maybe Text
mx of
        Maybe Text
Nothing -> [Text] -> IO [Text]
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)