diff options
-rw-r--r-- | doc/manual.txt | 8 | ||||
-rw-r--r-- | lib/pure/os.nim | 68 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 15 | ||||
-rw-r--r-- | lib/system/sysio.nim | 12 | ||||
-rw-r--r-- | lib/system/widestrs.nim | 359 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 4 | ||||
-rw-r--r-- | web/news.txt | 4 |
7 files changed, 164 insertions, 306 deletions
diff --git a/doc/manual.txt b/doc/manual.txt index 4d2cd6a62..31bd7134d 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -2868,9 +2868,9 @@ Effect system Exception tracking ------------------ -Nimrod supports `exception tracking`:idx:. The `raises`:idx: pragma can used to -explicitly define which exceptions a proc/iterator/method/converter is allowed -to raise. The compiler verifies this: +Nimrod supports `exception tracking`:idx:. The `raises`:idx: pragma can be used +to explicitly define which exceptions a proc/iterator/method/converter is +allowed to raise. The compiler verifies this: .. code-block:: nimrod proc p(what: bool) {.raises: [EIO, EOS].} = @@ -2878,7 +2878,7 @@ to raise. The compiler verifies this: else: raise newException(EOS, "OS") An empty ``raises`` list (``raises: []``) means that no exception may be raised: - + .. code-block:: nimrod proc p(): bool {.raises: [].} = try: diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 433a79c5e..233967753 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -184,7 +184,7 @@ proc OSErrorMsg*(): string {.rtl, extern: "nos$1".} = if FormatMessageW(0x00000100 or 0x00001000 or 0x00000200, nil, err, 0, addr(msgbuf), 0, nil) != 0'i32: result = $msgbuf - if msgbuf != nil: LocalFree(msgbuf) + if msgbuf != nil: LocalFree(cast[pointer](msgbuf)) else: var msgbuf: cstring if FormatMessageA(0x00000100 or 0x00001000 or 0x00000200, @@ -254,20 +254,14 @@ proc UnixToNativePath*(path: string): string {. when defined(windows): template wrapUnary(varname, winApiProc, arg: expr) {.immediate.} = - var tmp = allocWideCString(arg) - var varname = winApiProc(tmp) - dealloc tmp + var varname = winApiProc(newWideCString(arg)) template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = - var tmp2 = allocWideCString(arg) - var varname = winApiProc(tmp2, arg2) - dealloc tmp2 + var varname = winApiProc(newWideCString(arg), arg2) when useWinUnicode: proc FindFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle = - var aa = allocWideCString(a) - result = FindFirstFileW(aa, b) - dealloc aa + result = FindFirstFileW(newWideCString(a), b) template FindNextFile(a, b: expr): expr = FindNextFileW(a, b) template getCommandLine(): expr = getCommandLineW() @@ -363,11 +357,10 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} = const bufsize = 512 # should be enough when defined(windows): when useWinUnicode: - var res = cast[wideCString](alloc0(bufsize+1)) + var res = newWideCString("", bufsize) var L = GetCurrentDirectoryW(bufsize, res) - result = res$L - dealloc res if L == 0'i32: OSError() + result = res$L else: result = newString(bufsize) var L = GetCurrentDirectoryA(bufsize, result) @@ -385,10 +378,7 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [].} = ## `newDir` cannot been set. when defined(Windows): when useWinUnicode: - var x = allocWideCString(newDir) - let res = SetCurrentDirectoryW(x) - dealloc x - if res == 0'i32: OSError() + if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError() else: if SetCurrentDirectoryA(newDir) == 0'i32: OSError() else: @@ -579,15 +569,11 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", const bufsize = 3072'i32 when useWinUnicode: var unused: widecstring - var res = cast[widecstring](alloc(bufsize*2+2)) - var f = allocWideCString(filename) - var L = GetFullPathNameW(f, bufsize, res, unused) - dealloc f + var res = newWideCString("", bufsize div 2) + var L = GetFullPathNameW(newWideCString(filename), bufsize, res, unused) if L <= 0'i32 or L >= bufsize: - dealloc res OSError() result = res$L - dealloc res else: var unused: cstring result = newString(bufsize) @@ -673,8 +659,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", var success = true when useWinUnicode: - var p1 = allocWideCString(path1) - var p2 = allocWideCString(path2) + var p1 = newWideCString(path1) + var p2 = newWideCString(path2) template OpenHandle(path: expr): expr = CreateFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, @@ -705,9 +691,6 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", discard CloseHandle(f1) discard CloseHandle(f2) - when useWinUnicode: - dealloc p1 - dealloc p2 if not success: OSError() else: @@ -754,12 +737,9 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", ## `EOS` is raised. when defined(Windows): when useWinUnicode: - var s = allocWideCString(source) - var d = allocWideCString(dest) - let res = CopyFileW(s, d, 0'i32) - dealloc s - dealloc d - if res == 0'i32: OSError() + let s = newWideCString(source) + let d = newWideCString(dest) + if CopyFileW(s, d, 0'i32) == 0'i32: OSError() else: if CopyFileA(source, dest, 0'i32) == 0'i32: OSError() else: @@ -794,11 +774,8 @@ when not defined(ENOENT): var ENOENT {.importc, header: "<errno.h>".}: cint proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = - ## Removes the `file`. - ## - ## If this fails, `EOS` is raised. This does not fail if the file never - ## existed in the first place. Despite the name of this proc you can also - ## call it on directories, but they will only be removed if they are empty. + ## Removes the `file`. If this fails, `EOS` is raised. This does not fail + ## if the file never existed in the first place. if cremove(file) != 0'i32 and errno != ENOENT: OSError() proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", @@ -934,12 +911,9 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = OSError() else: when useWinUnicode: - var k = allocWideCString(key) - var v = allocWideCString(val) - let res = SetEnvironmentVariableW(k, v) - dealloc k - dealloc v - if res == 0'i32: OSError() + var k = newWideCString(key) + var v = newWideCString(val) + if SetEnvironmentVariableW(k, v) == 0'i32: OSError() else: if SetEnvironmentVariableA(key, val) == 0'i32: OSError() @@ -1082,9 +1056,7 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ ## in `dir` (recursively). ## ## If this fails, `EOS` is raised. This does not fail if the directory never - ## existed in the first place. If you need non recursive directory removal - ## which fails when the directory contains files use the `removeFile` proc - ## instead. + ## existed in the first place. for kind, path in walkDir(dir): case kind of pcFile, pcLinkToFile, pcLinkToDir: removeFile(path) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index e627e73c8..aa4fbe32d 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -361,14 +361,12 @@ when defined(Windows) and not defined(useNimRtl): if env != nil: e = buildEnv(env) if poEchoCmd in options: echo($cmdl) when useWinUnicode: - var tmp = allocWideCString(cmdl) - var ee = allocWideCString(e) - var wwd = allocWideCString(wd) + var tmp = newWideCString(cmdl) + var ee = newWideCString(e) + var wwd = newWideCString(wd) success = winlean.CreateProcessW(nil, - tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS, ee, wwd, SI, ProcInfo) - if tmp != nil: dealloc tmp - if ee != nil: dealloc ee - if wwd != nil: dealloc wwd + tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, + ee, wwd, SI, ProcInfo) else: success = winlean.CreateProcessA(nil, cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo) @@ -445,10 +443,9 @@ when defined(Windows) and not defined(useNimRtl): SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) when useWinUnicode: - var c = allocWideCString(command) + var c = newWideCString(command) var res = winlean.CreateProcessW(nil, c, nil, nil, 0, NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo) - dealloc c else: var res = winlean.CreateProcessA(nil, command, nil, nil, 0, NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 3d5a53f03..31758eb45 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -168,18 +168,14 @@ when defined(windows) and not defined(useWinAnsi): importc: "_wfreopen", nodecl.} proc fopen(filename, mode: CString): pointer = - var f = allocWideCString(filename) - var m = allocWideCString(mode) + var f = newWideCString(filename) + var m = newWideCString(mode) result = wfopen(f, m) - dealloc m - dealloc f proc freopen(filename, mode: cstring, stream: TFile): TFile = - var f = allocWideCString(filename) - var m = allocWideCString(mode) + var f = newWideCString(filename) + var m = newWideCString(mode) result = wfreopen(f, m, stream) - dealloc m - dealloc f else: proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.} diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index 588093d10..cf1f0910c 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -12,249 +12,138 @@ type TUtf16Char* = distinct int16 - WideCString* = ptr array[0.. 1_000_000, TUtf16Char] + WideCString* = ref array[0.. 1_000_000, TUtf16Char] proc len*(w: WideCString): int = ## returns the length of a widestring. This traverses the whole string to ## find the binary zero end marker! while int16(w[result]) != 0'i16: inc result -when true: - const - UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16) - UNI_MAX_BMP = 0x0000FFFF - UNI_MAX_UTF16 = 0x0010FFFF - UNI_MAX_UTF32 = 0x7FFFFFFF - UNI_MAX_LEGAL_UTF32 = 0x0010FFFF - - halfShift = 10 - halfBase = 0x0010000 - halfMask = 0x3FF - - UNI_SUR_HIGH_START = 0xD800 - UNI_SUR_HIGH_END = 0xDBFF - UNI_SUR_LOW_START = 0xDC00 - UNI_SUR_LOW_END = 0xDFFF - - template ones(n: expr): expr = ((1 shl n)-1) - - template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) = - ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true`` - ## `i` is incremented by the number of bytes that have been processed. - bind ones - - if ord(s[i]) <=% 127: - result = ord(s[i]) - when doInc: inc(i) - elif ord(s[i]) shr 5 == 0b110: - #assert(ord(s[i+1]) shr 6 == 0b10) - result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6)) - when doInc: inc(i, 2) - elif ord(s[i]) shr 4 == 0b1110: - #assert(ord(s[i+1]) shr 6 == 0b10) - #assert(ord(s[i+2]) shr 6 == 0b10) - result = (ord(s[i]) and ones(4)) shl 12 or - (ord(s[i+1]) and ones(6)) shl 6 or - (ord(s[i+2]) and ones(6)) - when doInc: inc(i, 3) - elif ord(s[i]) shr 3 == 0b11110: - #assert(ord(s[i+1]) shr 6 == 0b10) - #assert(ord(s[i+2]) shr 6 == 0b10) - #assert(ord(s[i+3]) shr 6 == 0b10) - result = (ord(s[i]) and ones(3)) shl 18 or - (ord(s[i+1]) and ones(6)) shl 12 or - (ord(s[i+2]) and ones(6)) shl 6 or - (ord(s[i+3]) and ones(6)) - when doInc: inc(i, 4) - else: - result = 0xFFFD - when doInc: inc(i) - - iterator runes(s: cstring): int = - var - i = 0 - result: int - while s[i] != '\0': - fastRuneAt(s, i, result, true) - yield result - - proc allocWideCString*(source: cstring, L: int): WideCString = - ## free after usage with `dealloc`. - result = cast[wideCString](alloc(L * 4 + 2)) - var d = 0 - for ch in runes(source): - if ch <=% UNI_MAX_BMP: - if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END: - result[d] = UNI_REPLACEMENT_CHAR - else: - result[d] = TUtf16Char(toU16(ch)) - elif ch >% UNI_MAX_UTF16: +const + UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16) + UNI_MAX_BMP = 0x0000FFFF + UNI_MAX_UTF16 = 0x0010FFFF + UNI_MAX_UTF32 = 0x7FFFFFFF + UNI_MAX_LEGAL_UTF32 = 0x0010FFFF + + halfShift = 10 + halfBase = 0x0010000 + halfMask = 0x3FF + + UNI_SUR_HIGH_START = 0xD800 + UNI_SUR_HIGH_END = 0xDBFF + UNI_SUR_LOW_START = 0xDC00 + UNI_SUR_LOW_END = 0xDFFF + +template ones(n: expr): expr = ((1 shl n)-1) + +template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) = + ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true`` + ## `i` is incremented by the number of bytes that have been processed. + bind ones + + if ord(s[i]) <=% 127: + result = ord(s[i]) + when doInc: inc(i) + elif ord(s[i]) shr 5 == 0b110: + #assert(ord(s[i+1]) shr 6 == 0b10) + result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6)) + when doInc: inc(i, 2) + elif ord(s[i]) shr 4 == 0b1110: + #assert(ord(s[i+1]) shr 6 == 0b10) + #assert(ord(s[i+2]) shr 6 == 0b10) + result = (ord(s[i]) and ones(4)) shl 12 or + (ord(s[i+1]) and ones(6)) shl 6 or + (ord(s[i+2]) and ones(6)) + when doInc: inc(i, 3) + elif ord(s[i]) shr 3 == 0b11110: + #assert(ord(s[i+1]) shr 6 == 0b10) + #assert(ord(s[i+2]) shr 6 == 0b10) + #assert(ord(s[i+3]) shr 6 == 0b10) + result = (ord(s[i]) and ones(3)) shl 18 or + (ord(s[i+1]) and ones(6)) shl 12 or + (ord(s[i+2]) and ones(6)) shl 6 or + (ord(s[i+3]) and ones(6)) + when doInc: inc(i, 4) + else: + result = 0xFFFD + when doInc: inc(i) + +iterator runes(s: cstring): int = + var + i = 0 + result: int + while s[i] != '\0': + fastRuneAt(s, i, result, true) + yield result + +proc newWideCString*(source: cstring, L: int): WideCString = + unsafeNew(result, L * 4 + 2) + #result = cast[wideCString](alloc(L * 4 + 2)) + var d = 0 + for ch in runes(source): + if ch <=% UNI_MAX_BMP: + if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END: result[d] = UNI_REPLACEMENT_CHAR else: - let ch = ch -% halfBase - result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START)) - inc d - result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START)) + result[d] = TUtf16Char(toU16(ch)) + elif ch >% UNI_MAX_UTF16: + result[d] = UNI_REPLACEMENT_CHAR + else: + let ch = ch -% halfBase + result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START)) inc d - result[d] = TUtf16Char(0'i16) - - proc allocWideCString*(s: cstring): WideCString = - ## free after usage with `dealloc`. - if s.isNil: return nil - - when not defined(c_strlen): - proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".} - - let L = cstrlen(s) - result = allocWideCString(s, L) - - proc allocWideCString*(s: string): WideCString = - ## free after usage with `dealloc`. - result = allocWideCString(s, s.len) - - proc `$`*(w: wideCString, estimate: int): string = - result = newStringOfCap(estimate + estimate shr 2) - - var i = 0 - while w[i].int16 != 0'i16: - var ch = w[i].int - inc i - if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END: - # If the 16 bits following the high surrogate are in the source buffer... - let ch2 = w[i].int - # If it's a low surrogate, convert to UTF32: - if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END: - ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +% - (ch2 -% UNI_SUR_LOW_START) +% halfBase - inc i - - if ch <=% 127: - result.add chr(ch) - elif ch <=% 0x07FF: - result.add chr((ch shr 6) or 0b110_00000) - result.add chr((ch and ones(6)) or 0b10_000000) - elif ch <=% 0xFFFF: - result.add chr(ch shr 12 or 0b1110_0000) - result.add chr(ch shr 6 and ones(6) or 0b10_0000_00) - result.add chr(ch and ones(6) or 0b10_0000_00) - elif ch <=% 0x0010FFFF: - result.add chr(ch shr 18 or 0b1111_0000) - result.add chr(ch shr 12 and ones(6) or 0b10_0000_00) - result.add chr(ch shr 6 and ones(6) or 0b10_0000_00) - result.add chr(ch and ones(6) or 0b10_0000_00) - else: - # replacement char: - result.add chr(0xFFFD shr 12 or 0b1110_0000) - result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00) - result.add chr(0xFFFD and ones(6) or 0b10_0000_00) - - proc `$`*(s: WideCString): string = - result = s $ 80 - -else: - const - utf8Encoding = 65001 - - proc MultiByteToWideChar*( - CodePage: int32, - dwFlags: int32, - lpMultiByteStr: cstring, - cbMultiByte: cint, - lpWideCharStr: WideCString, - cchWideChar: cint): cint {. - stdcall, importc: "MultiByteToWideChar", dynlib: "kernel32".} - - proc WideCharToMultiByte*( - CodePage: int32, - dwFlags: int32, - lpWideCharStr: WideCString, - cchWideChar: cint, - lpMultiByteStr: cstring, - cbMultiByte: cint, - lpDefaultChar: cstring=nil, - lpUsedDefaultChar: pointer=nil): cint {. - stdcall, importc: "WideCharToMultiByte", dynlib: "kernel32".} - - proc raiseEncodingError() {.noinline, noreturn.} = - raise newException(EOS, "error in unicode conversion") - - proc `$`*(s: WideCString, len: int): string = - # special case: empty string: needed because MultiByteToWideChar - # returns 0 in case of error: - if len == 0: return "" - - # educated guess of capacity: - var cap = len + len shr 2 - result = newStringOfCap(cap) - - let m = WideCharToMultiByte( - CodePage = utf8Encoding, - dwFlags = 0'i32, - lpWideCharStr = s, - cchWideChar = cint(len), - lpMultiByteStr = cstring(result), - cbMultiByte = cap) - if m == 0: - # try again; ask for capacity: - cap = WideCharToMultiByte( - CodePage = utf8Encoding, - dwFlags = 0'i32, - lpWideCharStr = s, - cchWideChar = cint(len), - lpMultiByteStr = nil, - cbMultiByte = cint(0)) - # and do the conversion properly: - result = newStringOfCap(cap) - let m = WideCharToMultiByte( - CodePage = utf8Encoding, - dwFlags = 0'i32, - lpWideCharStr = s, - cchWideChar = cint(len), - lpMultiByteStr = cstring(result), - cbMultiByte = cap) - if m == 0: raiseEncodingError() - setLen(result, m) - elif m <= cap: - setLen(result, m) + result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START)) + inc d + result[d] = TUtf16Char(0'i16) + +proc newWideCString*(s: cstring): WideCString = + if s.isNil: return nil + + when not defined(c_strlen): + proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".} + + let L = cstrlen(s) + result = newWideCString(s, L) + +proc newWideCString*(s: string): WideCString = + result = newWideCString(s, s.len) + +proc `$`*(w: wideCString, estimate: int): string = + result = newStringOfCap(estimate + estimate shr 2) + + var i = 0 + while w[i].int16 != 0'i16: + var ch = w[i].int + inc i + if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END: + # If the 16 bits following the high surrogate are in the source buffer... + let ch2 = w[i].int + # If it's a low surrogate, convert to UTF32: + if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END: + ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +% + (ch2 -% UNI_SUR_LOW_START) +% halfBase + inc i + + if ch <=% 127: + result.add chr(ch) + elif ch <=% 0x07FF: + result.add chr((ch shr 6) or 0b110_00000) + result.add chr((ch and ones(6)) or 0b10_000000) + elif ch <=% 0xFFFF: + result.add chr(ch shr 12 or 0b1110_0000) + result.add chr(ch shr 6 and ones(6) or 0b10_0000_00) + result.add chr(ch and ones(6) or 0b10_0000_00) + elif ch <=% 0x0010FFFF: + result.add chr(ch shr 18 or 0b1111_0000) + result.add chr(ch shr 12 and ones(6) or 0b10_0000_00) + result.add chr(ch shr 6 and ones(6) or 0b10_0000_00) + result.add chr(ch and ones(6) or 0b10_0000_00) else: - sysAssert(false, "") # cannot happen - - proc `$`*(s: WideCString): string = - result = s $ s.len - - proc allocWideCString*(s: string): WideCString = - ## free after usage with `dealloc`. - let cap = s.len+1 - result = cast[wideCString](alloc0(cap * 2)) - # special case: empty string: needed because MultiByteToWideChar - # return 0 in case of error: - if s.len == 0: return - # convert to utf-16 LE - let m = MultiByteToWideChar(CodePage = utf8Encoding, dwFlags = 0'i32, - lpMultiByteStr = cstring(s), - cbMultiByte = cint(s.len), - lpWideCharStr = result, - cchWideChar = cint(cap)) - if m == 0: raiseEncodingError() - - proc allocWideCString*(s: cstring): WideCString = - ## free after usage with `dealloc`. - if s.isNil: return nil - - when not defined(c_strlen): - proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".} - - let len = cstrlen(s) - let cap = len+1 - result = cast[wideCString](alloc0(cap * 2)) - # special case: empty string: needed because MultiByteToWideChar - # return 0 in case of error: - if s.len == 0: return - # convert to utf-16 LE - let m = MultiByteToWideChar(CodePage = utf8Encoding, dwFlags = 0'i32, - lpMultiByteStr = s, - cbMultiByte = cint(len), - lpWideCharStr = result, - cchWideChar = cint(cap)) - if m == 0: raiseEncodingError() + # replacement char: + result.add chr(0xFFFD shr 12 or 0b1110_0000) + result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00) + result.add chr(0xFFFD and ones(6) or 0b10_0000_00) +proc `$`*(s: WideCString): string = + result = s $ 80 diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 1ea00c737..fa4925ee6 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -93,6 +93,8 @@ const SW_SHOWNORMAL* = 1'i32 INVALID_HANDLE_VALUE* = THANDLE(-1) + + CREATE_UNICODE_ENVIRONMENT* = 1024'i32 proc CloseHandle*(hObject: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32", importc: "CloseHandle".} @@ -116,7 +118,7 @@ when useWinUnicode: lpProcessAttributes: ptr TSECURITY_ATTRIBUTES, lpThreadAttributes: ptr TSECURITY_ATTRIBUTES, bInheritHandles: WINBOOL, dwCreationFlags: int32, - lpEnvironment: pointer, lpCurrentDirectory: widecstring, + lpEnvironment, lpCurrentDirectory: widecstring, lpStartupInfo: var TSTARTUPINFO, lpProcessInformation: var TPROCESS_INFORMATION): WINBOOL{. stdcall, dynlib: "kernel32", importc: "CreateProcessW".} diff --git a/web/news.txt b/web/news.txt index 906fb1108..57963407d 100644 --- a/web/news.txt +++ b/web/news.txt @@ -31,9 +31,9 @@ Bugfixes floating point values. - SCGI module's performance has been improved greatly, it will no longer block on many concurrent requests. - - In total fixed over 70 github issues and merged over 60 pull requests. + Library Additions ----------------- @@ -60,6 +60,8 @@ Changes affecting backwards compatibility - The expression/statement unification has been implemented. Again this only affects edge cases and no known real world code. - Changed the async interface of the ``scgi`` module. +- WideStrings are now garbage collected like other string types. + Compiler Additions ------------------ |