module PCD.Internal.AsciiParsers where
import Control.Applicative
import Control.Lens ((^.))
import Data.Attoparsec.Text (double, count, skipSpace)
import qualified Data.Attoparsec.Text.Lazy as ATL
import qualified Data.Text.Lazy.IO as TL
import qualified Data.Vector as B
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as GM
import System.IO (Handle)
import PCD.Header (Header, FieldType, pointParser, points)
import PCD.Internal.Types (V3(..), V4(..))
readPoints :: (G.Vector v a) =>
Header -> Handle -> ATL.Parser a -> IO (v a)
readPoints pcd h p = aux <$> TL.hGetContents h
where n = fromIntegral $ pcd^.points
aux t0 = G.create $
do v <- GM.new n
let write = GM.write v
go !i !t
| i == n = return v
| otherwise = case ATL.parse p t of
ATL.Done !t' !pt -> write i pt >>
go (i+1) t'
ATL.Fail _ _ msg -> error msg
go 0 t0
readPointsDefault :: Header -> Handle -> IO (B.Vector (B.Vector FieldType))
readPointsDefault pcd h = readPoints pcd h $ B.fromList <$> pointParser pcd
readXYZ :: Fractional a => ATL.Parser (V3 a)
readXYZ = (\[x,y,z] -> V3 x y z) <$>
count 3 ((realToFrac <$> double) <* skipSpace)
readXYZW :: Fractional a => ATL.Parser (V4 a)
readXYZW = (\[x,y,z,w] -> V4 x y z w) <$>
count 4 ((realToFrac <$> double) <* skipSpace)