summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/manual/pragmas.txt2
-rw-r--r--lib/pure/marshal.nim28
-rw-r--r--lib/system/nimscript.nim2
3 files changed, 28 insertions, 4 deletions
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index 70fc4a914..a19f41a34 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -161,7 +161,7 @@ requires full qualification.
 
 asmNoStackFrame pragma
 ----------------------
-A proc can be marked with the ``AsmNoStackFrame`` pragma to tell the compiler
+A proc can be marked with the ``asmNoStackFrame`` pragma to tell the compiler
 it should not generate a stack frame for the proc. There are also no exit
 statements like ``return result;`` generated and the generated C function is
 declared as ``__declspec(naked)`` or ``__attribute__((naked))`` (depending on
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index 134581a06..701dff88c 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -36,6 +36,30 @@ import streams, typeinfo, json, intsets, tables
 proc ptrToInt(x: pointer): int {.inline.} =
   result = cast[int](x) # don't skip alignment
 
+proc binaryToUtf8(s: string): string =
+  ## converts binary data to valid UTF-8 string
+  result = newStringOfCap(s.len)
+  for c in s:
+    let code = ord(c)
+    if code > 0x7F:
+      result.add(chr(0xC0 or (code shr 6)))
+      result.add(chr(0x80 or (code and 0x3F)))
+    else:
+      result.add(c)
+
+proc utf8ToBinary(s: string): string =
+  result = newStringOfCap(s.len)
+  var i = 0
+  while i < s.len:
+    var code = ord(s[i])
+    if code > 127:
+      if (code and 0xE0) != 0xC0 or (code and 0x1F) > 3 or i + 1 == s.len:
+        raise newException(ValueError, "invalid binary encoding")
+      code = ((code and 0x1F) shl 6) or (ord(s[i + 1]) and 0x3F)
+      inc i
+    result.add(chr(code))
+    inc i
+
 proc storeAny(s: Stream, a: Any, stored: var IntSet) =
   case a.kind
   of akNone: assert false
@@ -92,7 +116,7 @@ proc storeAny(s: Stream, a: Any, stored: var IntSet) =
   of akString:
     var x = getString(a)
     if isNil(x): s.write("null")
-    else: s.write(escapeJson(x))
+    else: s.write(escapeJson(binaryToUtf8(x)))
   of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a))
   of akFloat..akFloat128: s.write($getBiggestFloat(a))
 
@@ -205,7 +229,7 @@ proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) =
       setPointer(a, nil)
       next(p)
     of jsonString:
-      setString(a, p.str)
+      setString(a, utf8ToBinary(p.str))
       next(p)
     else: raiseParseErr(p, "string expected")
   of akInt..akInt64, akUInt..akUInt64:
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index fc6b8c99d..29466c34d 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -301,7 +301,7 @@ var
   author*: string      ## Nimble support: The package's author.
   description*: string ## Nimble support: The package's description.
   license*: string     ## Nimble support: The package's license.
-  srcdir*: string      ## Nimble support: The package's source directory.
+  srcDir*: string      ## Nimble support: The package's source directory.
   binDir*: string      ## Nimble support: The package's binary directory.
   backend*: string     ## Nimble support: The package's backend.