(* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh * Jagannathan, and Stephen Weeks. * Copyright (C) 1997-2000 NEC Research Institute. * * MLton is released under a BSD-style license. * See the file MLton-LICENSE for details. *) structure CUtil: C_UTIL = struct open Int structure Pointer = Primitive.MLton.Pointer fun makeLength (sub, term) p = let fun loop i = if term (sub (p, i)) then i else loop (i +? 1) in loop 0 end fun toArrayOfLength (s: 'a, sub: 'a * int -> 'b, n: int) : 'b array = let val (a, _) = Array.unfoldi (n, (), fn (i, ()) => (sub (s, i), ())) in a end structure C_Pointer = struct type t = C_Pointer.t val null = Pointer.toWord Pointer.null fun isNull p = p = null end structure C_String = struct type t = C_String.t fun sub (cs, i) = Primitive.Char8.idFromWord8 (Pointer.getWord8 (Pointer.fromWord cs, C_Ptrdiff.fromInt i)) fun update (cs, i, c) = Pointer.setWord8 (Pointer.fromWord cs, C_Ptrdiff.fromInt i, Primitive.Char8.idToWord8 c) val length = makeLength (sub, fn #"\000" => true | _ => false) fun toCharArrayOfLength (cs, n) = toArrayOfLength (cs, sub, n) fun toStringOfLength (cs, n) = String.unsafeFromArray (CharArray.fromPoly (toCharArrayOfLength (cs, n))) fun toString cs = toStringOfLength (cs, length cs) end structure C_StringArray = struct type t = C_StringArray.t fun sub (css: t, i) = (Pointer.toWord o Pointer.getCPointer) (Pointer.fromWord css, C_Ptrdiff.fromInt i) val length = makeLength (sub, C_Pointer.isNull) val toArrayOfLength = fn (css, n) => toArrayOfLength (css, C_String.toString o sub, n) fun toArray css = toArrayOfLength (css, length css) val toList = Array.toList o toArray (* The C side converts the last element of the array, "", * to the null terminator that C primitives expect. * As far as C can tell, the other elements of the array * are just char*'s. *) fun fromList l = let val (a, _) = Array.unfoldi (1 +? List.length l, l, fn (_, l) => case l of [] => (NullString.empty, l) | s::l => (NullString.nullTerm s, l)) in a end end end