2013-09-08 10 views
11

Storable.Vector Word8と厳密なByteStringの間で変換する最善の方法は何ですか?ByteStringとStorable Vectorの間の変換方法は?

もちろん、非コピー(ノーオペレーション)の方法が最も高く評価されます。

私はちょうどunsafeCoerceかライブラリ関数がありますか(私は見つけられませんでした)?

また、アプローチはUnboxed.Vector Word8についても同じですか?

+1

いくつかのケースでは、コピーすることが有益であろう。あなたのバイトコードが長いオリジナルのバイトコードの短いセグメントである場合。 ( 'BS.take 10 someLongByteString')、長いチャンク全体は' ForeignPtr'によって保持されます。この場合、コピーを使うほうがメモリがはるかに少なくなるため、コピーはしばしば優れています。これは特殊なケースのようですが、頻繁に出てくるようです。 –

答えて

9

シンプルunsafeCoerceデータ構築のレイアウトが異なっているとして、機能しません:あなたは、生のコンストラクタへのアクセスを得るためにData.Array.Storable.InternalsData.ByteString.Internalをインポートすることができます

data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload 
        {-# UNPACK #-} !Int    -- offset 
        {-# UNPACK #-} !Int    -- length 

data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e) 

対データをコピーせずに一方を構成します。

> let bs = pack [1,2,3] 
> bs 
"\SOH\STX\ETX" 
> let sa = case bs of (PS ptr 0 n) -> StorableArray 0 (n-1) n ptr 
> :t sa 
sa :: StorableArray Int GHC.Word.Word8 
> Data.Array.MArray.readArray sa 1 
2 
> Data.Array.MArray.readArray sa 0 
1 
> Data.Array.MArray.readArray sa 3 
*** Exception: Ix{Int}.index: Index (3) out of range ((0,2)) 

(私はPrelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>というかなり長いプロンプトを削除しました)

これは、データがHaskellヒープ上にあり、GHCランタイムによって管理され、他の2つがHaskellヒープ外のデータを管理するため、Data.Vector.Unboxedでは機能しません。

3
byteStringToVector :: (Storable a) => BS.ByteString -> V.Vector a 
byteStringToVector bs = vec where 
    vec = V.unsafeFromForeignPtr (castForeignPtr fptr) (scale off) (scale len) 
    (fptr, off, len) = BS.toForeignPtr bs 
    scale = (`div` sizeOfElem vec) 

sizeOfElem vec = sizeOf (undefined `asTypeOf` V.head vec) 

http://hackage.haskell.org/packages/archive/spool/0.1/doc/html/Data-Vector-Storable-ByteString.html

+0

それをHackageに載せてくれてありがとう! – nh2

関連する問題