4

CString(私の場合はnullで終了するC文字)の格納可能なベクトルインスタンスを作成しようとしています。格納可能なインスタンスは、CStringが(Ptr CChar)であるポインターを格納します。したがって、ベクトルの長さはCStringポインターの数です。さて、この保存可能なインスタンスを作成する理由は、FFI CStringからゼロコピーを実行し、unsafeCreateを使用してByteStringを高速ビルドするために使用されるためです(変換後、ここでは中間操作に高速ベクトルを使用します)。ByteStringの高速ビルドを行うには、保存可能なインスタンスに3つのことが必要です。

  • バイト単位の全長-格納可能なインスタンスには、ベクターに追加するときに各CStringの長さを格納するためのブックキーピング割り当てと、これまでに格納されたCStringの全長が必要です。C文字列の全長が2^31を超えることはできないとしましょう。したがって、Int32 / Word32は、各CStringの長さと全長を格納するために行います。
  • CStringとその長さを格納する関数-O(n)時間。この関数は、CStringをウォークし、その長さを格納します。また、全長をCStringの長さだけインクリメントします。
  • 長さを合計バイトで返す関数-O(1)時間。この関数は、全長を格納するフィールドから値を取得するだけです。

カスタムの保存可能なインスタンスを作成する方法は知っていますが、この種のケースを処理する方法はわかりません。カスタム簿記を行う方法を示す簡単なコード(簡単なおもちゃの例でもかまいません)、および簿記の結果を保存/取得する関数を作成することは非常に高く評価されます。

アップデート1(説明)

私の場合、保存可能なベクトルインスタンスを使用する理由は、ボックス化されていない型を使用した高速な計算/変換(C FFIを介して受信したリアルタイムデータ)と、バイト文字列への高速変換(データをリアルタイムで送信するため)の2つです。別のプログラムへのIPC)。高速なバイト文字列変換には、unsafeCreateが優れています。ただし、割り当てる量を把握し、変換用の関数を渡す必要があります。格納可能なベクトルインスタンス(混合型-上記の質問をCString型のみに簡略化した)が与えられた場合、ベクトルの各要素をウォークしてバイト文字列に変換する高速変換関数を簡単に構築できます。次に、それをunsafeCreateに渡すだけです。ただし、割り当てるバイト数も渡す必要があります。AO(n)再帰バイト長計算関数は遅すぎるため、バイト文字列を作成するオーバーヘッドが2倍になる可能性があります。

4

1 に答える 1

1

このようなものを書きたいようですね。このコードはテストされていないことに注意してください。

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

その後、アプリケーションに応じて、必要に応じて他の機能を追加できます。各関数が不変条件を保持していることを確認してください。

于 2011-12-11T16:08:19.803 に答える