[MLton-commit] r5871

Vesa Karvonen vesak at mlton.org
Tue Aug 14 01:18:32 PDT 2007


Pickling of LargeInt.t values via a packed string representation.

It seems that the only way to pickle/unpickle IntInf values in (hopefully)
linear time with the current Basis Library is via fmt/scan, that can (but
might not) be implemented in linear time.

----------------------------------------------------------------------

U   mltonlib/trunk/com/ssh/generic/unstable/detail/value/pickle.sml

----------------------------------------------------------------------

Modified: mltonlib/trunk/com/ssh/generic/unstable/detail/value/pickle.sml
===================================================================
--- mltonlib/trunk/com/ssh/generic/unstable/detail/value/pickle.sml	2007-08-14 08:08:23 UTC (rev 5870)
+++ mltonlib/trunk/com/ssh/generic/unstable/detail/value/pickle.sml	2007-08-14 08:18:30 UTC (rev 5871)
@@ -174,12 +174,10 @@
 
    fun pickle t =
        case getT t
-        of INT {wr, ...} =>
-           O.run (HashMap.new {eq = Dyn.eq, hash = Dyn.hash}) wr
+        of INT r => O.run (HashMap.new {eq = Dyn.eq, hash = Dyn.hash}) (#wr r)
    fun unpickle t =
        case getT t
-        of INT {rd, ...} =>
-           I.run (HashMap.new {eq = op =, hash = Arg.hash (Arg.int ())}) rd
+        of INT r => I.run (HashMap.new {eq = op =, hash = Word.fromInt}) (#rd r)
 
    fun fake msg = INT {rd = I.thunk (failing msg), wr = failing msg}
 
@@ -394,7 +392,55 @@
                        char
       val word = bits Word.ops Iso.id
 
-      val largeInt : LargeInt.t t = fake "Pickle.largeInt unimplemented"
+      val largeInt = let
+         fun to i = let
+            val buffer = Buffer.new ()
+            fun hexToInt c =
+                ord c - (if      Char.inRange (#"0", #"9") c then ord #"0"
+                         else if Char.inRange (#"a", #"f") c then ord #"a" - 10
+                         else if Char.inRange (#"A", #"F") c then ord #"A" - 10
+                         else fail "Bug in LargeInt.fmt")
+            fun pack s =
+                if Int.isOdd (Substring.size s) then pl (0, s) else lp s
+            and lp s =
+                case Substring.getc s
+                 of NONE        => ()
+                  | SOME (c, s) => pl (hexToInt c, s)
+            and pl (i, s) =
+                case Substring.getc s
+                 of NONE        => fail "Bug"
+                  | SOME (c, s) =>
+                    (Buffer.push buffer (chr (hexToInt c * 16 + i)) ; lp s)
+         in
+            Buffer.push buffer (if i < 0 then #"\001" else #"\000")
+          ; pack (Substring.full (LargeInt.fmt StringCvt.HEX (abs i)))
+          ; Buffer.toString buffer
+         end
+         fun from s = let
+            val buffer = Buffer.new ()
+            fun intToHex i = chr (if i < 10 then i + ord #"0" else i - 10 + ord #"A")
+            fun lp s =
+                case Substring.getc s
+                 of NONE        => ()
+                  | SOME (c, s) =>
+                    (Buffer.push buffer (intToHex (Int.rem (ord c, 16)))
+                   ; Buffer.push buffer (intToHex (Int.quot (ord c, 16)))
+                   ; lp s)
+         in
+            if size s < 2 then fail "Corrupted pickle" else ()
+          ; case String.sub (s, 0)
+             of #"\000" => ()
+              | #"\001" => Buffer.push buffer #"~"
+              | _       => fail "Corrupted pickle"
+          ; lp (Substring.triml 1 (Substring.full s))
+          ; case LargeInt.scan StringCvt.HEX Substring.getc
+                               (Substring.full (Buffer.toString buffer))
+             of NONE        => fail "Corrupted pickle"
+              | SOME (i, _) => i
+         end
+      in
+         iso' id string (to, from)
+      end
       val largeReal = bits LargeRealWord.ops CastLargeReal.isoBits
       val largeWord = bits LargeWord.ops Iso.id
 




More information about the MLton-commit mailing list