haskell – 使用O(1)函数为CString编写可存储的实例以获得总字节
我正在尝试为CString编写一个
storable vector实例(在我的例子中,以null结尾的C字符).可存储的实例将存储CString所指的指针(Ptr CChar).因此,向量的长度是CString指针的数量.现在,我写这个可存储实例的原因是因为它将用于从FFI CString进行零拷贝,然后使用unsafeCreate进行快速ByteString构建(在一些转换之后 – 所以,我们在这里使用快速向量进行中间操作).为了快速进行ByteString构建,可存储实例需要三件事:
>总长度(以字节为单位) – 可存储实例需要具有簿记分配,用于在将每个CString添加到向量时存储每个CString的长度,以及到目前为止存储的CString的总长度.让我们说C字符串的总长度不能超过2 ^ 31.因此,Int32 / Word32将用于存储每个CString的长度和总长度. 虽然我知道如何编写自定义可存储实例,但我不知道如何处理这种情况.一个简单的代码(可以是一个简单的玩具示例),显示如何进行自定义簿记,并写入存储/获取簿记结果的功能将非常感谢. 更新1(澄清) 在我的案例中使用可存储的矢量实例的原因有两个:使用未装箱类型的快速计算/转换(通过C FFI接收的实时数据),以及快速转换为bytestring(以实时发送数据) IPC到另一个程序).对于快速字节串转换,unsafeCreate非常好.但是,我们必须知道要分配多少,并且还要传递一个转换功能.给定一个可存储的向量实例(使用混合类型 – 我将上面的问题简化为CString类型),我很容易构建一个快速转换函数,它可以遍历向量的每个元素并将其转换为bytestring.然后,我们将它传递给unsafeCreate.但是,我们还必须传递它要分配的字节数. O(n)递归字节长度计算函数太慢,并且可以使构造字节串的开销加倍. 解决方法
听起来你想写这样的东西.请注意,此代码未经过测试.
-- The basic type. Export the type but not the constructors or -- accessors from the module. data StringVector { strVecLength :: Word32,-- Total length strVecContents [(Word32,Ptr CChar)] -- (Length,value) pairs } -- Invariants: forall (StringVector len contents),-- len == sum (map fst) contents -- all (p -> fst p == c_strlen (snd p)) contents -- The null case. emptyStrVec :: StringVector emptyStrVec = StringVector 0 [] -- Put a new Cstring at the head of the vector. Analogous to ":". stringVectorCons :: Ptr CChar -> StringVector -> StringVector stringVectorCons ptr (StringVector len pairs) = StringVector (len + n) $(n,ptr) : pairs where n = c_strlen ptr -- Or whatever the right function name is -- Extract the head of the vector and the remaining vector. stringVectorUncons :: StringVector -> ((Word32,Ptr CChar),StringVector) stringVectorUncons (StringVector len (h:t)) = (h,StringVector (len - fst h) t) 之后,您可以根据应用程序添加您可能需要的任何其他功能.只需确保每个函数都保留不变量. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |