2013-09-08 18 views
11

Cách tốt nhất để chuyển đổi giữa Storable.Vector Word8ByteString nghiêm ngặt là gì?Làm thế nào để chuyển đổi giữa ByteString và Vector đáng yêu?

Tất nhiên, cách thức không sao chép (không có) sẽ được đánh giá cao nhất.

Tôi có nên chỉ unsafeCoerce hoặc có chức năng thư viện cho điều đó không (tôi không thể tìm thấy)?

Ngoài ra, cách tiếp cận này có giống với một số Unboxed.Vector Word8 không?

+1

Trong một số trường hợp nó sẽ có lợi để sao chép. Nếu các phần tử thuở của bạn là các đoạn ngắn của bản gốc dài hơn, ví dụ: ('BS.take 10 someLongByteString'), toàn bộ đoạn dài sẽ được giữ lại bởi' ForeignPtr'. Trong trường hợp này sao chép thường tốt hơn vì nó sẽ sử dụng ít bộ nhớ hơn nhiều. Đây là một trường hợp đặc biệt, nhưng dường như nó xuất hiện thường xuyên. –

Trả lời

9

Một đơn giản unsafeCoerce sẽ không hoạt động, như cách bố trí của các nhà thầu dữ liệu là khác nhau:

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

vs

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

Bạn có thể nhập Data.Array.Storable.InternalsData.ByteString.Internal để có được quyền truy cập vào các nhà thầu liệu và sau đó xây dựng một cái khác mà không sao chép dữ liệu:

> 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)) 

(Tôi đã xóa lời nhắc khá dài là Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>).

Điều này sẽ không hoạt động cho Data.Vector.Unboxed, bởi vì ở đây dữ liệu nằm trên vùng Haskell và được quản lý bởi thời gian chạy GHC, trong khi hai dữ liệu kia quản lý dữ liệu bên ngoài vùng Haskell.

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

Cảm ơn bạn đã đặt nó trên Hackage! – nh2

Các vấn đề liên quan