Storable.Vector Word8
と厳密なByteString
の間で変換する最善の方法は何ですか?ByteStringとStorable Vectorの間の変換方法は?
もちろん、非コピー(ノーオペレーション)の方法が最も高く評価されます。
私はちょうどunsafeCoerce
かライブラリ関数がありますか(私は見つけられませんでした)?
また、アプローチはUnboxed.Vector Word8
についても同じですか?
Storable.Vector Word8
と厳密なByteString
の間で変換する最善の方法は何ですか?ByteStringとStorable Vectorの間の変換方法は?
もちろん、非コピー(ノーオペレーション)の方法が最も高く評価されます。
私はちょうどunsafeCoerce
かライブラリ関数がありますか(私は見つけられませんでした)?
また、アプローチはUnboxed.Vector Word8
についても同じですか?
シンプルunsafeCoerce
データ構築のレイアウトが異なっているとして、機能しません:あなたは、生のコンストラクタへのアクセスを得るためにData.Array.Storable.Internals
とData.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
では機能しません。
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
それをHackageに載せてくれてありがとう! – nh2
いくつかのケースでは、コピーすることが有益であろう。あなたのバイトコードが長いオリジナルのバイトコードの短いセグメントである場合。 ( 'BS.take 10 someLongByteString')、長いチャンク全体は' ForeignPtr'によって保持されます。この場合、コピーを使うほうがメモリがはるかに少なくなるため、コピーはしばしば優れています。これは特殊なケースのようですが、頻繁に出てくるようです。 –