diff options
Diffstat (limited to 'lib')
203 files changed, 5736 insertions, 5380 deletions
diff --git a/lib/core/hotcodereloading.nim b/lib/core/hotcodereloading.nim index 73f38402d..3a876885c 100644 --- a/lib/core/hotcodereloading.nim +++ b/lib/core/hotcodereloading.nim @@ -11,7 +11,7 @@ when defined(hotcodereloading): import - macros + std/macros template beforeCodeReload*(body: untyped) = hcrAddEventHandler(true, proc = body) {.executeOnReload.} diff --git a/lib/core/locks.nim b/lib/core/locks.nim index ad0bff44d..523727479 100644 --- a/lib/core/locks.nim +++ b/lib/core/locks.nim @@ -37,7 +37,7 @@ proc initLock*(lock: var Lock) {.inline.} = when not defined(js): initSysLock(lock) -proc deinitLock*(lock: var Lock) {.inline.} = +proc deinitLock*(lock: Lock) {.inline.} = ## Frees the resources associated with the lock. deinitSys(lock) @@ -60,7 +60,7 @@ proc initCond*(cond: var Cond) {.inline.} = ## Initializes the given condition variable. initSysCond(cond) -proc deinitCond*(cond: var Cond) {.inline.} = +proc deinitCond*(cond: Cond) {.inline.} = ## Frees the resources associated with the condition variable. deinitSysCond(cond) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 01a654b6c..7646b165c 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -93,6 +93,8 @@ type nnkFuncDef, nnkTupleConstr, nnkError, ## erroneous AST node + nnkModuleRef, nnkReplayAction, nnkNilRodNode ## internal IC nodes + nnkOpenSym NimNodeKinds* = set[NimNodeKind] NimTypeKind* = enum # some types are no longer used, see ast.nim @@ -277,7 +279,7 @@ when (NimMajor, NimMinor, NimPatch) >= (1, 3, 5) or defined(nimSymImplTransform) ## note that code transformations are implementation dependent and subject to change. ## See an example in `tests/macros/tmacros_various.nim`. -proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.} +proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect, deprecated.} ## Accepts a node of kind `nnkSym` and returns its owner's symbol. ## The meaning of 'owner' depends on `sym`'s `NimSymKind` and declaration ## context. For top level declarations this is an `nskModule` symbol, @@ -347,8 +349,7 @@ proc getTypeImpl*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} = newLit(x.getTypeImpl.repr) let t = """ object - arr: array[0 .. 3, float32] -""" + arr: array[0 .. 3, float32]""" doAssert(dumpTypeImpl(a) == t) doAssert(dumpTypeImpl(b) == t) doAssert(dumpTypeImpl(c) == t) @@ -427,7 +428,12 @@ proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.} = let x = 12 echo x -proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign.} +when defined(nimHasNoReturnError): + {.pragma: errorNoReturn, noreturn.} +else: + {.pragma: errorNoReturn.} + +proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign, errorNoReturn.} ## Writes an error message at compile time. The optional `n: NimNode` ## parameter is used as the source for file and line number information in ## the compilation error message. @@ -1403,7 +1409,7 @@ proc `$`*(node: NimNode): string = result = node.basename.strVal & "*" of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkSym, nnkIdent: result = node.strVal - of nnkOpenSymChoice, nnkClosedSymChoice: + of nnkOpenSymChoice, nnkClosedSymChoice, nnkOpenSym: result = $node[0] of nnkAccQuoted: result = "" diff --git a/lib/core/rlocks.nim b/lib/core/rlocks.nim index bee5c1655..8cb0cef05 100644 --- a/lib/core/rlocks.nim +++ b/lib/core/rlocks.nim @@ -31,7 +31,7 @@ proc initRLock*(lock: var RLock) {.inline.} = else: initSysLock(lock) -proc deinitRLock*(lock: var RLock) {.inline.} = +proc deinitRLock*(lock: RLock) {.inline.} = ## Frees the resources associated with the lock. deinitSys(lock) diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index 5075c8458..f2fee91c4 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -129,7 +129,9 @@ when not defined(gcDestructors): else: proc nimNewObj(size, align: int): pointer {.importCompilerProc.} proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc.} - proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {. + proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {. + importCompilerProc.} + proc zeroNewElements(len: int; p: pointer; addlen, elemSize, elemAlign: int) {. importCompilerProc.} template `+!!`(a, b): untyped = cast[pointer](cast[int](a) + b) @@ -159,16 +161,6 @@ proc newAny(value: pointer, rawType: PNimType): Any {.inline.} = result.value = value result.rawType = rawType -when declared(system.VarSlot): - proc toAny*(x: VarSlot): Any {.inline.} = - ## Constructs an `Any` object from a variable slot `x`. - ## This captures `x`'s address, so `x` can be modified with its - ## `Any` wrapper! The caller needs to ensure that the wrapper - ## **does not** live longer than `x`! - ## This is provided for easier reflection capabilities of a debugger. - result.value = x.address - result.rawType = x.typ - proc toAny*[T](x: var T): Any {.inline.} = ## Constructs an `Any` object from `x`. This captures `x`'s address, so ## `x` can be modified with its `Any` wrapper! The caller needs to ensure @@ -221,7 +213,8 @@ proc extendSeq*(x: Any) = var s = cast[ptr NimSeqV2Reimpl](x.value) let elem = x.rawType.base if s.p == nil or s.p.cap < s.len+1: - s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAdd(s.len, s.p, 1, elem.size, elem.align)) + s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAddUninit(s.len, s.p, 1, elem.size, elem.align)) + zeroNewElements(s.len, s.p, 1, elem.size, elem.align) inc s.len else: var y = cast[ptr PGenSeq](x.value)[] diff --git a/lib/deprecated/pure/future.nim b/lib/deprecated/pure/future.nim index 3f7b63a30..0e06161f2 100644 --- a/lib/deprecated/pure/future.nim +++ b/lib/deprecated/pure/future.nim @@ -2,5 +2,5 @@ {.deprecated: "Use the new 'sugar' module instead".} -import sugar +import std/sugar export sugar diff --git a/lib/deprecated/pure/ospaths.nim b/lib/deprecated/pure/ospaths.nim index b57839d1a..43fcb17cc 100644 --- a/lib/deprecated/pure/ospaths.nim +++ b/lib/deprecated/pure/ospaths.nim @@ -11,7 +11,7 @@ {.deprecated: "use `std/os` instead".} -import os +import std/os export ReadEnvEffect, WriteEnvEffect, ReadDirEffect, WriteDirEffect, OSErrorCode, doslikeFileSystem, CurDir, ParDir, DirSep, AltSep, PathSep, FileSystemCaseSensitive, ExeExt, ScriptExt, DynlibFormat, ExtSep, joinPath, `/`, splitPath, parentDir, diff --git a/lib/deprecated/pure/oswalkdir.nim b/lib/deprecated/pure/oswalkdir.nim index 866f9ed70..57a2cb81d 100644 --- a/lib/deprecated/pure/oswalkdir.nim +++ b/lib/deprecated/pure/oswalkdir.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## This module is deprecated, `import os` instead. -{.deprecated: "import os.nim instead".} -import os +## This module is deprecated, `import std/os` instead. +{.deprecated: "import 'std/os' instead".} +import std/os export PathComponent, walkDir, walkDirRec diff --git a/lib/experimental/diff.nim b/lib/experimental/diff.nim index 4ca5eb319..669e9f613 100644 --- a/lib/experimental/diff.nim +++ b/lib/experimental/diff.nim @@ -43,7 +43,7 @@ jkl""" # "An O(ND) Difference Algorithm and its Variations" by Eugene Myers # Algorithmica Vol. 1 No. 2, 1986, p 251. -import tables, strutils +import std/[tables, strutils] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim index 2c1b1deae..39d238055 100644 --- a/lib/impure/nre.nim +++ b/lib/impure/nre.nim @@ -61,12 +61,12 @@ runnableExamples: assert find("uxabc", re"(?<=x|y)ab", start = 1).get.captures[-1] == "ab" assert find("uxabc", re"ab", start = 3).isNone -from pcre import nil +from std/pcre import nil import nre/private/util -import tables -from strutils import `%` -import options -from unicode import runeLenAt +import std/tables +from std/strutils import `%` +import std/options +from std/unicode import runeLenAt when defined(nimPreviewSlimSystem): import std/assertions @@ -217,9 +217,11 @@ type ## code. proc destroyRegex(pattern: Regex) = + `=destroy`(pattern.pattern) pcre.free_substring(cast[cstring](pattern.pcreObj)) if pattern.pcreExtra != nil: pcre.free_study(pattern.pcreExtra) + `=destroy`(pattern.captureNameToId) proc getinfo[T](pattern: Regex, opt: cint): T = let retcode = pcre.fullinfo(pattern.pcreObj, pattern.pcreExtra, opt, addr result) diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim index d227dcba3..ed8420776 100644 --- a/lib/impure/nre/private/util.nim +++ b/lib/impure/nre/private/util.nim @@ -1,5 +1,5 @@ ## INTERNAL FILE FOR USE ONLY BY nre.nim. -import tables +import std/tables const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} const StartIdent = Ident - {'0'..'9'} diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim index b0c648373..f4fc26380 100644 --- a/lib/impure/rdstdin.nim +++ b/lib/impure/rdstdin.nim @@ -55,7 +55,7 @@ elif defined(genode): stdin.readLine(line) else: - import linenoise + import std/linenoise proc readLineFromStdin*(prompt: string, line: var string): bool {. tags: [ReadIOEffect, WriteIOEffect].} = diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 5e84091c7..053c6ab55 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -36,7 +36,7 @@ runnableExamples: # can't match start of string since we're starting at 1 import - pcre, strutils, rtarrays + std/[pcre, strutils, rtarrays] when defined(nimPreviewSlimSystem): import std/syncio diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim index 8e2f85156..9b043f3e5 100644 --- a/lib/js/asyncjs.nim +++ b/lib/js/asyncjs.nim @@ -90,6 +90,8 @@ proc replaceReturn(node: var NimNode) = node[z] = nnkReturnStmt.newTree(value) elif son.kind == nnkAsgn and son[0].kind == nnkIdent and $son[0] == "result": node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(jsResolve, son[1])) + elif son.kind in RoutineNodes: + discard else: replaceReturn(son) inc z @@ -241,7 +243,7 @@ since (1, 5, 1): else: type A = impl(onSuccess(default(T))) var ret: A - asm "`ret` = `future`.then(`onSuccess`, `onReject`)" + {.emit: "`ret` = `future`.then(`onSuccess`, `onReject`);".} return ret proc catch*[T](future: Future[T], onReject: OnReject): Future[void] = @@ -264,4 +266,4 @@ since (1, 5, 1): discard main() - asm "`result` = `future`.catch(`onReject`)" + {.emit: "`result` = `future`.catch(`onReject`);".} diff --git a/lib/js/dom.nim b/lib/js/dom.nim index ceb0375b7..be2a34db1 100644 --- a/lib/js/dom.nim +++ b/lib/js/dom.nim @@ -1655,7 +1655,7 @@ proc item*(list: TouchList, i: int): Touch proc clearData*(dt: DataTransfer, format: cstring) proc getData*(dt: DataTransfer, format: cstring): cstring proc setData*(dt: DataTransfer, format: cstring, data: cstring) -proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int64, yOffset: int64) +proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int, yOffset: int) # DataTransferItem "methods" proc getAsFile*(dti: DataTransferItem): File @@ -1682,7 +1682,6 @@ proc `$`*(s: Selection): string = $(s.toString()) # Storage "methods" proc getItem*(s: Storage, key: cstring): cstring proc setItem*(s: Storage, key, value: cstring) -proc hasItem*(s: Storage, key: cstring): bool proc clear*(s: Storage) proc removeItem*(s: Storage, key: cstring) @@ -1832,3 +1831,11 @@ since (1, 7): proc matches*(self: Node; cssSelector: cstring): bool {.importjs: "(#.$1(#) || false)".} ## https://developer.mozilla.org/en-US/docs/Web/API/Element/matches + + +since (2, 1): + type VisualViewport* {.importc.} = ref object of EventTarget + offsetLeft*, offsetTop*, pageLeft*, pageTop*, width*, height*, scale*: float + onResize*, onScroll*: proc (event: Event) {.closure.} + + func visualViewport*(self: Window): VisualViewport {.importjs: "#.$1", nodecl.} diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index 08b1c6db9..d50d58ae5 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -468,7 +468,7 @@ proc replaceSyms(n: NimNode): NimNode = for i in 0..<n.len: result[i] = replaceSyms(n[i]) -macro bindMethod*(procedure: typed): auto = +macro bindMethod*(procedure: typed): auto {.deprecated: "Don't use it with closures".} = ## Takes the name of a procedure and wraps it into a lambda missing the first ## argument, which passes the JavaScript builtin `this` as the first ## argument to the procedure. Returns the resulting lambda. diff --git a/lib/js/jsre.nim b/lib/js/jsre.nim index 69bd75c3b..2d931eb20 100644 --- a/lib/js/jsre.nim +++ b/lib/js/jsre.nim @@ -58,7 +58,7 @@ func contains*(pattern: cstring; self: RegExp): bool = assert jsregex in r"abc" assert jsregex notin r"abcd" assert "xabc".contains jsregex - asm "`result` = `self`.test(`pattern`);" + {.emit: "`result` = `self`.test(`pattern`);".} func startsWith*(pattern: cstring; self: RegExp): bool = ## Tests if string starts with given RegExp diff --git a/lib/nimbase.h b/lib/nimbase.h index 3a1289b6f..cf0c8002b 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -14,6 +14,8 @@ __GNUC__ __TINYC__ __clang__ __AVR__ +__arm__ +__EMSCRIPTEN__ */ @@ -177,12 +179,13 @@ __AVR__ # define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name) # define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name) -# ifdef __cplusplus -# define N_LIB_EXPORT NIM_EXTERNC __declspec(dllexport) +# ifdef __EMSCRIPTEN__ +# define N_LIB_EXPORT NIM_EXTERNC __declspec(dllexport) __attribute__((used)) +# define N_LIB_EXPORT_VAR __declspec(dllexport) __attribute__((used)) # else # define N_LIB_EXPORT NIM_EXTERNC __declspec(dllexport) +# define N_LIB_EXPORT_VAR __declspec(dllexport) # endif -# define N_LIB_EXPORT_VAR __declspec(dllexport) # define N_LIB_IMPORT extern __declspec(dllimport) #else # define N_LIB_PRIVATE __attribute__((visibility("hidden"))) @@ -211,8 +214,13 @@ __AVR__ # define N_FASTCALL_PTR(rettype, name) rettype (*name) # define N_SAFECALL_PTR(rettype, name) rettype (*name) # endif -# define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"))) -# define N_LIB_EXPORT_VAR __attribute__((visibility("default"))) +# ifdef __EMSCRIPTEN__ +# define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"), used)) +# define N_LIB_EXPORT_VAR __attribute__((visibility("default"), used)) +# else +# define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"))) +# define N_LIB_EXPORT_VAR __attribute__((visibility("default"))) +# endif # define N_LIB_IMPORT extern #endif @@ -265,11 +273,15 @@ __AVR__ #elif defined(__cplusplus) #define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg) #else -#define NIM_STATIC_ASSERT(x, msg) typedef int NIM_STATIC_ASSERT_AUX[(x) ? 1 : -1]; +#define _NIM_STATIC_ASSERT_FINAL(x, append_name) typedef int NIM_STATIC_ASSERT_AUX ## append_name[(x) ? 1 : -1]; +#define _NIM_STATIC_ASSERT_STAGE_3(x, line) _NIM_STATIC_ASSERT_FINAL(x, _AT_LINE_##line) +#define _NIM_STATIC_ASSERT_STAGE_2(x, line) _NIM_STATIC_ASSERT_STAGE_3(x, line) +#define NIM_STATIC_ASSERT(x, msg) _NIM_STATIC_ASSERT_STAGE_2(x,__LINE__) // On failure, your C compiler will say something like: -// "error: 'NIM_STATIC_ASSERT_AUX' declared as an array with a negative size" -// we could use a better fallback to also show line number, using: -// http://www.pixelbeat.org/programming/gcc/static_assert.html +// "error: 'NIM_STATIC_ASSERT_AUX_AT_LINE_XXX' declared as an array with a negative size" +// Adding the line number helps to avoid redefinitions which are not allowed in +// old GCC versions, however the order of evaluation for __LINE__ is a little tricky, +// hence all the helper macros. See https://stackoverflow.com/a/3385694 for more info. #endif /* C99 compiler? */ @@ -466,7 +478,7 @@ typedef char* NCSTRING; /* declared size of a sequence/variable length array: */ #if defined(__cplusplus) && defined(__clang__) # define SEQ_DECL_SIZE 1 -#elif defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#elif defined(__GNUC__) || defined(_MSC_VER) # define SEQ_DECL_SIZE /* empty is correct! */ #else # define SEQ_DECL_SIZE 1000000 @@ -573,9 +585,16 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "P #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res) #if NIM_INTBITS == 32 - #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res) - #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res) - #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res) + #if defined(__arm__) && defined(__GNUC__) + /* arm-none-eabi-gcc targets defines int32_t as long int */ + #define nimAddInt(a, b, res) __builtin_saddl_overflow(a, b, res) + #define nimSubInt(a, b, res) __builtin_ssubl_overflow(a, b, res) + #define nimMulInt(a, b, res) __builtin_smull_overflow(a, b, res) + #else + #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res) + #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res) + #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res) + #endif #else /* map it to the 'long long' variant */ #define nimAddInt(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res) diff --git a/lib/nimhcr.nim b/lib/nimhcr.nim index 2a74cc92d..e87bb2413 100644 --- a/lib/nimhcr.nim +++ b/lib/nimhcr.nim @@ -219,7 +219,7 @@ when defined(createNimHcr): when system.appType != "lib": {.error: "This file has to be compiled as a library!".} - import os, tables, sets, times, strutils, reservedmem, dynlib + import std/[os, tables, sets, times, strutils, reservedmem, dynlib] template trace(args: varargs[untyped]) = when defined(testNimHcr) or defined(traceHcr): diff --git a/lib/nimrtl.nim b/lib/nimrtl.nim index 93349b287..a2fb6ce60 100644 --- a/lib/nimrtl.nim +++ b/lib/nimrtl.nim @@ -36,5 +36,5 @@ when not defined(createNimRtl): {.error: "This file has to be compiled with '-d:createNimRtl'".} import - parseutils, strutils, parseopt, parsecfg, strtabs, unicode, pegs, ropes, - os, osproc, times, cstrutils + std/[parseutils, strutils, parseopt, parsecfg, strtabs, unicode, pegs, ropes, + os, osproc, times, cstrutils] diff --git a/lib/packages/docutils/dochelpers.nim b/lib/packages/docutils/dochelpers.nim index 7b257ffff..0a41d85b5 100644 --- a/lib/packages/docutils/dochelpers.nim +++ b/lib/packages/docutils/dochelpers.nim @@ -13,7 +13,8 @@ ## `type LangSymbol`_ in ``rst.nim``, while `match(generated, docLink)`_ ## matches it with `generated`, produced from `PNode` by ``docgen.rst``. -import rstast, strutils +import rstast +import std/strutils when defined(nimPreviewSlimSystem): import std/[assertions, syncio] diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim index c3caf31b4..f8376f46c 100644 --- a/lib/packages/docutils/highlite.nim +++ b/lib/packages/docutils/highlite.nim @@ -57,8 +57,8 @@ ## as program output. import - strutils -from algorithm import binarySearch + std/strutils +from std/algorithm import binarySearch when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -324,17 +324,18 @@ proc nimNextToken(g: var GeneralTokenizer, keywords: openArray[string] = @[]) = pos = nimNumber(g, pos) of '\'': inc(pos) - g.kind = gtCharLit - while true: - case g.buf[pos] - of '\0', '\r', '\n': - break - of '\'': - inc(pos) - break - of '\\': - inc(pos, 2) - else: inc(pos) + if g.kind != gtPunctuation: + g.kind = gtCharLit + while true: + case g.buf[pos] + of '\0', '\r', '\n': + break + of '\'': + inc(pos) + break + of '\\': + inc(pos, 2) + else: inc(pos) of '\"': inc(pos) if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'): diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index a9bc4db91..706c50689 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -21,8 +21,10 @@ ## turned on by passing ``options:`` [RstParseOptions] to [proc rstParse]. import - os, strutils, rstast, dochelpers, std/enumutils, algorithm, lists, sequtils, - std/private/miscdollars, tables, strscans, rstidx + std/[os, strutils, enumutils, algorithm, lists, sequtils, + tables, strscans] +import dochelpers, rstidx, rstast +import std/private/miscdollars from highlite import SourceLanguage, getSourceLanguage when defined(nimPreviewSlimSystem): @@ -378,8 +380,8 @@ type kind: FootnoteType # discriminator number: int # valid for fnManualNumber (always) and fnAutoNumber, # fnAutoNumberLabel after resolveSubs is called - autoNumIdx: int # order of occurence: fnAutoNumber, fnAutoNumberLabel - autoSymIdx: int # order of occurence: fnAutoSymbol + autoNumIdx: int # order of occurrence: fnAutoNumber, fnAutoNumberLabel + autoSymIdx: int # order of occurrence: fnAutoSymbol label: string # valid for fnAutoNumberLabel RstFileTable* = object filenameToIdx*: Table[string, FileIndex] @@ -1524,7 +1526,7 @@ proc parseMarkdownCodeblockFields(p: var RstParser): PRstNode = result = nil else: result = newRstNode(rnFieldList) - while currentTok(p).kind != tkIndent: + while currentTok(p).kind notin {tkIndent, tkEof}: if currentTok(p).kind == tkWhite: inc p.idx else: @@ -1601,6 +1603,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode = else: args = nil var n = newLeaf("") + var isFirstLine = true while true: if currentTok(p).kind == tkEof: rstMessage(p, meMissingClosing, @@ -1612,7 +1615,8 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode = inc p.idx, 2 break elif currentTok(p).kind == tkIndent: - n.text.add "\n" + if not isFirstLine: + n.text.add "\n" if currentTok(p).ival > baseCol: n.text.add " ".repeat(currentTok(p).ival - baseCol) elif currentTok(p).ival < baseCol: @@ -1622,6 +1626,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode = else: n.text.add(currentTok(p).symbol) inc p.idx + isFirstLine = false result.sons[0] = args if result.sons[2] == nil: var lb = newRstNode(rnLiteralBlock) @@ -3650,114 +3655,114 @@ proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) loadIdxFile(s, origFilename) proc resolveLink(s: PRstSharedState, n: PRstNode) : PRstNode = - # Associate this link alias with its target and change node kind to - # rnHyperlink or rnInternalRef appropriately. - var desc, alias: PRstNode - if n.kind == rnPandocRef: # link like [desc][alias] - desc = n.sons[0] - alias = n.sons[1] - else: # n.kind == rnRstRef, link like `desc=alias`_ - desc = n - alias = n - type LinkDef = object - ar: AnchorRule - priority: int - tooltip: string - target: PRstNode - info: TLineInfo - externFilename: string - # when external anchor: origin filename where anchor was defined - isTitle: bool - proc cmp(x, y: LinkDef): int = - result = cmp(x.priority, y.priority) - if result == 0: - result = cmp(x.target, y.target) - var foundLinks: seq[LinkDef] - let refn = rstnodeToRefname(alias) - var hyperlinks = findRef(s, refn) - for y in hyperlinks: - foundLinks.add LinkDef(ar: arHyperlink, priority: refPriority(y.kind), - target: y.value, info: y.info, - tooltip: "(" & $y.kind & ")") - let substRst = findMainAnchorRst(s, alias.addNodes, n.info) - template getExternFilename(subst: AnchorSubst): string = - if subst.kind == arExternalRst or - (subst.kind == arNim and subst.external): - getFilename(s, subst) - else: "" - for subst in substRst: - var refname, fullRefname: string - if subst.kind == arInternalRst: - refname = subst.target.anchor - fullRefname = refname - else: # arExternalRst - refname = subst.refnameExt - fullRefname = s.idxImports[getFilename(s, subst)].linkRelPath & - "/" & refname - let anchorType = - if subst.kind == arInternalRst: subst.anchorType - else: subst.anchorTypeExt # arExternalRst + # Associate this link alias with its target and change node kind to + # rnHyperlink or rnInternalRef appropriately. + var desc, alias: PRstNode + if n.kind == rnPandocRef: # link like [desc][alias] + desc = n.sons[0] + alias = n.sons[1] + else: # n.kind == rnRstRef, link like `desc=alias`_ + desc = n + alias = n + type LinkDef = object + ar: AnchorRule + priority: int + tooltip: string + target: PRstNode + info: TLineInfo + externFilename: string + # when external anchor: origin filename where anchor was defined + isTitle: bool + proc cmp(x, y: LinkDef): int = + result = cmp(x.priority, y.priority) + if result == 0: + result = cmp(x.target, y.target) + var foundLinks: seq[LinkDef] + let refn = rstnodeToRefname(alias) + var hyperlinks = findRef(s, refn) + for y in hyperlinks: + foundLinks.add LinkDef(ar: arHyperlink, priority: refPriority(y.kind), + target: y.value, info: y.info, + tooltip: "(" & $y.kind & ")") + let substRst = findMainAnchorRst(s, alias.addNodes, n.info) + template getExternFilename(subst: AnchorSubst): string = + if subst.kind == arExternalRst or + (subst.kind == arNim and subst.external): + getFilename(s, subst) + else: "" + for subst in substRst: + var refname, fullRefname: string + if subst.kind == arInternalRst: + refname = subst.target.anchor + fullRefname = refname + else: # arExternalRst + refname = subst.refnameExt + fullRefname = s.idxImports[getFilename(s, subst)].linkRelPath & + "/" & refname + let anchorType = + if subst.kind == arInternalRst: subst.anchorType + else: subst.anchorTypeExt # arExternalRst + foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority, + target: newLeaf(fullRefname), + info: subst.info, + externFilename: getExternFilename(subst), + isTitle: isDocumentationTitle(refname), + tooltip: "(" & $anchorType & ")") + # find anchors automatically generated from Nim symbols + if roNimFile in s.options or s.nimFileImported: + let substNim = findMainAnchorNim(s, signature=alias, n.info) + for subst in substNim: + let fullRefname = + if subst.external: + s.idxImports[getFilename(s, subst)].linkRelPath & + "/" & subst.refname + else: subst.refname foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority, target: newLeaf(fullRefname), - info: subst.info, externFilename: getExternFilename(subst), - isTitle: isDocumentationTitle(refname), - tooltip: "(" & $anchorType & ")") - # find anchors automatically generated from Nim symbols - if roNimFile in s.options or s.nimFileImported: - let substNim = findMainAnchorNim(s, signature=alias, n.info) - for subst in substNim: - let fullRefname = - if subst.external: - s.idxImports[getFilename(s, subst)].linkRelPath & - "/" & subst.refname - else: subst.refname - foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority, - target: newLeaf(fullRefname), - externFilename: getExternFilename(subst), - isTitle: isDocumentationTitle(subst.refname), - info: subst.info, tooltip: subst.tooltip) - foundLinks.sort(cmp = cmp, order = Descending) - let aliasStr = addNodes(alias) - if foundLinks.len >= 1: + isTitle: isDocumentationTitle(subst.refname), + info: subst.info, tooltip: subst.tooltip) + foundLinks.sort(cmp = cmp, order = Descending) + let aliasStr = addNodes(alias) + if foundLinks.len >= 1: + if foundLinks[0].externFilename != "": + s.idxImports[foundLinks[0].externFilename].used = true + let kind = if foundLinks[0].ar in {arHyperlink, arExternalRst}: rnHyperlink + elif foundLinks[0].ar == arNim: + if foundLinks[0].externFilename == "": rnNimdocRef + else: rnHyperlink + else: rnInternalRef + result = newRstNode(kind) + let documentName = # filename without ext for `.nim`, title for `.md` + if foundLinks[0].ar == arNim: + changeFileExt(foundLinks[0].externFilename.extractFilename, "") + elif foundLinks[0].externFilename != "": + s.idxImports[foundLinks[0].externFilename].title + else: foundLinks[0].externFilename.extractFilename + let linkText = if foundLinks[0].externFilename != "": - s.idxImports[foundLinks[0].externFilename].used = true - let kind = if foundLinks[0].ar in {arHyperlink, arExternalRst}: rnHyperlink - elif foundLinks[0].ar == arNim: - if foundLinks[0].externFilename == "": rnNimdocRef - else: rnHyperlink - else: rnInternalRef - result = newRstNode(kind) - let documentName = # filename without ext for `.nim`, title for `.md` - if foundLinks[0].ar == arNim: - changeFileExt(foundLinks[0].externFilename.extractFilename, "") - elif foundLinks[0].externFilename != "": - s.idxImports[foundLinks[0].externFilename].title - else: foundLinks[0].externFilename.extractFilename - let linkText = - if foundLinks[0].externFilename != "": - if foundLinks[0].isTitle: newLeaf(addNodes(desc)) - else: newLeaf(documentName & ": " & addNodes(desc)) - else: - newRstNode(rnInner, desc.sons) - result.sons = @[linkText, foundLinks[0].target] - if kind == rnNimdocRef: result.tooltip = foundLinks[0].tooltip - if foundLinks.len > 1: # report ambiguous link - var targets = newSeq[string]() - for l in foundLinks: - var t = " " - if s.filenames.len > 1: - t.add getFilename(s.filenames, l.info.fileIndex) - let n = l.info.line - let c = l.info.col + ColRstOffset - t.add "($1, $2): $3" % [$n, $c, l.tooltip] - targets.add t - rstMessage(s.filenames, s.msgHandler, n.info, mwAmbiguousLink, - "`$1`\n clash:\n$2" % [ - aliasStr, targets.join("\n")]) - else: # nothing found - result = n - rstMessage(s.filenames, s.msgHandler, n.info, mwBrokenLink, aliasStr) + if foundLinks[0].isTitle: newLeaf(addNodes(desc)) + else: newLeaf(documentName & ": " & addNodes(desc)) + else: + newRstNode(rnInner, desc.sons) + result.sons = @[linkText, foundLinks[0].target] + if kind == rnNimdocRef: result.tooltip = foundLinks[0].tooltip + if foundLinks.len > 1: # report ambiguous link + var targets = newSeq[string]() + for l in foundLinks: + var t = " " + if s.filenames.len > 1: + t.add getFilename(s.filenames, l.info.fileIndex) + let n = l.info.line + let c = l.info.col + ColRstOffset + t.add "($1, $2): $3" % [$n, $c, l.tooltip] + targets.add t + rstMessage(s.filenames, s.msgHandler, n.info, mwAmbiguousLink, + "`$1`\n clash:\n$2" % [ + aliasStr, targets.join("\n")]) + else: # nothing found + result = n + rstMessage(s.filenames, s.msgHandler, n.info, mwBrokenLink, aliasStr) proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode = ## Makes pass 2 of RST parsing. diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim index c808318b5..2bbb0d0b8 100644 --- a/lib/packages/docutils/rstast.nim +++ b/lib/packages/docutils/rstast.nim @@ -9,7 +9,7 @@ ## This module implements an AST for the `reStructuredText`:idx: parser. -import strutils, json +import std/[strutils, json] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index f06e11de2..7fc0ac03a 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -39,10 +39,10 @@ ## No backreferences are generated since finding all references of a footnote ## can be done by simply searching for ``[footnoteName]``. -import strutils, os, hashes, strtabs, rstast, rst, rstidx, - highlite, tables, sequtils, - algorithm, parseutils, std/strbasics +import std/[strutils, os, hashes, strtabs, tables, sequtils, + algorithm, parseutils, strbasics] +import rstast, rst, rstidx, highlite when defined(nimPreviewSlimSystem): import std/[assertions, syncio, formatfloat] diff --git a/lib/packages/docutils/rstidx.nim b/lib/packages/docutils/rstidx.nim index 236b8361a..1472d28fd 100644 --- a/lib/packages/docutils/rstidx.nim +++ b/lib/packages/docutils/rstidx.nim @@ -7,8 +7,8 @@ ## Nim `idx`:idx: file format related definitions. -import strutils, std/syncio, hashes -from os import splitFile +import std/[strutils, syncio, hashes] +from std/os import splitFile type IndexEntryKind* = enum ## discriminator tag diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim index 7ee062e4f..007488354 100644 --- a/lib/posix/epoll.nim +++ b/lib/posix/epoll.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -from posix import SocketHandle +from std/posix import SocketHandle const EPOLLIN* = 0x00000001 diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim index 109d3680e..575accc18 100644 --- a/lib/posix/inotify.nim +++ b/lib/posix/inotify.nim @@ -14,12 +14,13 @@ when defined(nimPreviewSlimSystem): # Structure describing an inotify event. type InotifyEvent* {.pure, final, importc: "struct inotify_event", - header: "<sys/inotify.h>".} = object ## An Inotify event. + header: "<sys/inotify.h>", + completeStruct.} = object ## An Inotify event. wd* {.importc: "wd".}: FileHandle ## Watch descriptor. mask* {.importc: "mask".}: uint32 ## Watch mask. cookie* {.importc: "cookie".}: uint32 ## Cookie to synchronize two events. len* {.importc: "len".}: uint32 ## Length (including NULs) of name. - name* {.importc: "name".}: char ## Name. + name* {.importc: "name".}: UncheckedArray[char] ## Name. # Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. const @@ -66,7 +67,8 @@ proc inotify_init*(): FileHandle {.cdecl, importc: "inotify_init", proc inotify_init1*(flags: cint): FileHandle {.cdecl, importc: "inotify_init1", header: "<sys/inotify.h>".} - ## Create and initialize inotify instance. + ## Like `inotify_init<#inotify_init>`_ , + ## but has a flags argument that provides access to some extra functionality. proc inotify_add_watch*(fd: cint; name: cstring; mask: uint32): cint {.cdecl, importc: "inotify_add_watch", header: "<sys/inotify.h>".} @@ -78,11 +80,18 @@ proc inotify_rm_watch*(fd: cint; wd: cint): cint {.cdecl, iterator inotify_events*(evs: pointer, n: int): ptr InotifyEvent = ## Abstract the packed buffer interface to yield event object pointers. - ## ```Nim - ## var evs = newSeq[byte](8192) # Already did inotify_init+add_watch - ## while (let n = read(fd, evs[0].addr, 8192); n) > 0: # read forever - ## for e in inotify_events(evs[0].addr, n): echo e[].len # echo name lens - ## ``` + runnableExamples("-r:off"): + when defined(linux): + import std/posix # needed for FileHandle read procedure + const MaxWatches = 8192 + + let inotifyFd = inotify_init() # create new inotify instance and get it's FileHandle + let wd = inotifyFd.inotify_add_watch("/tmp", IN_CREATE or IN_DELETE) # Add new watch + + var events: array[MaxWatches, byte] # event buffer + while (let n = read(inotifyFd, addr events, MaxWatches); n) > 0: # blocks until any events have been read + for e in inotify_events(addr events, n): + echo (e[].wd, e[].mask, cast[cstring](addr e[].name)) # echo watch id, mask, and name value of each event var ev: ptr InotifyEvent = cast[ptr InotifyEvent](evs) var n = n while n > 0: @@ -93,8 +102,10 @@ iterator inotify_events*(evs: pointer, n: int): ptr InotifyEvent = runnableExamples: when defined(linux): - let inoty: FileHandle = inotify_init() ## Create 1 Inotify. - doAssert inoty >= 0 ## Check for errors (FileHandle is alias to cint). - let watchdoge: cint = inotify_add_watch(inoty, ".", IN_ALL_EVENTS) ## Add directory to watchdog. - doAssert watchdoge >= 0 ## Check for errors. - doAssert inotify_rm_watch(inoty, watchdoge) >= 0 ## Remove directory from the watchdog + let inotifyFd = inotify_init() # create and get new inotify FileHandle + doAssert inotifyFd >= 0 # check for errors + + let wd = inotifyFd.inotify_add_watch("/tmp", IN_CREATE or IN_DELETE) # Add new watch + doAssert wd >= 0 # check for errors + + discard inotifyFd.inotify_rm_watch(wd) # remove watch diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim index c83ae33ea..2450cdb42 100644 --- a/lib/posix/kqueue.nim +++ b/lib/posix/kqueue.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -from posix import Timespec +from std/posix import Timespec when defined(macosx) or defined(freebsd) or defined(openbsd) or defined(dragonfly): diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim index 9a5e9f062..29fd4288d 100644 --- a/lib/posix/linux.nim +++ b/lib/posix/linux.nim @@ -1,4 +1,4 @@ -import posix +import std/posix ## Flags of `clone` syscall. ## See `clone syscall manual diff --git a/lib/posix/posix_macos_amd64.nim b/lib/posix/posix_macos_amd64.nim index d6b5834cb..a4b64ed62 100644 --- a/lib/posix/posix_macos_amd64.nim +++ b/lib/posix/posix_macos_amd64.nim @@ -122,10 +122,14 @@ type ## used for block sizes Clock* {.importc: "clock_t", header: "<sys/types.h>".} = int ClockId* {.importc: "clockid_t", header: "<sys/types.h>".} = int - Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32 + Dev* {.importc: "dev_t", header: "<sys/types.h>".} = ( + when defined(freebsd): + uint32 + else: + int32) Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int - Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32 + Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32 Id* {.importc: "id_t", header: "<sys/types.h>".} = int Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int Key* {.importc: "key_t", header: "<sys/types.h>".} = int @@ -135,7 +139,7 @@ type else: uint16 ) - Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = int16 + Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = uint16 Off* {.importc: "off_t", header: "<sys/types.h>".} = int64 Pid* {.importc: "pid_t", header: "<sys/types.h>".} = int32 Pthread_attr* {.importc: "pthread_attr_t", header: "<sys/types.h>".} = int @@ -167,7 +171,7 @@ type Trace_event_set* {.importc: "trace_event_set_t", header: "<sys/types.h>".} = int Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int - Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32 + Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32 Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int Utsname* {.importc: "struct utsname", @@ -462,9 +466,9 @@ type header: "<netinet/in.h>".} = object ## struct sockaddr_in6 sin6_family*: TSa_Family ## AF_INET6. sin6_port*: InPort ## Port number. - sin6_flowinfo*: int32 ## IPv6 traffic class and flow information. + sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information. sin6_addr*: In6Addr ## IPv6 address. - sin6_scope_id*: int32 ## Set of interfaces for a scope. + sin6_scope_id*: uint32 ## Set of interfaces for a scope. Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final, header: "<netinet/in.h>".} = object ## struct ipv6_mreq @@ -491,7 +495,7 @@ type ## alternative network names, terminated by a ## null pointer. n_addrtype*: cint ## The address type of the network. - n_net*: int32 ## The network number, in host byte order. + n_net*: uint32 ## The network number, in host byte order. Protoent* {.importc: "struct protoent", pure, final, header: "<netdb.h>".} = object ## struct protoent diff --git a/lib/posix/posix_openbsd_amd64.nim b/lib/posix/posix_openbsd_amd64.nim index 1ef4a4182..184cd89c0 100644 --- a/lib/posix/posix_openbsd_amd64.nim +++ b/lib/posix/posix_openbsd_amd64.nim @@ -131,15 +131,19 @@ type ## used for block sizes Clock* {.importc: "clock_t", header: "<sys/types.h>".} = int ClockId* {.importc: "clockid_t", header: "<sys/types.h>".} = int - Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32 + Dev* {.importc: "dev_t", header: "<sys/types.h>".} = ( + when defined(freebsd): + uint32 + else: + int32) Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int - Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32 + Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32 Id* {.importc: "id_t", header: "<sys/types.h>".} = int Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int Key* {.importc: "key_t", header: "<sys/types.h>".} = int Mode* {.importc: "mode_t", header: "<sys/types.h>".} = uint32 - Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = int16 + Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = uint32 Off* {.importc: "off_t", header: "<sys/types.h>".} = int64 Pid* {.importc: "pid_t", header: "<sys/types.h>".} = int32 Pthread_attr* {.importc: "pthread_attr_t", header: "<pthread.h>".} = int @@ -171,7 +175,7 @@ type Trace_event_set* {.importc: "trace_event_set_t", header: "<sys/types.h>".} = int Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int - Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32 + Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32 Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int Utsname* {.importc: "struct utsname", @@ -446,9 +450,9 @@ type header: "<netinet/in.h>".} = object ## struct sockaddr_in6 sin6_family*: TSa_Family ## AF_INET6. sin6_port*: InPort ## Port number. - sin6_flowinfo*: int32 ## IPv6 traffic class and flow information. + sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information. sin6_addr*: In6Addr ## IPv6 address. - sin6_scope_id*: int32 ## Set of interfaces for a scope. + sin6_scope_id*: uint32 ## Set of interfaces for a scope. Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final, header: "<netinet/in.h>".} = object ## struct ipv6_mreq @@ -475,7 +479,7 @@ type ## alternative network names, terminated by a ## null pointer. n_addrtype*: cint ## The address type of the network. - n_net*: int32 ## The network number, in host byte order. + n_net*: uint32 ## The network number, in host byte order. Protoent* {.importc: "struct protoent", pure, final, header: "<netdb.h>".} = object ## struct protoent diff --git a/lib/posix/posix_utils.nim b/lib/posix/posix_utils.nim index 7e4a2eeda..0c668246f 100644 --- a/lib/posix/posix_utils.nim +++ b/lib/posix/posix_utils.nim @@ -11,7 +11,7 @@ # Where possible, contribute OS-independent procs in `os <os.html>`_ instead. -import posix, parsecfg, os +import std/[posix, parsecfg, os] import std/private/since when defined(nimPreviewSlimSystem): @@ -34,7 +34,7 @@ proc uname*(): Uname = var u: Utsname if uname(u) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) result.sysname = charArrayToString u.sysname result.nodename = charArrayToString u.nodename @@ -45,17 +45,17 @@ proc uname*(): Uname = proc fsync*(fd: int) = ## synchronize a file's buffer cache to the storage device if fsync(fd.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc stat*(path: string): Stat = ## Returns file status in a `Stat` structure if stat(path.cstring, result) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryLock*(a1: pointer, a2: int) = ## Locks pages starting from a1 for a1 bytes and prevent them from being swapped. if mlock(a1, a2) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryLockAll*(flags: int) = ## Locks all memory for the running process to prevent swapping. @@ -65,23 +65,23 @@ proc memoryLockAll*(flags: int) = ## memoryLockAll(MCL_CURRENT or MCL_FUTURE) ## ``` if mlockall(flags.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryUnlock*(a1: pointer, a2: int) = ## Unlock pages starting from a1 for a1 bytes and allow them to be swapped. if munlock(a1, a2) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryUnlockAll*() = ## Unlocks all memory for the running process to allow swapping. if munlockall() != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc sendSignal*(pid: Pid, signal: int) = ## Sends a signal to a running process by calling `kill`. ## Raise exception in case of failure e.g. process not running. if kill(pid, signal.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc mkstemp*(prefix: string, suffix=""): (string, File) = ## Creates a unique temporary file from a prefix string. A six-character string @@ -103,14 +103,14 @@ proc mkstemp*(prefix: string, suffix=""): (string, File) = var f: File if open(f, fd, fmReadWrite): return ($tmpl, f) - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc mkdtemp*(prefix: string): string = ## Creates a unique temporary directory from a prefix string. Adds a six chars suffix. ## The directory is created with permissions 0700. Returns the directory name. var tmpl = cstring(prefix & "XXXXXX") if mkdtemp(tmpl) == nil: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) return $tmpl proc osReleaseFile*(): Config {.since: (1, 5).} = diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim index f755c720d..7fb6bb81c 100644 --- a/lib/posix/termios.nim +++ b/lib/posix/termios.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -import posix +import std/posix type Speed* = cuint diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 65402e9fb..b12ed7cdd 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -387,7 +387,7 @@ func sort*[T](a: var openArray[T], ## ``` ## ## You can inline adhoc comparison procs with the `do notation - ## <manual_experimental.html#do-notation>`_. Example: + ## <manual.html#procedures-do-notation>`_. Example: ## ## ```nim ## people.sort do (x, y: Person) -> int: diff --git a/lib/pure/async.nim b/lib/pure/async.nim index 249c5f639..e4d8d41c3 100644 --- a/lib/pure/async.nim +++ b/lib/pure/async.nim @@ -2,8 +2,8 @@ ## and [asyncjs](asyncjs.html) on the JS backend. when defined(js): - import asyncjs + import std/asyncjs export asyncjs else: - import asyncmacro, asyncfutures + import std/[asyncmacro, asyncfutures] export asyncmacro, asyncfutures diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 24c1ec3d5..126db7a7f 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -226,11 +226,11 @@ ## ``none`` can be used when a library supports both a synchronous and ## asynchronous API, to disable the latter. -import os, tables, strutils, times, heapqueue, options, asyncstreams -import options, math, std/monotimes -import asyncfutures except callSoon +import std/[os, tables, strutils, times, heapqueue, options, asyncstreams] +import std/[math, monotimes] +import std/asyncfutures except callSoon -import nativesockets, net, deques +import std/[nativesockets, net, deques] when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -302,7 +302,7 @@ template implementSetInheritable() {.dirty.} = fd.FileHandle.setInheritable(inheritable) when defined(windows) or defined(nimdoc): - import winlean, sets, hashes + import std/[winlean, sets, hashes] type CompletionKey = ULONG_PTR @@ -533,7 +533,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(errcode): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if dataBuf.buf != nil: dealloc dataBuf.buf dataBuf.buf = nil @@ -551,7 +551,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) elif ret == 0: # Request completed immediately. if bytesReceived != 0: @@ -603,7 +603,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(errcode): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if dataBuf.buf != nil: dataBuf.buf = nil ) @@ -619,7 +619,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) elif ret == 0: # Request completed immediately. if bytesReceived != 0: @@ -667,7 +667,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: retFuture.complete() # We don't deallocate `ol` here because even though this completed @@ -702,7 +702,7 @@ when defined(windows) or defined(nimdoc): if errcode == OSErrorCode(-1): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let ret = WSASendTo(socket.SocketHandle, addr dataBuf, 1, addr bytesSent, @@ -712,7 +712,7 @@ when defined(windows) or defined(nimdoc): let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: retFuture.complete() # We don't deallocate `ol` here because even though this completed @@ -746,7 +746,7 @@ when defined(windows) or defined(nimdoc): else: # datagram sockets don't have disconnection, # so we can just raise an exception - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let res = WSARecvFrom(socket.SocketHandle, addr dataBuf, 1, @@ -757,7 +757,7 @@ when defined(windows) or defined(nimdoc): let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. if bytesReceived != 0: @@ -808,7 +808,7 @@ when defined(windows) or defined(nimdoc): else: retFuture.complete(newAcceptFut.read) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) template completeAccept() {.dirty.} = var listenSock = socket @@ -1166,11 +1166,11 @@ when defined(windows) or defined(nimdoc): initAll() else: - import selectors - from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK, + import std/selectors + from std/posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK, MSG_NOSIGNAL when declared(posix.accept4): - from posix import accept4, SOCK_CLOEXEC + from std/posix import accept4, SOCK_CLOEXEC when defined(genode): import genode/env # get the implicit Genode env import genode/signals @@ -1468,7 +1468,7 @@ else: if flags.isDisconnectionError(lastError): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -1497,7 +1497,7 @@ else: if flags.isDisconnectionError(lastError): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -1563,7 +1563,7 @@ else: let lastError = osLastError() if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -1589,7 +1589,7 @@ else: let lastError = osLastError() if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false else: @@ -1630,7 +1630,7 @@ else: if flags.isDisconnectionError(lastError): return false else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: try: let address = getAddrString(cast[ptr SockAddr](addr sockAddress)) @@ -1763,7 +1763,7 @@ when defined(windows) or defined(nimdoc): socket.SocketHandle.setSockOptInt(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, 1) # 15022 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, @@ -1781,7 +1781,7 @@ when defined(windows) or defined(nimdoc): # With ERROR_IO_PENDING `ol` will be deallocated in `poll`, # and the future will be completed/failed there, too. GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): owned(Future[void]) = let retFuture = newFuture[void]("doConnect") @@ -1798,7 +1798,7 @@ else: # interrupted, keep waiting return false else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true let ret = connect(socket.SocketHandle, @@ -1812,7 +1812,7 @@ else: if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: addWrite(socket, cb) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, protocol: Protocol = IPPROTO_RAW) = @@ -1994,7 +1994,7 @@ proc send*(socket: AsyncFD, data: string, return retFuture # -- Await Macro -import asyncmacro +import std/asyncmacro export asyncmacro proc readAll*(future: FutureStream[string]): owned(Future[string]) {.async.} = @@ -2032,7 +2032,7 @@ proc activeDescriptors*(): int {.inline.} = result = getGlobalDispatcher().selector.count when defined(posix): - import posix + import std/posix when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or defined(solaris) or defined(zephyr) or defined(freertos) or defined(nuttx) or defined(haiku): diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim index 96d5e6d2e..0f6504342 100644 --- a/lib/pure/asyncfile.nim +++ b/lib/pure/asyncfile.nim @@ -23,7 +23,7 @@ ## waitFor main() ## ``` -import asyncdispatch, os +import std/[asyncdispatch, os] when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -33,9 +33,9 @@ when defined(nimPreviewSlimSystem): # TODO: Fix duplication introduced by PR #4683. when defined(windows) or defined(nimdoc): - import winlean + import std/winlean else: - import posix + import std/posix type AsyncFile* = ref object @@ -146,7 +146,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if errcode.int32 == ERROR_HANDLE_EOF: retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) ol.offset = DWORD(f.offset and 0xffffffff) ol.offsetHigh = DWORD(f.offset shr 32) @@ -162,7 +162,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = # This happens in Windows Server 2003 retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesRead: DWORD @@ -173,7 +173,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if err.int32 == ERROR_HANDLE_EOF: retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesRead > 0 assert bytesRead <= size @@ -186,7 +186,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -228,7 +228,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if errcode.int32 == ERROR_HANDLE_EOF: retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if buffer != nil: dealloc buffer buffer = nil @@ -251,7 +251,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = # This happens in Windows Server 2003 retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesRead: DWORD @@ -262,7 +262,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if err.int32 == ERROR_HANDLE_EOF: retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesRead > 0 assert bytesRead <= size @@ -279,7 +279,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -301,6 +301,8 @@ proc readLine*(f: AsyncFile): Future[string] {.async.} = result = "" while true: var c = await read(f, 1) + if c.len == 0: + break if c[0] == '\c': c = await read(f, 1) break @@ -348,7 +350,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = assert bytesCount == size.int32 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) # passing -1 here should work according to MSDN, but doesn't. For more # information see @@ -365,14 +367,14 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesWritten: DWORD let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL) if not overlappedRes.bool: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesWritten == size.int32 retFuture.complete() @@ -387,7 +389,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -421,7 +423,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = assert bytesCount == data.len.int32 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if buffer != nil: dealloc buffer buffer = nil @@ -440,14 +442,14 @@ proc write*(f: AsyncFile, data: string): Future[void] = dealloc buffer buffer = nil GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesWritten: DWORD let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL) if not overlappedRes.bool: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesWritten == data.len.int32 retFuture.complete() @@ -468,7 +470,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: diff --git a/lib/pure/asyncfutures.nim b/lib/pure/asyncfutures.nim index 51aaaca36..29ebf8f89 100644 --- a/lib/pure/asyncfutures.nim +++ b/lib/pure/asyncfutures.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -import os, tables, strutils, times, heapqueue, options, deques, cstrutils +import std/[os, tables, strutils, times, heapqueue, options, deques, cstrutils, typetraits] import system/stacktraces @@ -51,7 +51,7 @@ const NimAsyncContinueSuffix* = "NimAsyncContinue" ## For internal usage. Do not use. when isFutureLoggingEnabled: - import hashes + import std/hashes type FutureInfo* = object stackTrace*: seq[StackTraceEntry] @@ -193,7 +193,7 @@ proc add(callbacks: var CallbackList, function: CallbackFunc) = last = last.next last.next = newCallback -proc completeImpl[T, U](future: Future[T], val: U, isVoid: static bool) = +proc completeImpl[T, U](future: Future[T], val: sink U, isVoid: static bool) = #assert(not future.finished, "Future already finished, cannot finish twice.") checkFinished(future) assert(future.error == nil) @@ -203,7 +203,7 @@ proc completeImpl[T, U](future: Future[T], val: U, isVoid: static bool) = future.callbacks.call() when isFutureLoggingEnabled: logFutureFinish(future) -proc complete*[T](future: Future[T], val: T) = +proc complete*[T](future: Future[T], val: sink T) = ## Completes `future` with value `val`. completeImpl(future, val, false) @@ -219,7 +219,7 @@ proc complete*[T](future: FutureVar[T]) = fut.callbacks.call() when isFutureLoggingEnabled: logFutureFinish(Future[T](future)) -proc complete*[T](future: FutureVar[T], val: T) = +proc complete*[T](future: FutureVar[T], val: sink T) = ## Completes a `FutureVar` with value `val`. ## ## Any previously stored value will be overwritten. @@ -370,11 +370,7 @@ proc injectStacktrace[T](future: Future[T]) = # newMsg.add "\n" & $entry future.error.msg = newMsg -proc read*[T](future: Future[T] | FutureVar[T]): T = - ## Retrieves the value of `future`. Future must be finished otherwise - ## this function will fail with a `ValueError` exception. - ## - ## If the result of the future is an error then that error will be raised. +template readImpl(future, T) = when future is Future[T]: let fut {.cursor.} = future else: @@ -384,11 +380,21 @@ proc read*[T](future: Future[T] | FutureVar[T]): T = injectStacktrace(fut) raise fut.error when T isnot void: - result = fut.value + result = distinctBase(future).value else: # TODO: Make a custom exception type for this? raise newException(ValueError, "Future still in progress.") +proc read*[T](future: Future[T] | FutureVar[T]): lent T = + ## Retrieves the value of `future`. Future must be finished otherwise + ## this function will fail with a `ValueError` exception. + ## + ## If the result of the future is an error then that error will be raised. + readImpl(future, T) + +proc read*(future: Future[void] | FutureVar[void]) = + readImpl(future, void) + proc readError*[T](future: Future[T]): ref Exception = ## Retrieves the exception stored in `future`. ## diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 07eed9a51..39e945d5e 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -39,9 +39,9 @@ runnableExamples("-r:off"): waitFor main() -import asyncnet, asyncdispatch, parseutils, uri, strutils -import httpcore -from nativesockets import getLocalAddr, Domain, AF_INET, AF_INET6 +import std/[asyncnet, asyncdispatch, parseutils, uri, strutils] +import std/httpcore +from std/nativesockets import getLocalAddr, Domain, AF_INET, AF_INET6 import std/private/since when defined(nimPreviewSlimSystem): diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index a026e159e..d4e72c28a 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -9,7 +9,7 @@ ## Implements the `async` and `multisync` macros for `asyncdispatch`. -import macros, strutils, asyncfutures +import std/[macros, strutils, asyncfutures] type Context = ref object diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 2fc8d366e..ee07e599e 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -99,7 +99,7 @@ import std/private/since when defined(nimPreviewSlimSystem): import std/[assertions, syncio] -import asyncdispatch, nativesockets, net, os +import std/[asyncdispatch, nativesockets, net, os] export SOBool @@ -110,7 +110,7 @@ const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr defined(nuttx) when defineSsl: - import openssl + import std/openssl type # TODO: I would prefer to just do: @@ -682,12 +682,12 @@ when defined(posix) and not useNimNetLite: elif ret == EINTR: return false else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true var socketAddr = makeUnixAddr(path) let ret = socket.fd.connect(cast[ptr SockAddr](addr socketAddr), - (sizeof(socketAddr.sun_family) + path.len).SockLen) + (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) if ret == 0: # Request to connect completed immediately. retFuture.complete() @@ -696,7 +696,7 @@ when defined(posix) and not useNimNetLite: if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: addWrite(AsyncFD(socket.fd), cb) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) proc bindUnix*(socket: AsyncSocket, path: string) {. tags: [ReadIOEffect].} = @@ -705,7 +705,7 @@ when defined(posix) and not useNimNetLite: when not defined(nimdoc): var socketAddr = makeUnixAddr(path) if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), - (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32: + (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32: raiseOSError(osLastError()) elif defined(nimdoc): diff --git a/lib/pure/asyncstreams.nim b/lib/pure/asyncstreams.nim index 3f7774ed8..c97b98d55 100644 --- a/lib/pure/asyncstreams.nim +++ b/lib/pure/asyncstreams.nim @@ -9,12 +9,12 @@ ## Unstable API. -import asyncfutures +import std/asyncfutures when defined(nimPreviewSlimSystem): import std/assertions -import deques +import std/deques type FutureStream*[T] = ref object ## Special future that acts as diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 795820433..591d22cc0 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -66,15 +66,11 @@ template cbBase(a, b): untyped = [ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', a, b] -let +const cb64 = cbBase('+', '/') cb64safe = cbBase('-', '_') const - cb64VM = cbBase('+', '/') - cb64safeVM = cbBase('-', '_') - -const invalidChar = 255 template encodeSize(size: int): int = (size * 4 div 3) + 6 @@ -134,14 +130,10 @@ template encodeInternal(s, alphabet: typed): untyped = result.setLen(outputIndex) template encodeImpl() {.dirty.} = - when nimvm: - block: - let lookupTableVM = if safe: cb64safeVM else: cb64VM - encodeInternal(s, lookupTableVM) + if safe: + encodeInternal(s, cb64safe) else: - block: - let lookupTable = if safe: unsafeAddr(cb64safe) else: unsafeAddr(cb64) - encodeInternal(s, lookupTable) + encodeInternal(s, cb64) proc encode*[T: byte|char](s: openArray[T], safe = false): string = ## Encodes `s` into base64 representation. @@ -252,7 +244,7 @@ proc decode*(s: string): string = inputLen = s.len inputEnds = 0 # strip trailing characters - while s[inputLen - 1] in {'\n', '\r', ' ', '='}: + while inputLen > 0 and s[inputLen - 1] in {'\n', '\r', ' ', '='}: dec inputLen # hot loop: read 4 characters at at time inputEnds = inputLen - 4 diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index d19c3d248..0d3351ee5 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -25,7 +25,7 @@ ## At this time only `fastLog2`, `firstSetBit`, `countLeadingZeroBits` and `countTrailingZeroBits` ## may return undefined and/or platform dependent values if given invalid input. -import macros +import std/macros import std/private/since from std/private/bitops_utils import forwardImpl, castToUnsigned @@ -65,7 +65,7 @@ type BitsRange*[T] = range[0..sizeof(T)*8-1] template typeMasked[T: SomeInteger](x: T): T = when defined(js): - x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8))) + T(x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8)))) else: x @@ -463,7 +463,7 @@ elif useVCC_builtins: importc: "_BitScanForward64", header: "<intrin.h>".} template vcc_scan_impl(fnc: untyped; v: untyped): int = - var index: culong + var index {.inject.}: culong = 0 discard fnc(index.addr, v) index.int diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim index a98d9d5b8..59e2078df 100644 --- a/lib/pure/browsers.nim +++ b/lib/pure/browsers.nim @@ -12,22 +12,22 @@ ## ## Unstable API. -import std/private/since +import std/private/since # used by the deprecated `openDefaultBrowser()` -import strutils +import std/strutils when defined(nimPreviewSlimSystem): import std/assertions when defined(windows): - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/widestrs - from os import absolutePath + from std/os import absolutePath else: - import os + import std/os when not defined(osx): - import osproc + import std/osproc const osOpenCmd* = when defined(macos) or defined(macosx) or defined(windows): "open" else: "xdg-open" ## \ @@ -40,7 +40,7 @@ proc prepare(s: string): string = else: result = "file://" & absolutePath(s) -proc openDefaultBrowserImplPrep(url: string) = +proc openDefaultBrowserRaw(url: string) = ## note the url argument should be alreadly prepared, i.e. the url is passed "AS IS" when defined(windows): @@ -60,9 +60,6 @@ proc openDefaultBrowserImplPrep(url: string) = except OSError: discard -proc openDefaultBrowserImpl(url: string) = - openDefaultBrowserImplPrep(prepare url) - proc openDefaultBrowser*(url: string) = ## Opens `url` with the user's default browser. This does not block. ## The URL must not be empty string, to open on a blank page see `openDefaultBrowser()`. @@ -78,16 +75,30 @@ proc openDefaultBrowser*(url: string) = ## block: openDefaultBrowser("https://nim-lang.org") ## ``` doAssert url.len > 0, "URL must not be empty string" - openDefaultBrowserImpl(url) + openDefaultBrowserRaw(url) -proc openDefaultBrowser*() {.since: (1, 1).} = - ## Opens the user's default browser without any `url` (blank page). This does not block. - ## Implements IETF RFC-6694 Section 3, "about:blank" must be reserved for a blank page. +proc openDefaultBrowser*() {.since: (1, 1), deprecated: + "not implemented, please open with a specific url instead".} = + ## Intends to open the user's default browser without any `url` (blank page). + ## This does not block. + ## Intends to implement IETF RFC-6694 Section 3, + ## ("about:blank" is reserved for a blank page). ## - ## Under Windows, `ShellExecute` is used. Under Mac OS X the `open` - ## command is used. Under Unix, it is checked if `xdg-open` exists and - ## used if it does. Otherwise the environment variable `BROWSER` is - ## used to determine the default browser to use. + ## Beware that this intended behavior is **not** implemented and + ## considered not worthy to implement here. + ## + ## The following describes the behavior of current implementation: + ## + ## - Under Windows, this will only cause a pop-up dialog \ + ## asking the assocated application with `about` \ + ## (as Windows simply treats `about:` as a protocol like `http`). + ## - Under Mac OS X the `open "about:blank"` command is used. + ## - Under Unix, it is checked if `xdg-open` exists and used \ + ## if it does and open the application assocated with `text/html` mime \ + ## (not `x-scheme-handler/http`, so maybe html-viewer \ + ## other than your default browser is opened). \ + ## Otherwise the environment variable `BROWSER` is used \ + ## to determine the default browser to use. ## ## This proc doesn't raise an exception on error, beware. ## @@ -98,4 +109,4 @@ proc openDefaultBrowser*() {.since: (1, 1).} = ## **See also:** ## ## * https://tools.ietf.org/html/rfc6694#section-3 - openDefaultBrowserImplPrep("about:blank") # See IETF RFC-6694 Section 3. + openDefaultBrowserRaw("about:blank") # See IETF RFC-6694 Section 3. diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim index e761569a1..034f224ac 100644 --- a/lib/pure/cgi.nim +++ b/lib/pure/cgi.nim @@ -29,7 +29,7 @@ ## writeLine(stdout, "</body></html>") ## ``` -import strutils, os, strtabs, cookies, uri +import std/[strutils, os, strtabs, cookies, uri] export uri.encodeUrl, uri.decodeUrl when defined(nimPreviewSlimSystem): diff --git a/lib/pure/collections/deques.nim b/lib/pure/collections/deques.nim index ed58028c8..d2b0099f2 100644 --- a/lib/pure/collections/deques.nim +++ b/lib/pure/collections/deques.nim @@ -50,7 +50,7 @@ runnableExamples: import std/private/since -import math +import std/[assertions, hashes, math] type Deque*[T] = object @@ -59,20 +59,29 @@ type ## To initialize an empty deque, ## use the `initDeque proc <#initDeque,int>`_. data: seq[T] - head, tail, count, mask: int + + # `head` and `tail` are masked only when accessing an element of `data` + # so that `tail - head == data.len` when the deque is full. + # They are uint so that incrementing/decrementing them doesn't cause + # over/underflow. You can get a number of items with `tail - head` + # even if `tail` or `head` is wraps around and `tail < head`, because + # `tail - head == (uint.high + 1 + tail) - head` when `tail < head`. + head, tail: uint const defaultInitialSize* = 4 template initImpl(result: typed, initialSize: int) = let correctSize = nextPowerOfTwo(initialSize) - result.mask = correctSize - 1 newSeq(result.data, correctSize) template checkIfInitialized(deq: typed) = - if deq.mask == 0: + if deq.data.len == 0: initImpl(deq, defaultInitialSize) +func mask[T](deq: Deque[T]): uint {.inline.} = + uint(deq.data.len) - 1 + proc initDeque*[T](initialSize: int = defaultInitialSize): Deque[T] = ## Creates a new empty deque. ## @@ -85,22 +94,22 @@ proc initDeque*[T](initialSize: int = defaultInitialSize): Deque[T] = ## * `toDeque proc <#toDeque,openArray[T]>`_ result.initImpl(initialSize) -proc len*[T](deq: Deque[T]): int {.inline.} = +func len*[T](deq: Deque[T]): int {.inline.} = ## Returns the number of elements of `deq`. - result = deq.count + int(deq.tail - deq.head) template emptyCheck(deq) = # Bounds check for the regular deque access. when compileOption("boundChecks"): - if unlikely(deq.count < 1): + if unlikely(deq.len < 1): raise newException(IndexDefect, "Empty deque.") template xBoundsCheck(deq, i) = # Bounds check for the array like accesses. when compileOption("boundChecks"): # `-d:danger` or `--checks:off` should disable this. - if unlikely(i >= deq.count): # x < deq.low is taken care by the Natural parameter + if unlikely(i >= deq.len): # x < deq.low is taken care by the Natural parameter raise newException(IndexDefect, - "Out of bounds: " & $i & " > " & $(deq.count - 1)) + "Out of bounds: " & $i & " > " & $(deq.len - 1)) if unlikely(i < 0): # when used with BackwardsIndex raise newException(IndexDefect, "Out of bounds: " & $i & " < 0") @@ -114,7 +123,7 @@ proc `[]`*[T](deq: Deque[T], i: Natural): lent T {.inline.} = doAssertRaises(IndexDefect, echo a[8]) xBoundsCheck(deq, i) - return deq.data[(deq.head + i) and deq.mask] + return deq.data[(deq.head + i.uint) and deq.mask] proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} = ## Accesses the `i`-th element of `deq` and returns a mutable @@ -125,7 +134,7 @@ proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} = assert a[0] == 11 xBoundsCheck(deq, i) - return deq.data[(deq.head + i) and deq.mask] + return deq.data[(deq.head + i.uint) and deq.mask] proc `[]=`*[T](deq: var Deque[T], i: Natural, val: sink T) {.inline.} = ## Sets the `i`-th element of `deq` to `val`. @@ -137,7 +146,7 @@ proc `[]=`*[T](deq: var Deque[T], i: Natural, val: sink T) {.inline.} = checkIfInitialized(deq) xBoundsCheck(deq, i) - deq.data[(deq.head + i) and deq.mask] = val + deq.data[(deq.head + i.uint) and deq.mask] = val proc `[]`*[T](deq: Deque[T], i: BackwardsIndex): lent T {.inline.} = ## Accesses the backwards indexed `i`-th element. @@ -190,10 +199,8 @@ iterator items*[T](deq: Deque[T]): lent T = let a = [10, 20, 30, 40, 50].toDeque assert toSeq(a.items) == @[10, 20, 30, 40, 50] - var i = deq.head - for c in 0 ..< deq.count: - yield deq.data[i] - i = (i + 1) and deq.mask + for c in 0 ..< deq.len: + yield deq.data[(deq.head + c.uint) and deq.mask] iterator mitems*[T](deq: var Deque[T]): var T = ## Yields every element of `deq`, which can be modified. @@ -207,10 +214,8 @@ iterator mitems*[T](deq: var Deque[T]): var T = x = 5 * x - 1 assert $a == "[49, 99, 149, 199, 249]" - var i = deq.head - for c in 0 ..< deq.count: - yield deq.data[i] - i = (i + 1) and deq.mask + for c in 0 ..< deq.len: + yield deq.data[(deq.head + c.uint) and deq.mask] iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] = ## Yields every `(position, value)`-pair of `deq`. @@ -220,10 +225,8 @@ iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] = let a = [10, 20, 30].toDeque assert toSeq(a.pairs) == @[(0, 10), (1, 20), (2, 30)] - var i = deq.head - for c in 0 ..< deq.count: - yield (c, deq.data[i]) - i = (i + 1) and deq.mask + for c in 0 ..< deq.len: + yield (c, deq.data[(deq.head + c.uint) and deq.mask]) proc contains*[T](deq: Deque[T], item: T): bool {.inline.} = ## Returns true if `item` is in `deq` or false if not found. @@ -242,8 +245,9 @@ proc contains*[T](deq: Deque[T], item: T): bool {.inline.} = proc expandIfNeeded[T](deq: var Deque[T]) = checkIfInitialized(deq) - var cap = deq.mask + 1 - if unlikely(deq.count >= cap): + let cap = deq.data.len + assert deq.len <= cap + if unlikely(deq.len == cap): var n = newSeq[T](cap * 2) var i = 0 for x in mitems(deq): @@ -251,8 +255,7 @@ proc expandIfNeeded[T](deq: var Deque[T]) = else: n[i] = move(x) inc i deq.data = move(n) - deq.mask = cap * 2 - 1 - deq.tail = deq.count + deq.tail = cap.uint deq.head = 0 proc addFirst*[T](deq: var Deque[T], item: sink T) = @@ -267,9 +270,8 @@ proc addFirst*[T](deq: var Deque[T], item: sink T) = assert $a == "[50, 40, 30, 20, 10]" expandIfNeeded(deq) - inc deq.count - deq.head = (deq.head - 1) and deq.mask - deq.data[deq.head] = item + dec deq.head + deq.data[deq.head and deq.mask] = item proc addLast*[T](deq: var Deque[T], item: sink T) = ## Adds an `item` to the end of `deq`. @@ -283,9 +285,8 @@ proc addLast*[T](deq: var Deque[T], item: sink T) = assert $a == "[10, 20, 30, 40, 50]" expandIfNeeded(deq) - inc deq.count - deq.data[deq.tail] = item - deq.tail = (deq.tail + 1) and deq.mask + deq.data[deq.tail and deq.mask] = item + inc deq.tail proc toDeque*[T](x: openArray[T]): Deque[T] {.since: (1, 3).} = ## Creates a new deque that contains the elements of `x` (in the same order). @@ -314,7 +315,7 @@ proc peekFirst*[T](deq: Deque[T]): lent T {.inline.} = assert len(a) == 5 emptyCheck(deq) - result = deq.data[deq.head] + result = deq.data[deq.head and deq.mask] proc peekLast*[T](deq: Deque[T]): lent T {.inline.} = ## Returns the last element of `deq`, but does not remove it from the deque. @@ -344,7 +345,7 @@ proc peekFirst*[T](deq: var Deque[T]): var T {.inline, since: (1, 3).} = assert $a == "[99, 20, 30, 40, 50]" emptyCheck(deq) - result = deq.data[deq.head] + result = deq.data[deq.head and deq.mask] proc peekLast*[T](deq: var Deque[T]): var T {.inline, since: (1, 3).} = ## Returns a mutable reference to the last element of `deq`, @@ -377,9 +378,8 @@ proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} = assert $a == "[20, 30, 40, 50]" emptyCheck(deq) - dec deq.count - result = move deq.data[deq.head] - deq.head = (deq.head + 1) and deq.mask + result = move deq.data[deq.head and deq.mask] + inc deq.head proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} = ## Removes and returns the last element of the `deq`. @@ -394,9 +394,8 @@ proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} = assert $a == "[10, 20, 30, 40]" emptyCheck(deq) - dec deq.count - deq.tail = (deq.tail - 1) and deq.mask - result = move deq.data[deq.tail] + dec deq.tail + result = move deq.data[deq.tail and deq.mask] proc clear*[T](deq: var Deque[T]) {.inline.} = ## Resets the deque so that it is empty. @@ -410,7 +409,6 @@ proc clear*[T](deq: var Deque[T]) {.inline.} = assert len(a) == 0 for el in mitems(deq): destroy(el) - deq.count = 0 deq.tail = deq.head proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) = @@ -430,19 +428,17 @@ proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) = a.shrink(fromFirst = 2, fromLast = 1) assert $a == "[30, 40]" - if fromFirst + fromLast > deq.count: + if fromFirst + fromLast > deq.len: clear(deq) return for i in 0 ..< fromFirst: - destroy(deq.data[deq.head]) - deq.head = (deq.head + 1) and deq.mask + destroy(deq.data[deq.head and deq.mask]) + inc deq.head for i in 0 ..< fromLast: destroy(deq.data[(deq.tail - 1) and deq.mask]) - deq.tail = (deq.tail - 1) and deq.mask - - dec deq.count, fromFirst + fromLast + dec deq.tail proc `$`*[T](deq: Deque[T]): string = ## Turns a deque into its string representation. @@ -455,3 +451,30 @@ proc `$`*[T](deq: Deque[T]): string = if result.len > 1: result.add(", ") result.addQuoted(x) result.add("]") + +func `==`*[T](deq1, deq2: Deque[T]): bool = + ## The `==` operator for Deque. + ## Returns `true` if both deques contains the same values in the same order. + runnableExamples: + var a, b = initDeque[int]() + a.addFirst(2) + a.addFirst(1) + b.addLast(1) + b.addLast(2) + doAssert a == b + + if deq1.len != deq2.len: + return false + + for i in 0 ..< deq1.len: + if deq1.data[(deq1.head + i.uint) and deq1.mask] != deq2.data[(deq2.head + i.uint) and deq2.mask]: + return false + + true + +func hash*[T](deq: Deque[T]): Hash = + ## Hashing of Deque. + var h: Hash = 0 + for x in deq: + h = h !& hash(x) + !$h diff --git a/lib/pure/collections/hashcommon.nim b/lib/pure/collections/hashcommon.nim index 8fd4c6e08..17785c8c7 100644 --- a/lib/pure/collections/hashcommon.nim +++ b/lib/pure/collections/hashcommon.nim @@ -58,7 +58,10 @@ proc rawGetKnownHC[X, A](t: X, key: A, hc: Hash): int {.inline.} = template genHashImpl(key, hc: typed) = hc = hash(key) if hc == 0: # This almost never taken branch should be very predictable. - hc = 314159265 # Value doesn't matter; Any non-zero favorite is fine. + when sizeof(int) < 4: + hc = 31415 # Value doesn't matter; Any non-zero favorite is fine <= 16-bit. + else: + hc = 314159265 # Value doesn't matter; Any non-zero favorite is fine. template genHash(key: typed): Hash = var res: Hash diff --git a/lib/pure/collections/heapqueue.nim b/lib/pure/collections/heapqueue.nim index bcfdf37c2..96f9b4430 100644 --- a/lib/pure/collections/heapqueue.nim +++ b/lib/pure/collections/heapqueue.nim @@ -47,6 +47,9 @@ runnableExamples: import std/private/since +when defined(nimPreviewSlimSystem): + import std/assertions + type HeapQueue*[T] = object ## A heap queue, commonly known as a priority queue. data: seq[T] @@ -73,6 +76,13 @@ proc `[]`*[T](heap: HeapQueue[T], i: Natural): lent T {.inline.} = ## Accesses the i-th element of `heap`. heap.data[i] +iterator items*[T](heap: HeapQueue[T]): lent T {.inline, since: (2, 1, 1).} = + ## Iterates over each item of `heap`. + let L = len(heap) + for i in 0 .. high(heap.data): + yield heap.data[i] + assert(len(heap) == L, "the length of the HeapQueue changed while iterating over it") + proc heapCmp[T](x, y: T): bool {.inline.} = x < y proc siftup[T](heap: var HeapQueue[T], startpos, p: int) = @@ -178,6 +188,11 @@ proc find*[T](heap: HeapQueue[T], x: T): int {.since: (1, 3).} = for i in 0 ..< heap.len: if heap[i] == x: return i +proc contains*[T](heap: HeapQueue[T], x: T): bool {.since: (2, 1, 1).} = + ## Returns true if `x` is in `heap` or false if not found. This is a shortcut + ## for `find(heap, x) >= 0`. + result = find(heap, x) >= 0 + proc del*[T](heap: var HeapQueue[T], index: Natural) = ## Removes the element at `index` from `heap`, maintaining the heap invariant. runnableExamples: diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index b9d5c48eb..6b88747ef 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -384,9 +384,7 @@ proc prependMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} = assert s == [0, 1, 0, 1, 0, 1] b.addMoved(a) - when defined(js): # XXX: swap broken in js; bug #16771 - (b, a) = (a, b) - else: swap a, b + swap a, b proc add*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} = ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1). @@ -983,6 +981,17 @@ func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: ( for elem in elems.items: result.add(elem) +func toSinglyLinkedRing*[T](elems: openArray[T]): SinglyLinkedRing[T] = + ## Creates a new `SinglyLinkedRing` from the members of `elems`. + runnableExamples: + from std/sequtils import toSeq + let a = [1, 2, 3, 4, 5].toSinglyLinkedRing + assert a.toSeq == [1, 2, 3, 4, 5] + + result = initSinglyLinkedRing[T]() + for elem in elems.items: + result.add(elem) + func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} = ## Creates a new `DoublyLinkedList` from the members of `elems`. runnableExamples: @@ -993,3 +1002,14 @@ func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: ( result = initDoublyLinkedList[T]() for elem in elems.items: result.add(elem) + +func toDoublyLinkedRing*[T](elems: openArray[T]): DoublyLinkedRing[T] = + ## Creates a new `DoublyLinkedRing` from the members of `elems`. + runnableExamples: + from std/sequtils import toSeq + let a = [1, 2, 3, 4, 5].toDoublyLinkedRing + assert a.toSeq == [1, 2, 3, 4, 5] + + result = initDoublyLinkedRing[T]() + for elem in elems.items: + result.add(elem) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index e2adba910..3c0d8dc0e 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -82,7 +82,8 @@ runnableExamples: import std/private/since -import macros +import std/macros +from std/typetraits import supportsCopyMem when defined(nimPreviewSlimSystem): import std/assertions @@ -140,6 +141,22 @@ func concat*[T](seqs: varargs[seq[T]]): seq[T] = result[i] = itm inc(i) +func addUnique*[T](s: var seq[T], x: sink T) = + ## Adds `x` to the container `s` if it is not already present. + ## Uses `==` to check if the item is already present. + runnableExamples: + var a = @[1, 2, 3] + a.addUnique(4) + a.addUnique(4) + assert a == @[1, 2, 3, 4] + + for i in 0..high(s): + if s[i] == x: return + when declared(ensureMove): + s.add ensureMove(x) + else: + s.add x + func count*[T](s: openArray[T], x: T): int = ## Returns the number of occurrences of the item `x` in the container `s`. ## @@ -1086,8 +1103,12 @@ template newSeqWith*(len: int, init: untyped): untyped = import std/random var seqRand = newSeqWith(20, rand(1.0)) assert seqRand[0] != seqRand[1] + type T = typeof(init) let newLen = len - var result = newSeq[typeof(init)](newLen) + when supportsCopyMem(T) and declared(newSeqUninit): + var result = newSeqUninit[T](newLen) + else: # TODO: use `newSeqUnsafe` when that's available + var result = newSeq[T](newLen) for i in 0 ..< newLen: result[i] = init move(result) # refs bug #7295 diff --git a/lib/pure/collections/setimpl.nim b/lib/pure/collections/setimpl.nim index dbd4ce1d5..360a075d6 100644 --- a/lib/pure/collections/setimpl.nim +++ b/lib/pure/collections/setimpl.nim @@ -87,7 +87,9 @@ proc exclImpl[A](s: var HashSet[A], key: A): bool {.inline.} = var j = i # The correctness of this depends on (h+1) in nextTry, var r = j # though may be adaptable to other simple sequences. s.data[i].hcode = 0 # mark current EMPTY - s.data[i].key = default(typeof(s.data[i].key)) + {.push warning[UnsafeDefault]:off.} + reset(s.data[i].key) + {.pop.} doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)): i = (i + 1) and msk # increment mod table size if isEmpty(s.data[i].hcode): # end of collision cluster; So all done diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 62abd68d4..af13135aa 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -50,7 +50,7 @@ import - hashes, math + std/[hashes, math] when not defined(nimHasEffectsOf): {.pragma: effectsOf.} @@ -382,7 +382,9 @@ proc clear*[A](s: var HashSet[A]) = s.counter = 0 for i in 0 ..< s.data.len: s.data[i].hcode = 0 - s.data[i].key = default(typeof(s.data[i].key)) + {.push warning[UnsafeDefault]:off.} + reset(s.data[i].key) + {.pop.} proc union*[A](s1, s2: HashSet[A]): HashSet[A] = @@ -816,7 +818,9 @@ proc clear*[A](s: var OrderedSet[A]) = for i in 0 ..< s.data.len: s.data[i].hcode = 0 s.data[i].next = 0 - s.data[i].key = default(typeof(s.data[i].key)) + {.push warning[UnsafeDefault]:off.} + reset(s.data[i].key) + {.pop.} proc len*[A](s: OrderedSet[A]): int {.inline.} = ## Returns the number of elements in `s`. diff --git a/lib/pure/collections/sharedlist.nim b/lib/pure/collections/sharedlist.nim index e61883220..ec8f1cd86 100644 --- a/lib/pure/collections/sharedlist.nim +++ b/lib/pure/collections/sharedlist.nim @@ -16,7 +16,7 @@ {.push stackTrace: off.} import - locks + std/locks const ElemsPerNode = 100 diff --git a/lib/pure/collections/sharedtables.nim b/lib/pure/collections/sharedtables.nim index 8b49066ac..b474ecd31 100644 --- a/lib/pure/collections/sharedtables.nim +++ b/lib/pure/collections/sharedtables.nim @@ -17,7 +17,7 @@ {.deprecated.} import - hashes, math, locks + std/[hashes, math, locks] type KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B] diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim index 112aaa7d0..3542741fa 100644 --- a/lib/pure/collections/tableimpl.nim +++ b/lib/pure/collections/tableimpl.nim @@ -45,7 +45,7 @@ template addImpl(enlarge) {.dirty.} = rawInsert(t, t.data, key, val, hc, j) inc(t.counter) -template maybeRehashPutImpl(enlarge) {.dirty.} = +template maybeRehashPutImpl(enlarge, val) {.dirty.} = checkIfInitialized() if mustRehash(t): enlarge(t) @@ -59,7 +59,7 @@ template putImpl(enlarge) {.dirty.} = var hc: Hash = default(Hash) var index = rawGet(t, key, hc) if index >= 0: t.data[index].val = val - else: maybeRehashPutImpl(enlarge) + else: maybeRehashPutImpl(enlarge, val) template mgetOrPutImpl(enlarge) {.dirty.} = checkIfInitialized() @@ -67,17 +67,30 @@ template mgetOrPutImpl(enlarge) {.dirty.} = var index = rawGet(t, key, hc) if index < 0: # not present: insert (flipping index) - maybeRehashPutImpl(enlarge) + when declared(val): + maybeRehashPutImpl(enlarge, val) + else: + maybeRehashPutImpl(enlarge, default(B)) # either way return modifiable val result = t.data[index].val +# template mgetOrPutDefaultImpl(enlarge) {.dirty.} = +# checkIfInitialized() +# var hc: Hash = default(Hash) +# var index = rawGet(t, key, hc) +# if index < 0: +# # not present: insert (flipping index) +# maybeRehashPutImpl(enlarge, default(B)) +# # either way return modifiable val +# result = t.data[index].val + template hasKeyOrPutImpl(enlarge) {.dirty.} = checkIfInitialized() var hc: Hash = default(Hash) var index = rawGet(t, key, hc) if index < 0: result = false - maybeRehashPutImpl(enlarge) + maybeRehashPutImpl(enlarge, val) else: result = true # delImplIdx is KnuthV3 Algo6.4R adapted to i=i+1 (from i=i-1) which has come to @@ -119,8 +132,10 @@ template delImplIdx(t, i, makeEmpty, cellEmpty, cellHash) = var j = i # The correctness of this depends on (h+1) in nextTry var r = j # though may be adaptable to other simple sequences. makeEmpty(i) # mark current EMPTY - t.data[i].key = default(typeof(t.data[i].key)) - t.data[i].val = default(typeof(t.data[i].val)) + {.push warning[UnsafeDefault]:off.} + reset(t.data[i].key) + reset(t.data[i].val) + {.pop.} while true: i = (i + 1) and msk # increment mod table size if cellEmpty(i): # end of collision cluster; So all done @@ -151,8 +166,10 @@ template clearImpl() {.dirty.} = for i in 0 ..< t.dataLen: when compiles(t.data[i].hcode): # CountTable records don't contain a hcode t.data[i].hcode = 0 - t.data[i].key = default(typeof(t.data[i].key)) - t.data[i].val = default(typeof(t.data[i].val)) + {.push warning[UnsafeDefault]:off.} + reset(t.data[i].key) + reset(t.data[i].val) + {.pop.} t.counter = 0 template ctAnd(a, b): bool = diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 39dcddb5a..d414caeed 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -194,7 +194,7 @@ runnableExamples: import std/private/since -import hashes, math, algorithm +import std/[hashes, math, algorithm] when not defined(nimHasEffectsOf): @@ -278,6 +278,7 @@ proc initTable*[A, B](initialSize = defaultInitialSize): Table[A, B] = let a = initTable[int, string]() b = initTable[char, seq[int]]() + result = default(Table[A, B]) initImpl(result, initialSize) proc `[]=`*[A, B](t: var Table[A, B], key: A, val: sink B) = @@ -312,7 +313,7 @@ proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] = result = initTable[A, B](pairs.len) for key, val in items(pairs): result[key] = val -proc `[]`*[A, B](t: Table[A, B], key: A): B = +proc `[]`*[A, B](t: Table[A, B], key: A): lent B = ## Retrieves the value at `t[key]`. ## ## If `key` is not in `t`, the `KeyError` exception is raised. @@ -474,6 +475,18 @@ proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B = mgetOrPutImpl(enlarge) +proc mgetOrPut*[A, B](t: var Table[A, B], key: A): var B = + ## Retrieves the value at `t[key]` or puts the + ## default initialization value for type `B` (e.g. 0 for any + ## integer type). + runnableExamples: + var a = {'a': 5}.newTable + doAssert a.mgetOrPut('a') == 5 + a.mgetOrPut('z').inc + doAssert a == {'a': 5, 'z': 1}.newTable + + mgetOrPutImpl(enlarge) + proc len*[A, B](t: Table[A, B]): int = ## Returns the number of keys in `t`. runnableExamples: @@ -1013,6 +1026,18 @@ proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B = doAssert t[25] == @[25, 35] t[].mgetOrPut(key, val) +proc mgetOrPut*[A, B](t: TableRef[A, B], key: A): var B = + ## Retrieves the value at `t[key]` or puts the + ## default initialization value for type `B` (e.g. 0 for any + ## integer type). + runnableExamples: + var a = {'a': 5}.newTable + doAssert a.mgetOrPut('a') == 5 + a.mgetOrPut('z').inc + doAssert a == {'a': 5, 'z': 1}.newTable + + t[].mgetOrPut(key) + proc len*[A, B](t: TableRef[A, B]): int = ## Returns the number of keys in `t`. runnableExamples: @@ -1322,6 +1347,7 @@ proc initOrderedTable*[A, B](initialSize = defaultInitialSize): OrderedTable[A, let a = initOrderedTable[int, string]() b = initOrderedTable[char, seq[int]]() + result = default(OrderedTable[A, B]) initImpl(result, initialSize) proc `[]=`*[A, B](t: var OrderedTable[A, B], key: A, val: sink B) = @@ -1357,7 +1383,7 @@ proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] = result = initOrderedTable[A, B](pairs.len) for key, val in items(pairs): result[key] = val -proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B = +proc `[]`*[A, B](t: OrderedTable[A, B], key: A): lent B = ## Retrieves the value at `t[key]`. ## ## If `key` is not in `t`, the `KeyError` exception is raised. @@ -1413,7 +1439,7 @@ proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool = doAssert a.hasKey('a') == true doAssert a.hasKey('z') == false - var hc: Hash + var hc: Hash = default(Hash) result = rawGet(t, key, hc) >= 0 proc contains*[A, B](t: OrderedTable[A, B], key: A): bool = @@ -1503,6 +1529,18 @@ proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B = mgetOrPutImpl(enlarge) +proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A): var B = + ## Retrieves the value at `t[key]` or puts the + ## default initialization value for type `B` (e.g. 0 for any + ## integer type). + runnableExamples: + var a = {'a': 5}.toOrderedTable + doAssert a.mgetOrPut('a') == 5 + a.mgetOrPut('z').inc + doAssert a == {'a': 5, 'z': 1}.toOrderedTable + + mgetOrPutImpl(enlarge) + proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} = ## Returns the number of keys in `t`. runnableExamples: @@ -1992,6 +2030,18 @@ proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B = result = t[].mgetOrPut(key, val) +proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A): var B = + ## Retrieves the value at `t[key]` or puts the + ## default initialization value for type `B` (e.g. 0 for any + ## integer type). + runnableExamples: + var a = {'a': 5}.toOrderedTable + doAssert a.mgetOrPut('a') == 5 + a.mgetOrPut('z').inc + doAssert a == {'a': 5, 'z': 1}.toOrderedTable + + t[].mgetOrPut(key) + proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} = ## Returns the number of keys in `t`. runnableExamples: @@ -2288,6 +2338,7 @@ proc initCountTable*[A](initialSize = defaultInitialSize): CountTable[A] = ## * `toCountTable proc<#toCountTable,openArray[A]>`_ ## * `newCountTable proc<#newCountTable>`_ for creating a ## `CountTableRef` + result = default(CountTable[A]) initImpl(result, initialSize) proc toCountTable*[A](keys: openArray[A]): CountTable[A] = diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index eccccbfaf..d3e6dc063 100644 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -9,8 +9,8 @@ ## This module implements color handling for Nim, ## namely color mixing and parsing the CSS color names. -import strutils -from algorithm import binarySearch +import std/strutils +from std/algorithm import binarySearch type Color* = distinct int ## A color stored as RGB, e.g. `0xff00cc`. diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 1e8349ef6..b48811eae 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -15,9 +15,6 @@ runnableExamples: from std/math import almostEqual, sqrt - func almostEqual(a, b: Complex): bool = - almostEqual(a.re, b.re) and almostEqual(a.im, b.im) - let z1 = complex(1.0, 2.0) z2 = complex(3.0, -4.0) @@ -36,7 +33,7 @@ runnableExamples: {.push checks: off, line_dir: off, stack_trace: off, debugger: off.} # the user does not want to trace a part of the standard library! -import math +import std/[math, strformat] type Complex*[T: SomeFloat] = object @@ -81,7 +78,7 @@ func abs2*[T](z: Complex[T]): T = ## that is the squared distance from (0, 0) to `z`. ## This is more efficient than `abs(z) ^ 2`. result = z.re * z.re + z.im * z.im - + func sgn*[T](z: Complex[T]): Complex[T] = ## Returns the phase of `z` as a unit complex number, ## or 0 if `z` is 0. @@ -249,10 +246,31 @@ func pow*[T](x, y: Complex[T]): Complex[T] = else: result.re = 0.0 result.im = 0.0 - elif y.re == 1.0 and y.im == 0.0: - result = x - elif y.re == -1.0 and y.im == 0.0: - result = T(1.0) / x + elif y.im == 0.0: + if y.re == 1.0: + result = x + elif y.re == -1.0: + result = T(1.0) / x + elif y.re == 2.0: + result = x * x + elif y.re == 0.5: + result = sqrt(x) + elif x.im == 0.0: + # Revert to real pow when both base and exponent are real + result.re = pow(x.re, y.re) + result.im = 0.0 + else: + # Special case when the exponent is real + let + rho = abs(x) + theta = arctan2(x.im, x.re) + s = pow(rho, y.re) + r = y.re * theta + result.re = s * cos(r) + result.im = s * sin(r) + elif x.im == 0.0 and x.re == E: + # Special case Euler's formula + result = exp(y) else: let rho = abs(x) @@ -391,6 +409,24 @@ func rect*[T](r, phi: T): Complex[T] = ## * `polar func<#polar,Complex[T]>`_ for the inverse operation complex(r * cos(phi), r * sin(phi)) +func almostEqual*[T: SomeFloat](x, y: Complex[T]; unitsInLastPlace: Natural = 4): bool = + ## Checks if two complex values are almost equal, using the + ## [machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon). + ## + ## Two complex values are considered almost equal if their real and imaginary + ## components are almost equal. + ## + ## `unitsInLastPlace` is the max number of + ## [units in the last place](https://en.wikipedia.org/wiki/Unit_in_the_last_place) + ## difference tolerated when comparing two numbers. The larger the value, the + ## more error is allowed. A `0` value means that two numbers must be exactly the + ## same to be considered equal. + ## + ## The machine epsilon has to be scaled to the magnitude of the values used + ## and multiplied by the desired precision in ULPs unless the difference is + ## subnormal. + almostEqual(x.re, y.re, unitsInLastPlace = unitsInLastPlace) and + almostEqual(x.im, y.im, unitsInLastPlace = unitsInLastPlace) func `$`*(z: Complex): string = ## Returns `z`'s string representation as `"(re, im)"`. @@ -399,4 +435,39 @@ func `$`*(z: Complex): string = result = "(" & $z.re & ", " & $z.im & ")" +proc formatValueAsTuple(result: var string; value: Complex; specifier: string) = + ## Format implementation for `Complex` representing the value as a (real, imaginary) tuple. + result.add "(" + formatValue(result, value.re, specifier) + result.add ", " + formatValue(result, value.im, specifier) + result.add ")" + +proc formatValueAsComplexNumber(result: var string; value: Complex; specifier: string) = + ## Format implementation for `Complex` representing the value as a (RE+IMj) number + ## By default, the real and imaginary parts are formatted using the general ('g') format + let specifier = if specifier.contains({'e', 'E', 'f', 'F', 'g', 'G'}): + specifier.replace("j") + else: + specifier.replace('j', 'g') + result.add "(" + formatValue(result, value.re, specifier) + if value.im >= 0 and not specifier.contains({'+', '-'}): + result.add "+" + formatValue(result, value.im, specifier) + result.add "j)" + +proc formatValue*(result: var string; value: Complex; specifier: string) = + ## Standard format implementation for `Complex`. It makes little + ## sense to call this directly, but it is required to exist + ## by the `&` macro. + ## For complex numbers, we add a specific 'j' specifier, which formats + ## the value as (A+Bj) like in mathematics. + if specifier.len == 0: + result.add $value + elif 'j' in specifier: + formatValueAsComplexNumber(result, value, specifier) + else: + formatValueAsTuple(result, value, specifier) + {.pop.} diff --git a/lib/pure/concurrency/atomics.nim b/lib/pure/concurrency/atomics.nim index c7b881bc5..818f1b37a 100644 --- a/lib/pure/concurrency/atomics.nim +++ b/lib/pure/concurrency/atomics.nim @@ -10,6 +10,9 @@ ## Types and operations for atomic operations and lockless algorithms. ## ## Unstable API. +## +## By default, C++ uses C11 atomic primitives. To use C++ `std::atomic`, +## `-d:nimUseCppAtomics` can be defined. runnableExamples: # Atomic @@ -50,8 +53,7 @@ runnableExamples: flag.clear(moRelaxed) assert not flag.testAndSet - -when defined(cpp) or defined(nimdoc): +when (defined(cpp) and defined(nimUseCppAtomics)) or defined(nimdoc): # For the C++ backend, types and operations map directly to C++11 atomics. {.push, header: "<atomic>".} @@ -274,10 +276,17 @@ else: cast[T](interlockedXor(addr(location.value), cast[nonAtomicType(T)](value))) else: - {.push, header: "<stdatomic.h>".} + when defined(cpp): + {.push, header: "<atomic>".} + template maybeWrapStd(x: string): string = + "std::" & x + else: + {.push, header: "<stdatomic.h>".} + template maybeWrapStd(x: string): string = + x type - MemoryOrder* {.importc: "memory_order".} = enum + MemoryOrder* {.importc: "memory_order".maybeWrapStd.} = enum moRelaxed moConsume moAcquire @@ -285,16 +294,25 @@ else: moAcquireRelease moSequentiallyConsistent - type - # Atomic*[T] {.importcpp: "_Atomic('0)".} = object + when defined(cpp): + type + # Atomic*[T] {.importcpp: "_Atomic('0)".} = object + + AtomicInt8 {.importc: "std::atomic<NI8>".} = int8 + AtomicInt16 {.importc: "std::atomic<NI16>".} = int16 + AtomicInt32 {.importc: "std::atomic<NI32>".} = int32 + AtomicInt64 {.importc: "std::atomic<NI64>".} = int64 + else: + type + # Atomic*[T] {.importcpp: "_Atomic('0)".} = object - AtomicInt8 {.importc: "_Atomic NI8".} = int8 - AtomicInt16 {.importc: "_Atomic NI16".} = int16 - AtomicInt32 {.importc: "_Atomic NI32".} = int32 - AtomicInt64 {.importc: "_Atomic NI64".} = int64 + AtomicInt8 {.importc: "_Atomic NI8".} = int8 + AtomicInt16 {.importc: "_Atomic NI16".} = int16 + AtomicInt32 {.importc: "_Atomic NI32".} = int32 + AtomicInt64 {.importc: "_Atomic NI64".} = int64 type - AtomicFlag* {.importc: "atomic_flag", size: 1.} = object + AtomicFlag* {.importc: "atomic_flag".maybeWrapStd, size: 1.} = object Atomic*[T] = object when T is Trivial: @@ -308,27 +326,27 @@ else: guard: AtomicFlag #proc init*[T](location: var Atomic[T]; value: T): T {.importcpp: "atomic_init(@)".} - proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc.} - proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc.} - proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} - proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.} - proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.} + proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc: "atomic_load_explicit".maybeWrapStd.} + proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_store_explicit".maybeWrapStd.} + proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_exchange_explicit".maybeWrapStd.} + proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_strong_explicit".maybeWrapStd.} + proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_weak_explicit".maybeWrapStd.} # Numerical operations - proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} - proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} - proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} - proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} - proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.} + proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_add_explicit".maybeWrapStd.} + proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_sub_explicit".maybeWrapStd.} + proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_and_explicit".maybeWrapStd.} + proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_or_explicit".maybeWrapStd.} + proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_xor_explicit".maybeWrapStd.} # Flag operations # var ATOMIC_FLAG_INIT {.importc, nodecl.}: AtomicFlag # proc init*(location: var AtomicFlag) {.inline.} = location = ATOMIC_FLAG_INIT - proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".} - proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".} + proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".maybeWrapStd.} + proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".maybeWrapStd.} - proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".} - proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".} + proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".maybeWrapStd.} + proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".maybeWrapStd.} {.pop.} diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index 1d2ff63e1..9bc3fd579 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -15,75 +15,96 @@ runnableExamples: include "system/inclrtl" -when defined(posix) and not (defined(macosx) or defined(bsd)): - import posix +when defined(js): + import std/jsffi + proc countProcessorsImpl(): int = + when defined(nodejs): + let jsOs = require("os") + let jsObj = jsOs.cpus().length + else: + # `navigator.hardwareConcurrency` + # works on browser as well as deno. + let navigator{.importcpp.}: JsObject + let jsObj = navigator.hardwareConcurrency + result = jsObj.to int +else: + when defined(posix) and not (defined(macosx) or defined(bsd)): + import std/posix -when defined(windows): - import std/private/win_getsysteminfo + when defined(windows): + import std/private/win_getsysteminfo + + when defined(freebsd) or defined(macosx): + {.emit: "#include <sys/types.h>".} + + when defined(openbsd) or defined(netbsd): + {.emit: "#include <sys/param.h>".} -when defined(freebsd) or defined(macosx): - {.emit: "#include <sys/types.h>".} + when defined(macosx) or defined(bsd): + # we HAVE to emit param.h before sysctl.h so we cannot use .header here + # either. The amount of archaic bullshit in Poonix based OSes is just insane. + {.emit: "#include <sys/sysctl.h>".} + {.push nodecl.} + when defined(macosx): + proc sysctlbyname(name: cstring, + oldp: pointer, oldlenp: var csize_t, + newp: pointer, newlen: csize_t): cint {.importc.} + let + CTL_HW{.importc.}: cint + HW_NCPU{.importc.}: cint + proc sysctl[I: static[int]](name: var array[I, cint], namelen: cuint, + oldp: pointer, oldlenp: var csize_t, + newp: pointer, newlen: csize_t): cint {.importc.} + {.pop.} -when defined(openbsd) or defined(netbsd): - {.emit: "#include <sys/param.h>".} + when defined(genode): + import genode/env -when defined(macosx) or defined(bsd): - # we HAVE to emit param.h before sysctl.h so we cannot use .header here - # either. The amount of archaic bullshit in Poonix based OSes is just insane. - {.emit: "#include <sys/sysctl.h>".} - const - CTL_HW = 6 - HW_AVAILCPU = 25 - HW_NCPU = 3 - proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, - a: var csize_t, b: pointer, c: csize_t): cint {. - importc: "sysctl", nodecl.} + proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {. + importcpp: "@->cpu().affinity_space().total()".} -when defined(genode): - import genode/env + when defined(haiku): + type + SystemInfo {.importc: "system_info", header: "<OS.h>".} = object + cpuCount {.importc: "cpu_count".}: uint32 - proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {. - importcpp: "@->cpu().affinity_space().total()".} + proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info", + header: "<OS.h>".} + + proc countProcessorsImpl(): int {.inline.} = + when defined(windows): + var + si: SystemInfo + getSystemInfo(addr si) + result = int(si.dwNumberOfProcessors) + elif defined(macosx) or defined(bsd): + let dest = addr result + var len = sizeof(result).csize_t + when defined(macosx): + # alias of "hw.activecpu" + if sysctlbyname("hw.logicalcpu", dest, len, nil, 0) == 0: + return + var mib = [CTL_HW, HW_NCPU] + if sysctl(mib, 2, dest, len, nil, 0) == 0: + return + elif defined(hpux): + result = mpctl(MPC_GETNUMSPUS, nil, nil) + elif defined(irix): + var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint + result = sysconf(SC_NPROC_ONLN) + elif defined(genode): + result = runtimeEnv.affinitySpaceTotal().int + elif defined(haiku): + var sysinfo: SystemInfo + if getSystemInfo(addr sysinfo) == 0: + result = sysinfo.cpuCount.int + else: + result = sysconf(SC_NPROCESSORS_ONLN) + if result < 0: result = 0 -when defined(haiku): - type - SystemInfo {.importc: "system_info", header: "<OS.h>".} = object - cpuCount {.importc: "cpu_count".}: uint32 - proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info", - header: "<OS.h>".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## Returns the number of the processors/cores the machine has. ## Returns 0 if it cannot be detected. - when defined(windows): - var - si: SystemInfo - getSystemInfo(addr si) - result = int(si.dwNumberOfProcessors) - elif defined(macosx) or defined(bsd): - var - mib: array[0..3, cint] - numCPU: int - mib[0] = CTL_HW - mib[1] = HW_AVAILCPU - var len = sizeof(numCPU).csize_t - discard sysctl(addr(mib), 2, addr(numCPU), len, nil, 0) - if numCPU < 1: - mib[1] = HW_NCPU - discard sysctl(addr(mib), 2, addr(numCPU), len, nil, 0) - result = numCPU - elif defined(hpux): - result = mpctl(MPC_GETNUMSPUS, nil, nil) - elif defined(irix): - var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint - result = sysconf(SC_NPROC_ONLN) - elif defined(genode): - result = runtimeEnv.affinitySpaceTotal().int - elif defined(haiku): - var sysinfo: SystemInfo - if getSystemInfo(addr sysinfo) == 0: - result = sysinfo.cpuCount.int - else: - result = sysconf(SC_NPROCESSORS_ONLN) - if result <= 0: result = 0 + countProcessorsImpl() diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim index 137dd67ad..bfbf16721 100644 --- a/lib/pure/concurrency/cpuload.nim +++ b/lib/pure/concurrency/cpuload.nim @@ -13,11 +13,11 @@ ## Unstable API. when defined(windows): - import winlean, os, strutils, math + import std/[winlean, os, strutils, math] proc `-`(a, b: FILETIME): int64 = a.rdFileTime - b.rdFileTime elif defined(linux): - from cpuinfo import countProcessors + from std/cpuinfo import countProcessors when defined(nimPreviewSlimSystem): import std/syncio @@ -87,7 +87,7 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice = inc s.calls when not defined(testing) and isMainModule and not defined(nimdoc): - import random + import std/random proc busyLoop() = while true: diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index e34162fa4..06ed2fe54 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -22,7 +22,7 @@ when not compileOption("threads"): {.error: "Threadpool requires --threads:on option.".} -import cpuinfo, cpuload, locks, os +import std/[cpuinfo, cpuload, locks, os] when defined(nimPreviewSlimSystem): import std/[assertions, typedthreads, sysatomics] diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 22704e434..f628aaf6b 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -9,7 +9,7 @@ ## This module implements helper procs for parsing Cookies. -import strtabs, times, options +import std/[strtabs, times, options] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/pure/coro.nim b/lib/pure/coro.nim index 5cdcb75fe..24836e316 100644 --- a/lib/pure/coro.nim +++ b/lib/pure/coro.nim @@ -29,8 +29,7 @@ when not nimCoroutines and not defined(nimdoc): else: {.error: "Coroutines require -d:nimCoroutines".} -import os -import lists +import std/[os, lists] include system/timers when defined(nimPreviewSlimSystem): @@ -68,7 +67,7 @@ else: const coroBackend = CORO_BACKEND_UCONTEXT when coroBackend == CORO_BACKEND_FIBERS: - import windows/winlean + import std/winlean type Context = pointer diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim index 58eacf633..9e71d4ce0 100644 --- a/lib/pure/distros.nim +++ b/lib/pure/distros.nim @@ -127,6 +127,7 @@ type BSD FreeBSD + NetBSD OpenBSD DragonFlyBSD @@ -168,7 +169,7 @@ proc detectOsImpl(d: Distribution): bool = else: when defined(bsd): case d - of Distribution.FreeBSD, Distribution.OpenBSD: + of Distribution.FreeBSD, Distribution.NetBSD, Distribution.OpenBSD: result = $d in uname() else: result = false @@ -251,7 +252,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) = result = ("nix-env -i " & p, false) elif detectOs(Solaris) or detectOs(FreeBSD): result = ("pkg install " & p, true) - elif detectOs(OpenBSD): + elif detectOs(NetBSD) or detectOs(OpenBSD): result = ("pkg_add " & p, true) elif detectOs(PCLinuxOS): result = ("rpm -ivh " & p, true) diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index 48fd91b8f..a162fe37f 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -105,7 +105,7 @@ when defined(posix) and not defined(nintendoswitch): # as an emulation layer on top of native functions. # ========================================================================= # - import posix + import std/posix proc loadLib(path: string, globalSymbols = false): LibHandle = let flags = @@ -148,7 +148,7 @@ elif defined(genode): # template raiseErr(prc: string) = - raise newException(OSError, prc & " not implemented, compile with POSIX suport") + raise newException(OSError, prc & " not implemented, compile with POSIX support") proc dlclose(lib: LibHandle) = raiseErr(OSError, "dlclose") diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index 0d7e878e5..bbadca655 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -39,7 +39,7 @@ runnableExamples: assert fromGB2312.convert(second) == "有白头如新,倾盖如故" -import os +import std/os when defined(nimPreviewSlimSystem): import std/assertions @@ -59,7 +59,7 @@ type ## for encoding errors. when defined(windows): - import parseutils, strutils + import std/[parseutils, strutils] proc eqEncodingNames(a, b: string): bool = var i = 0 var j = 0 @@ -342,7 +342,7 @@ proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter = ## Raises `EncodingError` if it cannot fulfill the request. when not defined(windows): result = iconvOpen(destEncoding, srcEncoding) - if result == nil: + if result == cast[EncodingConverter](-1): raise newException(EncodingError, "cannot create encoding converter from " & srcEncoding & " to " & destEncoding) diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index ddb6a1a0c..1d96fd6be 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -12,7 +12,7 @@ ## The types, vars and procs are bindings for the C standard library ## [<fenv.h>](https://en.cppreference.com/w/c/numeric/fenv) header. -when defined(posix) and not defined(genode): +when defined(posix) and not defined(genode) and not defined(macosx): {.passl: "-lm".} var diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 6d246d5b9..1038d55a1 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -190,7 +190,7 @@ proc hashData*(data: pointer, size: int): Hash = var h: Hash = 0 when defined(js): var p: cstring - asm """`p` = `Data`""" + {.emit: """`p` = `Data`;""".} else: var p = cast[cstring](data) var i = 0 @@ -217,7 +217,7 @@ else: when defined(js): var objectID = 0 proc getObjectId(x: pointer): int = - asm """ + {.emit: """ if (typeof `x` == "object") { if ("_NimID" in `x`) `result` = `x`["_NimID"]; @@ -226,7 +226,7 @@ when defined(js): `x`["_NimID"] = `result`; } } - """ + """.} proc hash*(x: pointer): Hash {.inline.} = ## Efficient `hash` overload. @@ -379,6 +379,158 @@ proc hashVmImplChar(x: openArray[char], sPos, ePos: int): Hash = proc hashVmImplByte(x: openArray[byte], sPos, ePos: int): Hash = raiseAssert "implementation override in compiler/vmops.nim" +const k0 = 0xc3a5c85c97cb3127u64 # Primes on (2^63, 2^64) for various uses +const k1 = 0xb492b66fbe98f273u64 +const k2 = 0x9ae16a3b2f90404fu64 + +proc load4e(s: openArray[byte], o=0): uint32 {.inline.} = + uint32(s[o + 3]) shl 24 or uint32(s[o + 2]) shl 16 or + uint32(s[o + 1]) shl 8 or uint32(s[o + 0]) + +proc load8e(s: openArray[byte], o=0): uint64 {.inline.} = + uint64(s[o + 7]) shl 56 or uint64(s[o + 6]) shl 48 or + uint64(s[o + 5]) shl 40 or uint64(s[o + 4]) shl 32 or + uint64(s[o + 3]) shl 24 or uint64(s[o + 2]) shl 16 or + uint64(s[o + 1]) shl 8 or uint64(s[o + 0]) + +proc load4(s: openArray[byte], o=0): uint32 {.inline.} = + when nimvm: result = load4e(s, o) + else: + when declared copyMem: copyMem result.addr, s[o].addr, result.sizeof + else: result = load4e(s, o) + +proc load8(s: openArray[byte], o=0): uint64 {.inline.} = + when nimvm: result = load8e(s, o) + else: + when declared copyMem: copyMem result.addr, s[o].addr, result.sizeof + else: result = load8e(s, o) + +proc lenU(s: openArray[byte]): uint64 {.inline.} = s.len.uint64 + +proc shiftMix(v: uint64): uint64 {.inline.} = v xor (v shr 47) + +proc rotR(v: uint64; bits: cint): uint64 {.inline.} = + (v shr bits) or (v shl (64 - bits)) + +proc len16(u: uint64; v: uint64; mul: uint64): uint64 {.inline.} = + var a = (u xor v)*mul + a = a xor (a shr 47) + var b = (v xor a)*mul + b = b xor (b shr 47) + b*mul + +proc len0_16(s: openArray[byte]): uint64 {.inline.} = + if s.len >= 8: + let mul = k2 + 2*s.lenU + let a = load8(s) + k2 + let b = load8(s, s.len - 8) + let c = rotR(b, 37)*mul + a + let d = (rotR(a, 25) + b)*mul + len16 c, d, mul + elif s.len >= 4: + let mul = k2 + 2*s.lenU + let a = load4(s).uint64 + len16 s.lenU + (a shl 3), load4(s, s.len - 4), mul + elif s.len > 0: + let a = uint32(s[0]) + let b = uint32(s[s.len shr 1]) + let c = uint32(s[s.len - 1]) + let y = a + (b shl 8) + let z = s.lenU + (c shl 2) + shiftMix(y*k2 xor z*k0)*k2 + else: k2 # s.len == 0 + +proc len17_32(s: openArray[byte]): uint64 {.inline.} = + let mul = k2 + 2*s.lenU + let a = load8(s)*k1 + let b = load8(s, 8) + let c = load8(s, s.len - 8)*mul + let d = load8(s, s.len - 16)*k2 + len16 rotR(a + b, 43) + rotR(c, 30) + d, a + rotR(b + k2, 18) + c, mul + +proc len33_64(s: openArray[byte]): uint64 {.inline.} = + let mul = k2 + 2*s.lenU + let a = load8(s)*k2 + let b = load8(s, 8) + let c = load8(s, s.len - 8)*mul + let d = load8(s, s.len - 16)*k2 + let y = rotR(a + b, 43) + rotR(c, 30) + d + let z = len16(y, a + rotR(b + k2, 18) + c, mul) + let e = load8(s, 16)*mul + let f = load8(s, 24) + let g = (y + load8(s, s.len - 32))*mul + let h = (z + load8(s, s.len - 24))*mul + len16 rotR(e + f, 43) + rotR(g, 30) + h, e + rotR(f + a, 18) + g, mul + +type Pair = tuple[first, second: uint64] + +proc weakLen32withSeeds2(w, x, y, z, a, b: uint64): Pair {.inline.} = + var a = a + w + var b = rotR(b + a + z, 21) + let c = a + a += x + a += y + b += rotR(a, 44) + result[0] = a + z + result[1] = b + c + +proc weakLen32withSeeds(s: openArray[byte]; o: int; a,b: uint64): Pair {.inline.} = + weakLen32withSeeds2 load8(s, o ), load8(s, o + 8), + load8(s, o + 16), load8(s, o + 24), a, b + +proc hashFarm(s: openArray[byte]): uint64 {.inline.} = + if s.len <= 16: return len0_16(s) + if s.len <= 32: return len17_32(s) + if s.len <= 64: return len33_64(s) + const seed = 81u64 # not const to use input `h` + var + o = 0 # s[] ptr arith -> variable origin variable `o` + x = seed + y = seed*k1 + 113 + z = shiftMix(y*k2 + 113)*k2 + v, w: Pair + x = x*k2 + load8(s) + let eos = ((s.len - 1) div 64)*64 + let last64 = eos + ((s.len - 1) and 63) - 63 + while true: + x = rotR(x + y + v[0] + load8(s, o+8), 37)*k1 + y = rotR(y + v[1] + load8(s, o+48), 42)*k1 + x = x xor w[1] + y += v[0] + load8(s, o+40) + z = rotR(z + w[0], 33)*k1 + v = weakLen32withSeeds(s, o+0 , v[1]*k1, x + w[0]) + w = weakLen32withSeeds(s, o+32, z + w[1], y + load8(s, o+16)) + swap z, x + inc o, 64 + if o == eos: break + let mul = k1 + ((z and 0xff) shl 1) + o = last64 + w[0] += (s.lenU - 1) and 63 + v[0] += w[0] + w[0] += v[0] + x = rotR(x + y + v[0] + load8(s, o+8), 37)*mul + y = rotR(y + v[1] + load8(s, o+48), 42)*mul + x = x xor w[1]*9 + y += v[0]*9 + load8(s, o+40) + z = rotR(z + w[0], 33)*mul + v = weakLen32withSeeds(s, o+0 , v[1]*mul, x + w[0]) + w = weakLen32withSeeds(s, o+32, z + w[1], y + load8(s, o+16)) + swap z, x + len16 len16(v[0],w[0],mul) + shiftMix(y)*k0 + z, len16(v[1],w[1],mul) + x, mul + +template jsNoInt64: untyped = + when defined js: + when compiles(compileOption("jsbigint64")): + when not compileOption("jsbigint64"): true + else: false + else: false + else: false +const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false) + +template maybeFailJS_Number = + when jsNoInt64() and not defined(nimStringHash2): + {.error: "Must use `-d:nimStringHash2` when using `--jsbigint64:off`".} + proc hash*(x: string): Hash = ## Efficient hashing of strings. ## @@ -387,11 +539,14 @@ proc hash*(x: string): Hash = ## * `hashIgnoreCase <#hashIgnoreCase,string>`_ runnableExamples: doAssert hash("abracadabra") != hash("AbracadabrA") - - when nimvm: - result = hashVmImpl(x, 0, high(x)) + maybeFailJS_Number() + when not sHash2: + result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high))) else: - result = murmurHash(toOpenArrayByte(x, 0, high(x))) + #when nimvm: + # result = hashVmImpl(x, 0, high(x)) + when true: + result = murmurHash(toOpenArrayByte(x, 0, high(x))) proc hash*(x: cstring): Hash = ## Efficient hashing of null-terminated strings. @@ -400,14 +555,22 @@ proc hash*(x: cstring): Hash = doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA") doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA") - when nimvm: - hashVmImpl(x, 0, high(x)) - else: - when not defined(js): - murmurHash(toOpenArrayByte(x, 0, x.high)) - else: + maybeFailJS_Number() + when not sHash2: + when defined js: let xx = $x - murmurHash(toOpenArrayByte(xx, 0, high(xx))) + result = cast[Hash](hashFarm(toOpenArrayByte(xx, 0, xx.high))) + else: + result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high))) + else: + #when nimvm: + # result = hashVmImpl(x, 0, high(x)) + when true: + when not defined(js): + result = murmurHash(toOpenArrayByte(x, 0, x.high)) + else: + let xx = $x + result = murmurHash(toOpenArrayByte(xx, 0, high(xx))) proc hash*(sBuf: string, sPos, ePos: int): Hash = ## Efficient hashing of a string buffer, from starting @@ -418,7 +581,11 @@ proc hash*(sBuf: string, sPos, ePos: int): Hash = var a = "abracadabra" doAssert hash(a, 0, 3) == hash(a, 7, 10) - murmurHash(toOpenArrayByte(sBuf, sPos, ePos)) + maybeFailJS_Number() + when not sHash2: + result = cast[Hash](hashFarm(toOpenArrayByte(sBuf, sPos, ePos))) + else: + murmurHash(toOpenArrayByte(sBuf, sPos, ePos)) proc hashIgnoreStyle*(x: string): Hash = ## Efficient hashing of strings; style is ignored. @@ -553,12 +720,18 @@ proc hash*[A](x: openArray[A]): Hash = ## Efficient hashing of arrays and sequences. ## There must be a `hash` proc defined for the element type `A`. when A is byte: - result = murmurHash(x) + when not sHash2: + result = cast[Hash](hashFarm(x)) + else: + result = murmurHash(x) elif A is char: - when nimvm: - result = hashVmImplChar(x, 0, x.high) + when not sHash2: + result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high))) else: - result = murmurHash(toOpenArrayByte(x, 0, x.high)) + #when nimvm: + # result = hashVmImplChar(x, 0, x.high) + when true: + result = murmurHash(toOpenArrayByte(x, 0, x.high)) else: result = 0 for a in x: @@ -574,17 +747,24 @@ proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash = runnableExamples: let a = [1, 2, 5, 1, 2, 6] doAssert hash(a, 0, 1) == hash(a, 3, 4) - when A is byte: - when nimvm: - result = hashVmImplByte(aBuf, sPos, ePos) + maybeFailJS_Number() + when not sHash2: + result = cast[Hash](hashFarm(toOpenArray(aBuf, sPos, ePos))) else: - result = murmurHash(toOpenArray(aBuf, sPos, ePos)) + #when nimvm: + # result = hashVmImplByte(aBuf, sPos, ePos) + when true: + result = murmurHash(toOpenArray(aBuf, sPos, ePos)) elif A is char: - when nimvm: - result = hashVmImplChar(aBuf, sPos, ePos) + maybeFailJS_Number() + when not sHash2: + result = cast[Hash](hashFarm(toOpenArrayByte(aBuf, sPos, ePos))) else: - result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos)) + #when nimvm: + # result = hashVmImplChar(aBuf, sPos, ePos) + when true: + result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos)) else: for i in sPos .. ePos: result = result !& hash(aBuf[i]) diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index be9e1fe90..fafa72463 100644 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -8,7 +8,7 @@ # ## Do yourself a favor and import the module -## as `from htmlgen import nil` and then fully qualify the macros. +## as `from std/htmlgen import nil` and then fully qualify the macros. ## ## *Note*: The Karax project (`nimble install karax`) has a better ## way to achieve the same, see https://github.com/pragmagic/karax/blob/master/tests/nativehtmlgen.nim @@ -41,7 +41,7 @@ ## import - macros, strutils + std/[macros, strutils] const coreAttr* = " accesskey class contenteditable dir hidden id lang " & diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim index 0de384a8e..62919546f 100644 --- a/lib/pure/htmlparser.nim +++ b/lib/pure/htmlparser.nim @@ -47,7 +47,9 @@ ## writeFile("output.html", $html) ## ``` -import strutils, streams, parsexml, xmltree, unicode, strtabs +{.deprecated: "use `nimble install htmlparser` and import `pkg/htmlparser` instead".} + +import std/[strutils, streams, parsexml, xmltree, unicode, strtabs] when defined(nimPreviewSlimSystem): import std/syncio @@ -2062,7 +2064,7 @@ proc loadHtml*(path: string): XmlNode = result = loadHtml(path, errors) when not defined(testing) and isMainModule: - import os + import std/os var errors: seq[string] = @[] var x = loadHtml(paramStr(1), errors) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index ddf208e4e..08ea99627 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -305,7 +305,7 @@ proc contentLength*(response: Response | AsyncResponse): int = ## ## A `ValueError` exception will be raised if the value is not an integer. ## If the Content-Length header is not set in the response, ContentLength is set to the value -1. - var contentLengthHeader = response.headers.getOrDefault("Content-Length", @["-1"]) + var contentLengthHeader = response.headers.getOrDefault("Content-Length", HttpHeaderValues(@["-1"])) result = contentLengthHeader.parseInt() proc lastModified*(response: Response | AsyncResponse): DateTime = @@ -359,7 +359,7 @@ type ## and `postContent` proc, ## when the server returns an error -const defUserAgent* = "Nim httpclient/" & NimVersion +const defUserAgent* = "Nim-httpclient/" & NimVersion proc httpError(msg: string) = var e: ref ProtocolError @@ -856,6 +856,7 @@ proc parseResponse(client: HttpClient | AsyncHttpClient, var parsedStatus = false var linei = 0 var fullyRead = false + var lastHeaderName = "" var line = "" result.headers = newHttpHeaders() while true: @@ -890,16 +891,29 @@ proc parseResponse(client: HttpClient | AsyncHttpClient, parsedStatus = true else: # Parse headers - var name = "" - var le = parseUntil(line, name, ':', linei) - if le <= 0: httpError("invalid headers") - inc(linei, le) - if line[linei] != ':': httpError("invalid headers") - inc(linei) # Skip : - - result.headers.add(name, line[linei .. ^1].strip()) - if result.headers.len > headerLimit: - httpError("too many headers") + # There's at least one char because empty lines are handled above (with client.close) + if line[0] in {' ', '\t'}: + # Check if it's a multiline header value, if so, append to the header we're currently parsing + # This works because a line with a header must start with the header name without any leading space + # See https://datatracker.ietf.org/doc/html/rfc7230, section 3.2 and 3.2.4 + # Multiline headers are deprecated in the spec, but it's better to parse them than crash + if lastHeaderName == "": + # Some extra unparsable lines in the HTTP output - we ignore them + discard + else: + result.headers.table[result.headers.toCaseInsensitive(lastHeaderName)][^1].add "\n" & line + else: + var name = "" + var le = parseUntil(line, name, ':', linei) + if le <= 0: httpError("Invalid headers - received empty header name") + if line.len == le: httpError("Invalid headers - no colon after header name") + inc(linei, le) # Skip the parsed header name + inc(linei) # Skip : + # If we want to be HTTP spec compliant later, error on linei == line.len (for empty header value) + lastHeaderName = name # Remember the header name for the possible multi-line header + result.headers.add(name, line[linei .. ^1].strip()) + if result.headers.len > headerLimit: + httpError("too many headers") if not fullyRead: httpError("Connection was closed before full request has been made") @@ -1218,7 +1232,7 @@ proc responseContent(resp: Response | AsyncResponse): Future[string] {.multisync ## A `HttpRequestError` will be raised if the server responds with a ## client error (status code 4xx) or a server error (status code 5xx). if resp.code.is4xx or resp.code.is5xx: - raise newException(HttpRequestError, resp.status) + raise newException(HttpRequestError, resp.status.move) else: return await resp.bodyStream.readAll() diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index 3b5cbc3cf..5ccab379c 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -12,7 +12,7 @@ ## ## Unstable API. import std/private/since -import tables, strutils, parseutils +import std/[tables, strutils, parseutils] type HttpHeaders* = ref object @@ -126,7 +126,8 @@ func toTitleCase(s: string): string = result[i] = if upper: toUpperAscii(s[i]) else: toLowerAscii(s[i]) upper = s[i] == '-' -func toCaseInsensitive(headers: HttpHeaders, s: string): string {.inline.} = +func toCaseInsensitive*(headers: HttpHeaders, s: string): string {.inline.} = + ## For internal usage only. Do not use. return if headers.isTitleCase: toTitleCase(s) else: toLowerAscii(s) func newHttpHeaders*(titleCase=false): HttpHeaders = @@ -163,7 +164,8 @@ func `[]`*(headers: HttpHeaders, key: string): HttpHeaderValues = ## To access multiple values of a key, use the overloaded `[]` below or ## to get all of them access the `table` field directly. {.cast(noSideEffect).}: - return headers.table[headers.toCaseInsensitive(key)].HttpHeaderValues + let tmp = headers.table[headers.toCaseInsensitive(key)] + return HttpHeaderValues(tmp) converter toString*(values: HttpHeaderValues): string = return seq[string](values)[0] @@ -233,10 +235,9 @@ func parseList(line: string, list: var seq[string], start: int): int = while start+i < line.len and line[start + i] notin {'\c', '\l'}: i += line.skipWhitespace(start + i) i += line.parseUntil(current, {'\c', '\l', ','}, start + i) - list.add(current) + list.add(move current) # implicit current.setLen(0) if start+i < line.len and line[start + i] == ',': i.inc # Skip , - current.setLen(0) func parseHeader*(line: string): tuple[key: string, value: seq[string]] = ## Parses a single raw header HTTP line into key value pairs. diff --git a/lib/pure/includes/unicode_ranges.nim b/lib/pure/includes/unicode_ranges.nim index 74c8c6399..04ccfb747 100644 --- a/lib/pure/includes/unicode_ranges.nim +++ b/lib/pure/includes/unicode_ranges.nim @@ -2,1988 +2,1979 @@ const toLowerRanges = [ - 0x00041, 0x0005A, 532, - 0x000C0, 0x000D6, 532, - 0x000D8, 0x000DE, 532, - 0x00189, 0x0018A, 705, - 0x001B1, 0x001B2, 717, - 0x00388, 0x0038A, 537, - 0x0038E, 0x0038F, 563, - 0x00391, 0x003A1, 532, - 0x003A3, 0x003AB, 532, - 0x003FD, 0x003FF, 370, - 0x00400, 0x0040F, 580, - 0x00410, 0x0042F, 532, - 0x00531, 0x00556, 548, - 0x010A0, 0x010C5, 7764, - 0x013A0, 0x013EF, 39364, - 0x013F0, 0x013F5, 508, - 0x01C90, 0x01CBA, -2508, - 0x01CBD, 0x01CBF, -2508, - 0x01F08, 0x01F0F, 492, - 0x01F18, 0x01F1D, 492, - 0x01F28, 0x01F2F, 492, - 0x01F38, 0x01F3F, 492, - 0x01F48, 0x01F4D, 492, - 0x01F68, 0x01F6F, 492, - 0x01F88, 0x01F8F, 492, - 0x01F98, 0x01F9F, 492, - 0x01FA8, 0x01FAF, 492, - 0x01FB8, 0x01FB9, 492, - 0x01FBA, 0x01FBB, 426, - 0x01FC8, 0x01FCB, 414, - 0x01FD8, 0x01FD9, 492, - 0x01FDA, 0x01FDB, 400, - 0x01FE8, 0x01FE9, 492, - 0x01FEA, 0x01FEB, 388, - 0x01FF8, 0x01FF9, 372, - 0x01FFA, 0x01FFB, 374, - 0x02C00, 0x02C2E, 548, - 0x02C7E, 0x02C7F, -10315, - 0x0FF21, 0x0FF3A, 532, - 0x10400, 0x10427, 540, - 0x104B0, 0x104D3, 540, - 0x10C80, 0x10CB2, 564, - 0x118A0, 0x118BF, 532, - 0x16E40, 0x16E5F, 532, - 0x1E900, 0x1E921, 534, + 0x00041'i32, 0x0005A'i32, 532, + 0x000C0'i32, 0x000D6'i32, 532, + 0x000D8'i32, 0x000DE'i32, 532, + 0x00189'i32, 0x0018A'i32, 705, + 0x001B1'i32, 0x001B2'i32, 717, + 0x00388'i32, 0x0038A'i32, 537, + 0x0038E'i32, 0x0038F'i32, 563, + 0x00391'i32, 0x003A1'i32, 532, + 0x003A3'i32, 0x003AB'i32, 532, + 0x003FD'i32, 0x003FF'i32, 370, + 0x00400'i32, 0x0040F'i32, 580, + 0x00410'i32, 0x0042F'i32, 532, + 0x00531'i32, 0x00556'i32, 548, + 0x010A0'i32, 0x010C5'i32, 7764, + 0x013A0'i32, 0x013EF'i32, 39364, + 0x013F0'i32, 0x013F5'i32, 508, + 0x01C90'i32, 0x01CBA'i32, -2508, + 0x01CBD'i32, 0x01CBF'i32, -2508, + 0x01F08'i32, 0x01F0F'i32, 492, + 0x01F18'i32, 0x01F1D'i32, 492, + 0x01F28'i32, 0x01F2F'i32, 492, + 0x01F38'i32, 0x01F3F'i32, 492, + 0x01F48'i32, 0x01F4D'i32, 492, + 0x01F68'i32, 0x01F6F'i32, 492, + 0x01F88'i32, 0x01F8F'i32, 492, + 0x01F98'i32, 0x01F9F'i32, 492, + 0x01FA8'i32, 0x01FAF'i32, 492, + 0x01FB8'i32, 0x01FB9'i32, 492, + 0x01FBA'i32, 0x01FBB'i32, 426, + 0x01FC8'i32, 0x01FCB'i32, 414, + 0x01FD8'i32, 0x01FD9'i32, 492, + 0x01FDA'i32, 0x01FDB'i32, 400, + 0x01FE8'i32, 0x01FE9'i32, 492, + 0x01FEA'i32, 0x01FEB'i32, 388, + 0x01FF8'i32, 0x01FF9'i32, 372, + 0x01FFA'i32, 0x01FFB'i32, 374, + 0x02C00'i32, 0x02C2E'i32, 548, + 0x02C7E'i32, 0x02C7F'i32, -10315, + 0x0FF21'i32, 0x0FF3A'i32, 532, + 0x10400'i32, 0x10427'i32, 540, + 0x104B0'i32, 0x104D3'i32, 540, + 0x10C80'i32, 0x10CB2'i32, 564, + 0x118A0'i32, 0x118BF'i32, 532, + 0x16E40'i32, 0x16E5F'i32, 532, + 0x1E900'i32, 0x1E921'i32, 534, ] toLowerSinglets = [ - 0x00100, 501, - 0x00102, 501, - 0x00104, 501, - 0x00106, 501, - 0x00108, 501, - 0x0010A, 501, - 0x0010C, 501, - 0x0010E, 501, - 0x00110, 501, - 0x00112, 501, - 0x00114, 501, - 0x00116, 501, - 0x00118, 501, - 0x0011A, 501, - 0x0011C, 501, - 0x0011E, 501, - 0x00120, 501, - 0x00122, 501, - 0x00124, 501, - 0x00126, 501, - 0x00128, 501, - 0x0012A, 501, - 0x0012C, 501, - 0x0012E, 501, - 0x00130, 301, - 0x00132, 501, - 0x00134, 501, - 0x00136, 501, - 0x00139, 501, - 0x0013B, 501, - 0x0013D, 501, - 0x0013F, 501, - 0x00141, 501, - 0x00143, 501, - 0x00145, 501, - 0x00147, 501, - 0x0014A, 501, - 0x0014C, 501, - 0x0014E, 501, - 0x00150, 501, - 0x00152, 501, - 0x00154, 501, - 0x00156, 501, - 0x00158, 501, - 0x0015A, 501, - 0x0015C, 501, - 0x0015E, 501, - 0x00160, 501, - 0x00162, 501, - 0x00164, 501, - 0x00166, 501, - 0x00168, 501, - 0x0016A, 501, - 0x0016C, 501, - 0x0016E, 501, - 0x00170, 501, - 0x00172, 501, - 0x00174, 501, - 0x00176, 501, - 0x00178, 379, - 0x00179, 501, - 0x0017B, 501, - 0x0017D, 501, - 0x00181, 710, - 0x00182, 501, - 0x00184, 501, - 0x00186, 706, - 0x00187, 501, - 0x0018B, 501, - 0x0018E, 579, - 0x0018F, 702, - 0x00190, 703, - 0x00191, 501, - 0x00193, 705, - 0x00194, 707, - 0x00196, 711, - 0x00197, 709, - 0x00198, 501, - 0x0019C, 711, - 0x0019D, 713, - 0x0019F, 714, - 0x001A0, 501, - 0x001A2, 501, - 0x001A4, 501, - 0x001A6, 718, - 0x001A7, 501, - 0x001A9, 718, - 0x001AC, 501, - 0x001AE, 718, - 0x001AF, 501, - 0x001B3, 501, - 0x001B5, 501, - 0x001B7, 719, - 0x001B8, 501, - 0x001BC, 501, - 0x001C4, 502, - 0x001C5, 501, - 0x001C7, 502, - 0x001C8, 501, - 0x001CA, 502, - 0x001CB, 501, - 0x001CD, 501, - 0x001CF, 501, - 0x001D1, 501, - 0x001D3, 501, - 0x001D5, 501, - 0x001D7, 501, - 0x001D9, 501, - 0x001DB, 501, - 0x001DE, 501, - 0x001E0, 501, - 0x001E2, 501, - 0x001E4, 501, - 0x001E6, 501, - 0x001E8, 501, - 0x001EA, 501, - 0x001EC, 501, - 0x001EE, 501, - 0x001F1, 502, - 0x001F2, 501, - 0x001F4, 501, - 0x001F6, 403, - 0x001F7, 444, - 0x001F8, 501, - 0x001FA, 501, - 0x001FC, 501, - 0x001FE, 501, - 0x00200, 501, - 0x00202, 501, - 0x00204, 501, - 0x00206, 501, - 0x00208, 501, - 0x0020A, 501, - 0x0020C, 501, - 0x0020E, 501, - 0x00210, 501, - 0x00212, 501, - 0x00214, 501, - 0x00216, 501, - 0x00218, 501, - 0x0021A, 501, - 0x0021C, 501, - 0x0021E, 501, - 0x00220, 370, - 0x00222, 501, - 0x00224, 501, - 0x00226, 501, - 0x00228, 501, - 0x0022A, 501, - 0x0022C, 501, - 0x0022E, 501, - 0x00230, 501, - 0x00232, 501, - 0x0023A, 11295, - 0x0023B, 501, - 0x0023D, 337, - 0x0023E, 11292, - 0x00241, 501, - 0x00243, 305, - 0x00244, 569, - 0x00245, 571, - 0x00246, 501, - 0x00248, 501, - 0x0024A, 501, - 0x0024C, 501, - 0x0024E, 501, - 0x00370, 501, - 0x00372, 501, - 0x00376, 501, - 0x0037F, 616, - 0x00386, 538, - 0x0038C, 564, - 0x003CF, 508, - 0x003D8, 501, - 0x003DA, 501, - 0x003DC, 501, - 0x003DE, 501, - 0x003E0, 501, - 0x003E2, 501, - 0x003E4, 501, - 0x003E6, 501, - 0x003E8, 501, - 0x003EA, 501, - 0x003EC, 501, - 0x003EE, 501, - 0x003F4, 440, - 0x003F7, 501, - 0x003F9, 493, - 0x003FA, 501, - 0x00460, 501, - 0x00462, 501, - 0x00464, 501, - 0x00466, 501, - 0x00468, 501, - 0x0046A, 501, - 0x0046C, 501, - 0x0046E, 501, - 0x00470, 501, - 0x00472, 501, - 0x00474, 501, - 0x00476, 501, - 0x00478, 501, - 0x0047A, 501, - 0x0047C, 501, - 0x0047E, 501, - 0x00480, 501, - 0x0048A, 501, - 0x0048C, 501, - 0x0048E, 501, - 0x00490, 501, - 0x00492, 501, - 0x00494, 501, - 0x00496, 501, - 0x00498, 501, - 0x0049A, 501, - 0x0049C, 501, - 0x0049E, 501, - 0x004A0, 501, - 0x004A2, 501, - 0x004A4, 501, - 0x004A6, 501, - 0x004A8, 501, - 0x004AA, 501, - 0x004AC, 501, - 0x004AE, 501, - 0x004B0, 501, - 0x004B2, 501, - 0x004B4, 501, - 0x004B6, 501, - 0x004B8, 501, - 0x004BA, 501, - 0x004BC, 501, - 0x004BE, 501, - 0x004C0, 515, - 0x004C1, 501, - 0x004C3, 501, - 0x004C5, 501, - 0x004C7, 501, - 0x004C9, 501, - 0x004CB, 501, - 0x004CD, 501, - 0x004D0, 501, - 0x004D2, 501, - 0x004D4, 501, - 0x004D6, 501, - 0x004D8, 501, - 0x004DA, 501, - 0x004DC, 501, - 0x004DE, 501, - 0x004E0, 501, - 0x004E2, 501, - 0x004E4, 501, - 0x004E6, 501, - 0x004E8, 501, - 0x004EA, 501, - 0x004EC, 501, - 0x004EE, 501, - 0x004F0, 501, - 0x004F2, 501, - 0x004F4, 501, - 0x004F6, 501, - 0x004F8, 501, - 0x004FA, 501, - 0x004FC, 501, - 0x004FE, 501, - 0x00500, 501, - 0x00502, 501, - 0x00504, 501, - 0x00506, 501, - 0x00508, 501, - 0x0050A, 501, - 0x0050C, 501, - 0x0050E, 501, - 0x00510, 501, - 0x00512, 501, - 0x00514, 501, - 0x00516, 501, - 0x00518, 501, - 0x0051A, 501, - 0x0051C, 501, - 0x0051E, 501, - 0x00520, 501, - 0x00522, 501, - 0x00524, 501, - 0x00526, 501, - 0x00528, 501, - 0x0052A, 501, - 0x0052C, 501, - 0x0052E, 501, - 0x010C7, 7764, - 0x010CD, 7764, - 0x01E00, 501, - 0x01E02, 501, - 0x01E04, 501, - 0x01E06, 501, - 0x01E08, 501, - 0x01E0A, 501, - 0x01E0C, 501, - 0x01E0E, 501, - 0x01E10, 501, - 0x01E12, 501, - 0x01E14, 501, - 0x01E16, 501, - 0x01E18, 501, - 0x01E1A, 501, - 0x01E1C, 501, - 0x01E1E, 501, - 0x01E20, 501, - 0x01E22, 501, - 0x01E24, 501, - 0x01E26, 501, - 0x01E28, 501, - 0x01E2A, 501, - 0x01E2C, 501, - 0x01E2E, 501, - 0x01E30, 501, - 0x01E32, 501, - 0x01E34, 501, - 0x01E36, 501, - 0x01E38, 501, - 0x01E3A, 501, - 0x01E3C, 501, - 0x01E3E, 501, - 0x01E40, 501, - 0x01E42, 501, - 0x01E44, 501, - 0x01E46, 501, - 0x01E48, 501, - 0x01E4A, 501, - 0x01E4C, 501, - 0x01E4E, 501, - 0x01E50, 501, - 0x01E52, 501, - 0x01E54, 501, - 0x01E56, 501, - 0x01E58, 501, - 0x01E5A, 501, - 0x01E5C, 501, - 0x01E5E, 501, - 0x01E60, 501, - 0x01E62, 501, - 0x01E64, 501, - 0x01E66, 501, - 0x01E68, 501, - 0x01E6A, 501, - 0x01E6C, 501, - 0x01E6E, 501, - 0x01E70, 501, - 0x01E72, 501, - 0x01E74, 501, - 0x01E76, 501, - 0x01E78, 501, - 0x01E7A, 501, - 0x01E7C, 501, - 0x01E7E, 501, - 0x01E80, 501, - 0x01E82, 501, - 0x01E84, 501, - 0x01E86, 501, - 0x01E88, 501, - 0x01E8A, 501, - 0x01E8C, 501, - 0x01E8E, 501, - 0x01E90, 501, - 0x01E92, 501, - 0x01E94, 501, - 0x01E9E, -7115, - 0x01EA0, 501, - 0x01EA2, 501, - 0x01EA4, 501, - 0x01EA6, 501, - 0x01EA8, 501, - 0x01EAA, 501, - 0x01EAC, 501, - 0x01EAE, 501, - 0x01EB0, 501, - 0x01EB2, 501, - 0x01EB4, 501, - 0x01EB6, 501, - 0x01EB8, 501, - 0x01EBA, 501, - 0x01EBC, 501, - 0x01EBE, 501, - 0x01EC0, 501, - 0x01EC2, 501, - 0x01EC4, 501, - 0x01EC6, 501, - 0x01EC8, 501, - 0x01ECA, 501, - 0x01ECC, 501, - 0x01ECE, 501, - 0x01ED0, 501, - 0x01ED2, 501, - 0x01ED4, 501, - 0x01ED6, 501, - 0x01ED8, 501, - 0x01EDA, 501, - 0x01EDC, 501, - 0x01EDE, 501, - 0x01EE0, 501, - 0x01EE2, 501, - 0x01EE4, 501, - 0x01EE6, 501, - 0x01EE8, 501, - 0x01EEA, 501, - 0x01EEC, 501, - 0x01EEE, 501, - 0x01EF0, 501, - 0x01EF2, 501, - 0x01EF4, 501, - 0x01EF6, 501, - 0x01EF8, 501, - 0x01EFA, 501, - 0x01EFC, 501, - 0x01EFE, 501, - 0x01F59, 492, - 0x01F5B, 492, - 0x01F5D, 492, - 0x01F5F, 492, - 0x01FBC, 491, - 0x01FCC, 491, - 0x01FEC, 493, - 0x01FFC, 491, - 0x02126, -7017, - 0x0212A, -7883, - 0x0212B, -7762, - 0x02132, 528, - 0x02183, 501, - 0x02C60, 501, - 0x02C62, -10243, - 0x02C63, -3314, - 0x02C64, -10227, - 0x02C67, 501, - 0x02C69, 501, - 0x02C6B, 501, - 0x02C6D, -10280, - 0x02C6E, -10249, - 0x02C6F, -10283, - 0x02C70, -10282, - 0x02C72, 501, - 0x02C75, 501, - 0x02C80, 501, - 0x02C82, 501, - 0x02C84, 501, - 0x02C86, 501, - 0x02C88, 501, - 0x02C8A, 501, - 0x02C8C, 501, - 0x02C8E, 501, - 0x02C90, 501, - 0x02C92, 501, - 0x02C94, 501, - 0x02C96, 501, - 0x02C98, 501, - 0x02C9A, 501, - 0x02C9C, 501, - 0x02C9E, 501, - 0x02CA0, 501, - 0x02CA2, 501, - 0x02CA4, 501, - 0x02CA6, 501, - 0x02CA8, 501, - 0x02CAA, 501, - 0x02CAC, 501, - 0x02CAE, 501, - 0x02CB0, 501, - 0x02CB2, 501, - 0x02CB4, 501, - 0x02CB6, 501, - 0x02CB8, 501, - 0x02CBA, 501, - 0x02CBC, 501, - 0x02CBE, 501, - 0x02CC0, 501, - 0x02CC2, 501, - 0x02CC4, 501, - 0x02CC6, 501, - 0x02CC8, 501, - 0x02CCA, 501, - 0x02CCC, 501, - 0x02CCE, 501, - 0x02CD0, 501, - 0x02CD2, 501, - 0x02CD4, 501, - 0x02CD6, 501, - 0x02CD8, 501, - 0x02CDA, 501, - 0x02CDC, 501, - 0x02CDE, 501, - 0x02CE0, 501, - 0x02CE2, 501, - 0x02CEB, 501, - 0x02CED, 501, - 0x02CF2, 501, - 0x0A640, 501, - 0x0A642, 501, - 0x0A644, 501, - 0x0A646, 501, - 0x0A648, 501, - 0x0A64A, 501, - 0x0A64C, 501, - 0x0A64E, 501, - 0x0A650, 501, - 0x0A652, 501, - 0x0A654, 501, - 0x0A656, 501, - 0x0A658, 501, - 0x0A65A, 501, - 0x0A65C, 501, - 0x0A65E, 501, - 0x0A660, 501, - 0x0A662, 501, - 0x0A664, 501, - 0x0A666, 501, - 0x0A668, 501, - 0x0A66A, 501, - 0x0A66C, 501, - 0x0A680, 501, - 0x0A682, 501, - 0x0A684, 501, - 0x0A686, 501, - 0x0A688, 501, - 0x0A68A, 501, - 0x0A68C, 501, - 0x0A68E, 501, - 0x0A690, 501, - 0x0A692, 501, - 0x0A694, 501, - 0x0A696, 501, - 0x0A698, 501, - 0x0A69A, 501, - 0x0A722, 501, - 0x0A724, 501, - 0x0A726, 501, - 0x0A728, 501, - 0x0A72A, 501, - 0x0A72C, 501, - 0x0A72E, 501, - 0x0A732, 501, - 0x0A734, 501, - 0x0A736, 501, - 0x0A738, 501, - 0x0A73A, 501, - 0x0A73C, 501, - 0x0A73E, 501, - 0x0A740, 501, - 0x0A742, 501, - 0x0A744, 501, - 0x0A746, 501, - 0x0A748, 501, - 0x0A74A, 501, - 0x0A74C, 501, - 0x0A74E, 501, - 0x0A750, 501, - 0x0A752, 501, - 0x0A754, 501, - 0x0A756, 501, - 0x0A758, 501, - 0x0A75A, 501, - 0x0A75C, 501, - 0x0A75E, 501, - 0x0A760, 501, - 0x0A762, 501, - 0x0A764, 501, - 0x0A766, 501, - 0x0A768, 501, - 0x0A76A, 501, - 0x0A76C, 501, - 0x0A76E, 501, - 0x0A779, 501, - 0x0A77B, 501, - 0x0A77D, -34832, - 0x0A77E, 501, - 0x0A780, 501, - 0x0A782, 501, - 0x0A784, 501, - 0x0A786, 501, - 0x0A78B, 501, - 0x0A78D, -41780, - 0x0A790, 501, - 0x0A792, 501, - 0x0A796, 501, - 0x0A798, 501, - 0x0A79A, 501, - 0x0A79C, 501, - 0x0A79E, 501, - 0x0A7A0, 501, - 0x0A7A2, 501, - 0x0A7A4, 501, - 0x0A7A6, 501, - 0x0A7A8, 501, - 0x0A7AA, -41808, - 0x0A7AB, -41819, - 0x0A7AC, -41815, - 0x0A7AD, -41805, - 0x0A7AE, -41808, - 0x0A7B0, -41758, - 0x0A7B1, -41782, - 0x0A7B2, -41761, - 0x0A7B3, 1428, - 0x0A7B4, 501, - 0x0A7B6, 501, - 0x0A7B8, 501, - 0x0A7BA, 501, - 0x0A7BC, 501, - 0x0A7BE, 501, - 0x0A7C2, 501, - 0x0A7C4, 452, - 0x0A7C5, -41807, - 0x0A7C6, -34884, + 0x00100'i32, 501, + 0x00102'i32, 501, + 0x00104'i32, 501, + 0x00106'i32, 501, + 0x00108'i32, 501, + 0x0010A'i32, 501, + 0x0010C'i32, 501, + 0x0010E'i32, 501, + 0x00110'i32, 501, + 0x00112'i32, 501, + 0x00114'i32, 501, + 0x00116'i32, 501, + 0x00118'i32, 501, + 0x0011A'i32, 501, + 0x0011C'i32, 501, + 0x0011E'i32, 501, + 0x00120'i32, 501, + 0x00122'i32, 501, + 0x00124'i32, 501, + 0x00126'i32, 501, + 0x00128'i32, 501, + 0x0012A'i32, 501, + 0x0012C'i32, 501, + 0x0012E'i32, 501, + 0x00130'i32, 301, + 0x00132'i32, 501, + 0x00134'i32, 501, + 0x00136'i32, 501, + 0x00139'i32, 501, + 0x0013B'i32, 501, + 0x0013D'i32, 501, + 0x0013F'i32, 501, + 0x00141'i32, 501, + 0x00143'i32, 501, + 0x00145'i32, 501, + 0x00147'i32, 501, + 0x0014A'i32, 501, + 0x0014C'i32, 501, + 0x0014E'i32, 501, + 0x00150'i32, 501, + 0x00152'i32, 501, + 0x00154'i32, 501, + 0x00156'i32, 501, + 0x00158'i32, 501, + 0x0015A'i32, 501, + 0x0015C'i32, 501, + 0x0015E'i32, 501, + 0x00160'i32, 501, + 0x00162'i32, 501, + 0x00164'i32, 501, + 0x00166'i32, 501, + 0x00168'i32, 501, + 0x0016A'i32, 501, + 0x0016C'i32, 501, + 0x0016E'i32, 501, + 0x00170'i32, 501, + 0x00172'i32, 501, + 0x00174'i32, 501, + 0x00176'i32, 501, + 0x00178'i32, 379, + 0x00179'i32, 501, + 0x0017B'i32, 501, + 0x0017D'i32, 501, + 0x00181'i32, 710, + 0x00182'i32, 501, + 0x00184'i32, 501, + 0x00186'i32, 706, + 0x00187'i32, 501, + 0x0018B'i32, 501, + 0x0018E'i32, 579, + 0x0018F'i32, 702, + 0x00190'i32, 703, + 0x00191'i32, 501, + 0x00193'i32, 705, + 0x00194'i32, 707, + 0x00196'i32, 711, + 0x00197'i32, 709, + 0x00198'i32, 501, + 0x0019C'i32, 711, + 0x0019D'i32, 713, + 0x0019F'i32, 714, + 0x001A0'i32, 501, + 0x001A2'i32, 501, + 0x001A4'i32, 501, + 0x001A6'i32, 718, + 0x001A7'i32, 501, + 0x001A9'i32, 718, + 0x001AC'i32, 501, + 0x001AE'i32, 718, + 0x001AF'i32, 501, + 0x001B3'i32, 501, + 0x001B5'i32, 501, + 0x001B7'i32, 719, + 0x001B8'i32, 501, + 0x001BC'i32, 501, + 0x001C4'i32, 502, + 0x001C5'i32, 501, + 0x001C7'i32, 502, + 0x001C8'i32, 501, + 0x001CA'i32, 502, + 0x001CB'i32, 501, + 0x001CD'i32, 501, + 0x001CF'i32, 501, + 0x001D1'i32, 501, + 0x001D3'i32, 501, + 0x001D5'i32, 501, + 0x001D7'i32, 501, + 0x001D9'i32, 501, + 0x001DB'i32, 501, + 0x001DE'i32, 501, + 0x001E0'i32, 501, + 0x001E2'i32, 501, + 0x001E4'i32, 501, + 0x001E6'i32, 501, + 0x001E8'i32, 501, + 0x001EA'i32, 501, + 0x001EC'i32, 501, + 0x001EE'i32, 501, + 0x001F1'i32, 502, + 0x001F2'i32, 501, + 0x001F4'i32, 501, + 0x001F6'i32, 403, + 0x001F7'i32, 444, + 0x001F8'i32, 501, + 0x001FA'i32, 501, + 0x001FC'i32, 501, + 0x001FE'i32, 501, + 0x00200'i32, 501, + 0x00202'i32, 501, + 0x00204'i32, 501, + 0x00206'i32, 501, + 0x00208'i32, 501, + 0x0020A'i32, 501, + 0x0020C'i32, 501, + 0x0020E'i32, 501, + 0x00210'i32, 501, + 0x00212'i32, 501, + 0x00214'i32, 501, + 0x00216'i32, 501, + 0x00218'i32, 501, + 0x0021A'i32, 501, + 0x0021C'i32, 501, + 0x0021E'i32, 501, + 0x00220'i32, 370, + 0x00222'i32, 501, + 0x00224'i32, 501, + 0x00226'i32, 501, + 0x00228'i32, 501, + 0x0022A'i32, 501, + 0x0022C'i32, 501, + 0x0022E'i32, 501, + 0x00230'i32, 501, + 0x00232'i32, 501, + 0x0023A'i32, 11295, + 0x0023B'i32, 501, + 0x0023D'i32, 337, + 0x0023E'i32, 11292, + 0x00241'i32, 501, + 0x00243'i32, 305, + 0x00244'i32, 569, + 0x00245'i32, 571, + 0x00246'i32, 501, + 0x00248'i32, 501, + 0x0024A'i32, 501, + 0x0024C'i32, 501, + 0x0024E'i32, 501, + 0x00370'i32, 501, + 0x00372'i32, 501, + 0x00376'i32, 501, + 0x0037F'i32, 616, + 0x00386'i32, 538, + 0x0038C'i32, 564, + 0x003CF'i32, 508, + 0x003D8'i32, 501, + 0x003DA'i32, 501, + 0x003DC'i32, 501, + 0x003DE'i32, 501, + 0x003E0'i32, 501, + 0x003E2'i32, 501, + 0x003E4'i32, 501, + 0x003E6'i32, 501, + 0x003E8'i32, 501, + 0x003EA'i32, 501, + 0x003EC'i32, 501, + 0x003EE'i32, 501, + 0x003F4'i32, 440, + 0x003F7'i32, 501, + 0x003F9'i32, 493, + 0x003FA'i32, 501, + 0x00460'i32, 501, + 0x00462'i32, 501, + 0x00464'i32, 501, + 0x00466'i32, 501, + 0x00468'i32, 501, + 0x0046A'i32, 501, + 0x0046C'i32, 501, + 0x0046E'i32, 501, + 0x00470'i32, 501, + 0x00472'i32, 501, + 0x00474'i32, 501, + 0x00476'i32, 501, + 0x00478'i32, 501, + 0x0047A'i32, 501, + 0x0047C'i32, 501, + 0x0047E'i32, 501, + 0x00480'i32, 501, + 0x0048A'i32, 501, + 0x0048C'i32, 501, + 0x0048E'i32, 501, + 0x00490'i32, 501, + 0x00492'i32, 501, + 0x00494'i32, 501, + 0x00496'i32, 501, + 0x00498'i32, 501, + 0x0049A'i32, 501, + 0x0049C'i32, 501, + 0x0049E'i32, 501, + 0x004A0'i32, 501, + 0x004A2'i32, 501, + 0x004A4'i32, 501, + 0x004A6'i32, 501, + 0x004A8'i32, 501, + 0x004AA'i32, 501, + 0x004AC'i32, 501, + 0x004AE'i32, 501, + 0x004B0'i32, 501, + 0x004B2'i32, 501, + 0x004B4'i32, 501, + 0x004B6'i32, 501, + 0x004B8'i32, 501, + 0x004BA'i32, 501, + 0x004BC'i32, 501, + 0x004BE'i32, 501, + 0x004C0'i32, 515, + 0x004C1'i32, 501, + 0x004C3'i32, 501, + 0x004C5'i32, 501, + 0x004C7'i32, 501, + 0x004C9'i32, 501, + 0x004CB'i32, 501, + 0x004CD'i32, 501, + 0x004D0'i32, 501, + 0x004D2'i32, 501, + 0x004D4'i32, 501, + 0x004D6'i32, 501, + 0x004D8'i32, 501, + 0x004DA'i32, 501, + 0x004DC'i32, 501, + 0x004DE'i32, 501, + 0x004E0'i32, 501, + 0x004E2'i32, 501, + 0x004E4'i32, 501, + 0x004E6'i32, 501, + 0x004E8'i32, 501, + 0x004EA'i32, 501, + 0x004EC'i32, 501, + 0x004EE'i32, 501, + 0x004F0'i32, 501, + 0x004F2'i32, 501, + 0x004F4'i32, 501, + 0x004F6'i32, 501, + 0x004F8'i32, 501, + 0x004FA'i32, 501, + 0x004FC'i32, 501, + 0x004FE'i32, 501, + 0x00500'i32, 501, + 0x00502'i32, 501, + 0x00504'i32, 501, + 0x00506'i32, 501, + 0x00508'i32, 501, + 0x0050A'i32, 501, + 0x0050C'i32, 501, + 0x0050E'i32, 501, + 0x00510'i32, 501, + 0x00512'i32, 501, + 0x00514'i32, 501, + 0x00516'i32, 501, + 0x00518'i32, 501, + 0x0051A'i32, 501, + 0x0051C'i32, 501, + 0x0051E'i32, 501, + 0x00520'i32, 501, + 0x00522'i32, 501, + 0x00524'i32, 501, + 0x00526'i32, 501, + 0x00528'i32, 501, + 0x0052A'i32, 501, + 0x0052C'i32, 501, + 0x0052E'i32, 501, + 0x010C7'i32, 7764, + 0x010CD'i32, 7764, + 0x01E00'i32, 501, + 0x01E02'i32, 501, + 0x01E04'i32, 501, + 0x01E06'i32, 501, + 0x01E08'i32, 501, + 0x01E0A'i32, 501, + 0x01E0C'i32, 501, + 0x01E0E'i32, 501, + 0x01E10'i32, 501, + 0x01E12'i32, 501, + 0x01E14'i32, 501, + 0x01E16'i32, 501, + 0x01E18'i32, 501, + 0x01E1A'i32, 501, + 0x01E1C'i32, 501, + 0x01E1E'i32, 501, + 0x01E20'i32, 501, + 0x01E22'i32, 501, + 0x01E24'i32, 501, + 0x01E26'i32, 501, + 0x01E28'i32, 501, + 0x01E2A'i32, 501, + 0x01E2C'i32, 501, + 0x01E2E'i32, 501, + 0x01E30'i32, 501, + 0x01E32'i32, 501, + 0x01E34'i32, 501, + 0x01E36'i32, 501, + 0x01E38'i32, 501, + 0x01E3A'i32, 501, + 0x01E3C'i32, 501, + 0x01E3E'i32, 501, + 0x01E40'i32, 501, + 0x01E42'i32, 501, + 0x01E44'i32, 501, + 0x01E46'i32, 501, + 0x01E48'i32, 501, + 0x01E4A'i32, 501, + 0x01E4C'i32, 501, + 0x01E4E'i32, 501, + 0x01E50'i32, 501, + 0x01E52'i32, 501, + 0x01E54'i32, 501, + 0x01E56'i32, 501, + 0x01E58'i32, 501, + 0x01E5A'i32, 501, + 0x01E5C'i32, 501, + 0x01E5E'i32, 501, + 0x01E60'i32, 501, + 0x01E62'i32, 501, + 0x01E64'i32, 501, + 0x01E66'i32, 501, + 0x01E68'i32, 501, + 0x01E6A'i32, 501, + 0x01E6C'i32, 501, + 0x01E6E'i32, 501, + 0x01E70'i32, 501, + 0x01E72'i32, 501, + 0x01E74'i32, 501, + 0x01E76'i32, 501, + 0x01E78'i32, 501, + 0x01E7A'i32, 501, + 0x01E7C'i32, 501, + 0x01E7E'i32, 501, + 0x01E80'i32, 501, + 0x01E82'i32, 501, + 0x01E84'i32, 501, + 0x01E86'i32, 501, + 0x01E88'i32, 501, + 0x01E8A'i32, 501, + 0x01E8C'i32, 501, + 0x01E8E'i32, 501, + 0x01E90'i32, 501, + 0x01E92'i32, 501, + 0x01E94'i32, 501, + 0x01E9E'i32, -7115, + 0x01EA0'i32, 501, + 0x01EA2'i32, 501, + 0x01EA4'i32, 501, + 0x01EA6'i32, 501, + 0x01EA8'i32, 501, + 0x01EAA'i32, 501, + 0x01EAC'i32, 501, + 0x01EAE'i32, 501, + 0x01EB0'i32, 501, + 0x01EB2'i32, 501, + 0x01EB4'i32, 501, + 0x01EB6'i32, 501, + 0x01EB8'i32, 501, + 0x01EBA'i32, 501, + 0x01EBC'i32, 501, + 0x01EBE'i32, 501, + 0x01EC0'i32, 501, + 0x01EC2'i32, 501, + 0x01EC4'i32, 501, + 0x01EC6'i32, 501, + 0x01EC8'i32, 501, + 0x01ECA'i32, 501, + 0x01ECC'i32, 501, + 0x01ECE'i32, 501, + 0x01ED0'i32, 501, + 0x01ED2'i32, 501, + 0x01ED4'i32, 501, + 0x01ED6'i32, 501, + 0x01ED8'i32, 501, + 0x01EDA'i32, 501, + 0x01EDC'i32, 501, + 0x01EDE'i32, 501, + 0x01EE0'i32, 501, + 0x01EE2'i32, 501, + 0x01EE4'i32, 501, + 0x01EE6'i32, 501, + 0x01EE8'i32, 501, + 0x01EEA'i32, 501, + 0x01EEC'i32, 501, + 0x01EEE'i32, 501, + 0x01EF0'i32, 501, + 0x01EF2'i32, 501, + 0x01EF4'i32, 501, + 0x01EF6'i32, 501, + 0x01EF8'i32, 501, + 0x01EFA'i32, 501, + 0x01EFC'i32, 501, + 0x01EFE'i32, 501, + 0x01F59'i32, 492, + 0x01F5B'i32, 492, + 0x01F5D'i32, 492, + 0x01F5F'i32, 492, + 0x01FBC'i32, 491, + 0x01FCC'i32, 491, + 0x01FEC'i32, 493, + 0x01FFC'i32, 491, + 0x02126'i32, -7017, + 0x0212A'i32, -7883, + 0x0212B'i32, -7762, + 0x02132'i32, 528, + 0x02183'i32, 501, + 0x02C60'i32, 501, + 0x02C62'i32, -10243, + 0x02C63'i32, -3314, + 0x02C64'i32, -10227, + 0x02C67'i32, 501, + 0x02C69'i32, 501, + 0x02C6B'i32, 501, + 0x02C6D'i32, -10280, + 0x02C6E'i32, -10249, + 0x02C6F'i32, -10283, + 0x02C70'i32, -10282, + 0x02C72'i32, 501, + 0x02C75'i32, 501, + 0x02C80'i32, 501, + 0x02C82'i32, 501, + 0x02C84'i32, 501, + 0x02C86'i32, 501, + 0x02C88'i32, 501, + 0x02C8A'i32, 501, + 0x02C8C'i32, 501, + 0x02C8E'i32, 501, + 0x02C90'i32, 501, + 0x02C92'i32, 501, + 0x02C94'i32, 501, + 0x02C96'i32, 501, + 0x02C98'i32, 501, + 0x02C9A'i32, 501, + 0x02C9C'i32, 501, + 0x02C9E'i32, 501, + 0x02CA0'i32, 501, + 0x02CA2'i32, 501, + 0x02CA4'i32, 501, + 0x02CA6'i32, 501, + 0x02CA8'i32, 501, + 0x02CAA'i32, 501, + 0x02CAC'i32, 501, + 0x02CAE'i32, 501, + 0x02CB0'i32, 501, + 0x02CB2'i32, 501, + 0x02CB4'i32, 501, + 0x02CB6'i32, 501, + 0x02CB8'i32, 501, + 0x02CBA'i32, 501, + 0x02CBC'i32, 501, + 0x02CBE'i32, 501, + 0x02CC0'i32, 501, + 0x02CC2'i32, 501, + 0x02CC4'i32, 501, + 0x02CC6'i32, 501, + 0x02CC8'i32, 501, + 0x02CCA'i32, 501, + 0x02CCC'i32, 501, + 0x02CCE'i32, 501, + 0x02CD0'i32, 501, + 0x02CD2'i32, 501, + 0x02CD4'i32, 501, + 0x02CD6'i32, 501, + 0x02CD8'i32, 501, + 0x02CDA'i32, 501, + 0x02CDC'i32, 501, + 0x02CDE'i32, 501, + 0x02CE0'i32, 501, + 0x02CE2'i32, 501, + 0x02CEB'i32, 501, + 0x02CED'i32, 501, + 0x02CF2'i32, 501, + 0x0A640'i32, 501, + 0x0A642'i32, 501, + 0x0A644'i32, 501, + 0x0A646'i32, 501, + 0x0A648'i32, 501, + 0x0A64A'i32, 501, + 0x0A64C'i32, 501, + 0x0A64E'i32, 501, + 0x0A650'i32, 501, + 0x0A652'i32, 501, + 0x0A654'i32, 501, + 0x0A656'i32, 501, + 0x0A658'i32, 501, + 0x0A65A'i32, 501, + 0x0A65C'i32, 501, + 0x0A65E'i32, 501, + 0x0A660'i32, 501, + 0x0A662'i32, 501, + 0x0A664'i32, 501, + 0x0A666'i32, 501, + 0x0A668'i32, 501, + 0x0A66A'i32, 501, + 0x0A66C'i32, 501, + 0x0A680'i32, 501, + 0x0A682'i32, 501, + 0x0A684'i32, 501, + 0x0A686'i32, 501, + 0x0A688'i32, 501, + 0x0A68A'i32, 501, + 0x0A68C'i32, 501, + 0x0A68E'i32, 501, + 0x0A690'i32, 501, + 0x0A692'i32, 501, + 0x0A694'i32, 501, + 0x0A696'i32, 501, + 0x0A698'i32, 501, + 0x0A69A'i32, 501, + 0x0A722'i32, 501, + 0x0A724'i32, 501, + 0x0A726'i32, 501, + 0x0A728'i32, 501, + 0x0A72A'i32, 501, + 0x0A72C'i32, 501, + 0x0A72E'i32, 501, + 0x0A732'i32, 501, + 0x0A734'i32, 501, + 0x0A736'i32, 501, + 0x0A738'i32, 501, + 0x0A73A'i32, 501, + 0x0A73C'i32, 501, + 0x0A73E'i32, 501, + 0x0A740'i32, 501, + 0x0A742'i32, 501, + 0x0A744'i32, 501, + 0x0A746'i32, 501, + 0x0A748'i32, 501, + 0x0A74A'i32, 501, + 0x0A74C'i32, 501, + 0x0A74E'i32, 501, + 0x0A750'i32, 501, + 0x0A752'i32, 501, + 0x0A754'i32, 501, + 0x0A756'i32, 501, + 0x0A758'i32, 501, + 0x0A75A'i32, 501, + 0x0A75C'i32, 501, + 0x0A75E'i32, 501, + 0x0A760'i32, 501, + 0x0A762'i32, 501, + 0x0A764'i32, 501, + 0x0A766'i32, 501, + 0x0A768'i32, 501, + 0x0A76A'i32, 501, + 0x0A76C'i32, 501, + 0x0A76E'i32, 501, + 0x0A779'i32, 501, + 0x0A77B'i32, 501, + 0x0A77D'i32, -34832, + 0x0A77E'i32, 501, + 0x0A780'i32, 501, + 0x0A782'i32, 501, + 0x0A784'i32, 501, + 0x0A786'i32, 501, + 0x0A78B'i32, 501, + 0x0A78D'i32, -41780, + 0x0A790'i32, 501, + 0x0A792'i32, 501, + 0x0A796'i32, 501, + 0x0A798'i32, 501, + 0x0A79A'i32, 501, + 0x0A79C'i32, 501, + 0x0A79E'i32, 501, + 0x0A7A0'i32, 501, + 0x0A7A2'i32, 501, + 0x0A7A4'i32, 501, + 0x0A7A6'i32, 501, + 0x0A7A8'i32, 501, + 0x0A7AA'i32, -41808, + 0x0A7AB'i32, -41819, + 0x0A7AC'i32, -41815, + 0x0A7AD'i32, -41805, + 0x0A7AE'i32, -41808, + 0x0A7B0'i32, -41758, + 0x0A7B1'i32, -41782, + 0x0A7B2'i32, -41761, + 0x0A7B3'i32, 1428, + 0x0A7B4'i32, 501, + 0x0A7B6'i32, 501, + 0x0A7B8'i32, 501, + 0x0A7BA'i32, 501, + 0x0A7BC'i32, 501, + 0x0A7BE'i32, 501, + 0x0A7C2'i32, 501, + 0x0A7C4'i32, 452, + 0x0A7C5'i32, -41807, + 0x0A7C6'i32, -34884, ] toUpperRanges = [ - 0x00061, 0x0007A, 468, - 0x000E0, 0x000F6, 468, - 0x000F8, 0x000FE, 468, - 0x0023F, 0x00240, 11315, - 0x00256, 0x00257, 295, - 0x0028A, 0x0028B, 283, - 0x0037B, 0x0037D, 630, - 0x003AD, 0x003AF, 463, - 0x003B1, 0x003C1, 468, - 0x003C3, 0x003CB, 468, - 0x003CD, 0x003CE, 437, - 0x00430, 0x0044F, 468, - 0x00450, 0x0045F, 420, - 0x00561, 0x00586, 452, - 0x010D0, 0x010FA, 3508, - 0x010FD, 0x010FF, 3508, - 0x013F8, 0x013FD, 492, - 0x01C83, 0x01C84, -5742, - 0x01F00, 0x01F07, 508, - 0x01F10, 0x01F15, 508, - 0x01F20, 0x01F27, 508, - 0x01F30, 0x01F37, 508, - 0x01F40, 0x01F45, 508, - 0x01F60, 0x01F67, 508, - 0x01F70, 0x01F71, 574, - 0x01F72, 0x01F75, 586, - 0x01F76, 0x01F77, 600, - 0x01F78, 0x01F79, 628, - 0x01F7A, 0x01F7B, 612, - 0x01F7C, 0x01F7D, 626, - 0x01F80, 0x01F87, 508, - 0x01F90, 0x01F97, 508, - 0x01FA0, 0x01FA7, 508, - 0x01FB0, 0x01FB1, 508, - 0x01FD0, 0x01FD1, 508, - 0x01FE0, 0x01FE1, 508, - 0x02C30, 0x02C5E, 452, - 0x02D00, 0x02D25, -6764, - 0x0AB70, 0x0ABBF, -38364, - 0x0FF41, 0x0FF5A, 468, - 0x10428, 0x1044F, 460, - 0x104D8, 0x104FB, 460, - 0x10CC0, 0x10CF2, 436, - 0x118C0, 0x118DF, 468, - 0x16E60, 0x16E7F, 468, - 0x1E922, 0x1E943, 466, + 0x00061'i32, 0x0007A'i32, 468, + 0x000E0'i32, 0x000F6'i32, 468, + 0x000F8'i32, 0x000FE'i32, 468, + 0x0023F'i32, 0x00240'i32, 11315, + 0x00256'i32, 0x00257'i32, 295, + 0x0028A'i32, 0x0028B'i32, 283, + 0x0037B'i32, 0x0037D'i32, 630, + 0x003AD'i32, 0x003AF'i32, 463, + 0x003B1'i32, 0x003C1'i32, 468, + 0x003C3'i32, 0x003CB'i32, 468, + 0x003CD'i32, 0x003CE'i32, 437, + 0x00430'i32, 0x0044F'i32, 468, + 0x00450'i32, 0x0045F'i32, 420, + 0x00561'i32, 0x00586'i32, 452, + 0x010D0'i32, 0x010FA'i32, 3508, + 0x010FD'i32, 0x010FF'i32, 3508, + 0x013F8'i32, 0x013FD'i32, 492, + 0x01C83'i32, 0x01C84'i32, -5742, + 0x01F00'i32, 0x01F07'i32, 508, + 0x01F10'i32, 0x01F15'i32, 508, + 0x01F20'i32, 0x01F27'i32, 508, + 0x01F30'i32, 0x01F37'i32, 508, + 0x01F40'i32, 0x01F45'i32, 508, + 0x01F60'i32, 0x01F67'i32, 508, + 0x01F70'i32, 0x01F71'i32, 574, + 0x01F72'i32, 0x01F75'i32, 586, + 0x01F76'i32, 0x01F77'i32, 600, + 0x01F78'i32, 0x01F79'i32, 628, + 0x01F7A'i32, 0x01F7B'i32, 612, + 0x01F7C'i32, 0x01F7D'i32, 626, + 0x01F80'i32, 0x01F87'i32, 508, + 0x01F90'i32, 0x01F97'i32, 508, + 0x01FA0'i32, 0x01FA7'i32, 508, + 0x01FB0'i32, 0x01FB1'i32, 508, + 0x01FD0'i32, 0x01FD1'i32, 508, + 0x01FE0'i32, 0x01FE1'i32, 508, + 0x02C30'i32, 0x02C5E'i32, 452, + 0x02D00'i32, 0x02D25'i32, -6764, + 0x0AB70'i32, 0x0ABBF'i32, -38364, + 0x0FF41'i32, 0x0FF5A'i32, 468, + 0x10428'i32, 0x1044F'i32, 460, + 0x104D8'i32, 0x104FB'i32, 460, + 0x10CC0'i32, 0x10CF2'i32, 436, + 0x118C0'i32, 0x118DF'i32, 468, + 0x16E60'i32, 0x16E7F'i32, 468, + 0x1E922'i32, 0x1E943'i32, 466, ] toUpperSinglets = [ - 0x000B5, 1243, - 0x000FF, 621, - 0x00101, 499, - 0x00103, 499, - 0x00105, 499, - 0x00107, 499, - 0x00109, 499, - 0x0010B, 499, - 0x0010D, 499, - 0x0010F, 499, - 0x00111, 499, - 0x00113, 499, - 0x00115, 499, - 0x00117, 499, - 0x00119, 499, - 0x0011B, 499, - 0x0011D, 499, - 0x0011F, 499, - 0x00121, 499, - 0x00123, 499, - 0x00125, 499, - 0x00127, 499, - 0x00129, 499, - 0x0012B, 499, - 0x0012D, 499, - 0x0012F, 499, - 0x00131, 268, - 0x00133, 499, - 0x00135, 499, - 0x00137, 499, - 0x0013A, 499, - 0x0013C, 499, - 0x0013E, 499, - 0x00140, 499, - 0x00142, 499, - 0x00144, 499, - 0x00146, 499, - 0x00148, 499, - 0x0014B, 499, - 0x0014D, 499, - 0x0014F, 499, - 0x00151, 499, - 0x00153, 499, - 0x00155, 499, - 0x00157, 499, - 0x00159, 499, - 0x0015B, 499, - 0x0015D, 499, - 0x0015F, 499, - 0x00161, 499, - 0x00163, 499, - 0x00165, 499, - 0x00167, 499, - 0x00169, 499, - 0x0016B, 499, - 0x0016D, 499, - 0x0016F, 499, - 0x00171, 499, - 0x00173, 499, - 0x00175, 499, - 0x00177, 499, - 0x0017A, 499, - 0x0017C, 499, - 0x0017E, 499, - 0x0017F, 200, - 0x00180, 695, - 0x00183, 499, - 0x00185, 499, - 0x00188, 499, - 0x0018C, 499, - 0x00192, 499, - 0x00195, 597, - 0x00199, 499, - 0x0019A, 663, - 0x0019E, 630, - 0x001A1, 499, - 0x001A3, 499, - 0x001A5, 499, - 0x001A8, 499, - 0x001AD, 499, - 0x001B0, 499, - 0x001B4, 499, - 0x001B6, 499, - 0x001B9, 499, - 0x001BD, 499, - 0x001BF, 556, - 0x001C5, 499, - 0x001C6, 498, - 0x001C8, 499, - 0x001C9, 498, - 0x001CB, 499, - 0x001CC, 498, - 0x001CE, 499, - 0x001D0, 499, - 0x001D2, 499, - 0x001D4, 499, - 0x001D6, 499, - 0x001D8, 499, - 0x001DA, 499, - 0x001DC, 499, - 0x001DD, 421, - 0x001DF, 499, - 0x001E1, 499, - 0x001E3, 499, - 0x001E5, 499, - 0x001E7, 499, - 0x001E9, 499, - 0x001EB, 499, - 0x001ED, 499, - 0x001EF, 499, - 0x001F2, 499, - 0x001F3, 498, - 0x001F5, 499, - 0x001F9, 499, - 0x001FB, 499, - 0x001FD, 499, - 0x001FF, 499, - 0x00201, 499, - 0x00203, 499, - 0x00205, 499, - 0x00207, 499, - 0x00209, 499, - 0x0020B, 499, - 0x0020D, 499, - 0x0020F, 499, - 0x00211, 499, - 0x00213, 499, - 0x00215, 499, - 0x00217, 499, - 0x00219, 499, - 0x0021B, 499, - 0x0021D, 499, - 0x0021F, 499, - 0x00223, 499, - 0x00225, 499, - 0x00227, 499, - 0x00229, 499, - 0x0022B, 499, - 0x0022D, 499, - 0x0022F, 499, - 0x00231, 499, - 0x00233, 499, - 0x0023C, 499, - 0x00242, 499, - 0x00247, 499, - 0x00249, 499, - 0x0024B, 499, - 0x0024D, 499, - 0x0024F, 499, - 0x00250, 11283, - 0x00251, 11280, - 0x00252, 11282, - 0x00253, 290, - 0x00254, 294, - 0x00259, 298, - 0x0025B, 297, - 0x0025C, 42819, - 0x00260, 295, - 0x00261, 42815, - 0x00263, 293, - 0x00265, 42780, - 0x00266, 42808, - 0x00268, 291, - 0x00269, 289, - 0x0026A, 42808, - 0x0026B, 11243, - 0x0026C, 42805, - 0x0026F, 289, - 0x00271, 11249, - 0x00272, 287, - 0x00275, 286, - 0x0027D, 11227, - 0x00280, 282, - 0x00282, 42807, - 0x00283, 282, - 0x00287, 42782, - 0x00288, 282, - 0x00289, 431, - 0x0028C, 429, - 0x00292, 281, - 0x0029D, 42761, - 0x0029E, 42758, - 0x00371, 499, - 0x00373, 499, - 0x00377, 499, - 0x003AC, 462, - 0x003C2, 469, - 0x003CC, 436, - 0x003D0, 438, - 0x003D1, 443, - 0x003D5, 453, - 0x003D6, 446, - 0x003D7, 492, - 0x003D9, 499, - 0x003DB, 499, - 0x003DD, 499, - 0x003DF, 499, - 0x003E1, 499, - 0x003E3, 499, - 0x003E5, 499, - 0x003E7, 499, - 0x003E9, 499, - 0x003EB, 499, - 0x003ED, 499, - 0x003EF, 499, - 0x003F0, 414, - 0x003F1, 420, - 0x003F2, 507, - 0x003F3, 384, - 0x003F5, 404, - 0x003F8, 499, - 0x003FB, 499, - 0x00461, 499, - 0x00463, 499, - 0x00465, 499, - 0x00467, 499, - 0x00469, 499, - 0x0046B, 499, - 0x0046D, 499, - 0x0046F, 499, - 0x00471, 499, - 0x00473, 499, - 0x00475, 499, - 0x00477, 499, - 0x00479, 499, - 0x0047B, 499, - 0x0047D, 499, - 0x0047F, 499, - 0x00481, 499, - 0x0048B, 499, - 0x0048D, 499, - 0x0048F, 499, - 0x00491, 499, - 0x00493, 499, - 0x00495, 499, - 0x00497, 499, - 0x00499, 499, - 0x0049B, 499, - 0x0049D, 499, - 0x0049F, 499, - 0x004A1, 499, - 0x004A3, 499, - 0x004A5, 499, - 0x004A7, 499, - 0x004A9, 499, - 0x004AB, 499, - 0x004AD, 499, - 0x004AF, 499, - 0x004B1, 499, - 0x004B3, 499, - 0x004B5, 499, - 0x004B7, 499, - 0x004B9, 499, - 0x004BB, 499, - 0x004BD, 499, - 0x004BF, 499, - 0x004C2, 499, - 0x004C4, 499, - 0x004C6, 499, - 0x004C8, 499, - 0x004CA, 499, - 0x004CC, 499, - 0x004CE, 499, - 0x004CF, 485, - 0x004D1, 499, - 0x004D3, 499, - 0x004D5, 499, - 0x004D7, 499, - 0x004D9, 499, - 0x004DB, 499, - 0x004DD, 499, - 0x004DF, 499, - 0x004E1, 499, - 0x004E3, 499, - 0x004E5, 499, - 0x004E7, 499, - 0x004E9, 499, - 0x004EB, 499, - 0x004ED, 499, - 0x004EF, 499, - 0x004F1, 499, - 0x004F3, 499, - 0x004F5, 499, - 0x004F7, 499, - 0x004F9, 499, - 0x004FB, 499, - 0x004FD, 499, - 0x004FF, 499, - 0x00501, 499, - 0x00503, 499, - 0x00505, 499, - 0x00507, 499, - 0x00509, 499, - 0x0050B, 499, - 0x0050D, 499, - 0x0050F, 499, - 0x00511, 499, - 0x00513, 499, - 0x00515, 499, - 0x00517, 499, - 0x00519, 499, - 0x0051B, 499, - 0x0051D, 499, - 0x0051F, 499, - 0x00521, 499, - 0x00523, 499, - 0x00525, 499, - 0x00527, 499, - 0x00529, 499, - 0x0052B, 499, - 0x0052D, 499, - 0x0052F, 499, - 0x01C80, -5754, - 0x01C81, -5753, - 0x01C82, -5744, - 0x01C85, -5743, - 0x01C86, -5736, - 0x01C87, -5681, - 0x01C88, 35766, - 0x01D79, 35832, - 0x01D7D, 4314, - 0x01D8E, 35884, - 0x01E01, 499, - 0x01E03, 499, - 0x01E05, 499, - 0x01E07, 499, - 0x01E09, 499, - 0x01E0B, 499, - 0x01E0D, 499, - 0x01E0F, 499, - 0x01E11, 499, - 0x01E13, 499, - 0x01E15, 499, - 0x01E17, 499, - 0x01E19, 499, - 0x01E1B, 499, - 0x01E1D, 499, - 0x01E1F, 499, - 0x01E21, 499, - 0x01E23, 499, - 0x01E25, 499, - 0x01E27, 499, - 0x01E29, 499, - 0x01E2B, 499, - 0x01E2D, 499, - 0x01E2F, 499, - 0x01E31, 499, - 0x01E33, 499, - 0x01E35, 499, - 0x01E37, 499, - 0x01E39, 499, - 0x01E3B, 499, - 0x01E3D, 499, - 0x01E3F, 499, - 0x01E41, 499, - 0x01E43, 499, - 0x01E45, 499, - 0x01E47, 499, - 0x01E49, 499, - 0x01E4B, 499, - 0x01E4D, 499, - 0x01E4F, 499, - 0x01E51, 499, - 0x01E53, 499, - 0x01E55, 499, - 0x01E57, 499, - 0x01E59, 499, - 0x01E5B, 499, - 0x01E5D, 499, - 0x01E5F, 499, - 0x01E61, 499, - 0x01E63, 499, - 0x01E65, 499, - 0x01E67, 499, - 0x01E69, 499, - 0x01E6B, 499, - 0x01E6D, 499, - 0x01E6F, 499, - 0x01E71, 499, - 0x01E73, 499, - 0x01E75, 499, - 0x01E77, 499, - 0x01E79, 499, - 0x01E7B, 499, - 0x01E7D, 499, - 0x01E7F, 499, - 0x01E81, 499, - 0x01E83, 499, - 0x01E85, 499, - 0x01E87, 499, - 0x01E89, 499, - 0x01E8B, 499, - 0x01E8D, 499, - 0x01E8F, 499, - 0x01E91, 499, - 0x01E93, 499, - 0x01E95, 499, - 0x01E9B, 441, - 0x01EA1, 499, - 0x01EA3, 499, - 0x01EA5, 499, - 0x01EA7, 499, - 0x01EA9, 499, - 0x01EAB, 499, - 0x01EAD, 499, - 0x01EAF, 499, - 0x01EB1, 499, - 0x01EB3, 499, - 0x01EB5, 499, - 0x01EB7, 499, - 0x01EB9, 499, - 0x01EBB, 499, - 0x01EBD, 499, - 0x01EBF, 499, - 0x01EC1, 499, - 0x01EC3, 499, - 0x01EC5, 499, - 0x01EC7, 499, - 0x01EC9, 499, - 0x01ECB, 499, - 0x01ECD, 499, - 0x01ECF, 499, - 0x01ED1, 499, - 0x01ED3, 499, - 0x01ED5, 499, - 0x01ED7, 499, - 0x01ED9, 499, - 0x01EDB, 499, - 0x01EDD, 499, - 0x01EDF, 499, - 0x01EE1, 499, - 0x01EE3, 499, - 0x01EE5, 499, - 0x01EE7, 499, - 0x01EE9, 499, - 0x01EEB, 499, - 0x01EED, 499, - 0x01EEF, 499, - 0x01EF1, 499, - 0x01EF3, 499, - 0x01EF5, 499, - 0x01EF7, 499, - 0x01EF9, 499, - 0x01EFB, 499, - 0x01EFD, 499, - 0x01EFF, 499, - 0x01F51, 508, - 0x01F53, 508, - 0x01F55, 508, - 0x01F57, 508, - 0x01FB3, 509, - 0x01FBE, -6705, - 0x01FC3, 509, - 0x01FE5, 507, - 0x01FF3, 509, - 0x0214E, 472, - 0x02184, 499, - 0x02C61, 499, - 0x02C65, -10295, - 0x02C66, -10292, - 0x02C68, 499, - 0x02C6A, 499, - 0x02C6C, 499, - 0x02C73, 499, - 0x02C76, 499, - 0x02C81, 499, - 0x02C83, 499, - 0x02C85, 499, - 0x02C87, 499, - 0x02C89, 499, - 0x02C8B, 499, - 0x02C8D, 499, - 0x02C8F, 499, - 0x02C91, 499, - 0x02C93, 499, - 0x02C95, 499, - 0x02C97, 499, - 0x02C99, 499, - 0x02C9B, 499, - 0x02C9D, 499, - 0x02C9F, 499, - 0x02CA1, 499, - 0x02CA3, 499, - 0x02CA5, 499, - 0x02CA7, 499, - 0x02CA9, 499, - 0x02CAB, 499, - 0x02CAD, 499, - 0x02CAF, 499, - 0x02CB1, 499, - 0x02CB3, 499, - 0x02CB5, 499, - 0x02CB7, 499, - 0x02CB9, 499, - 0x02CBB, 499, - 0x02CBD, 499, - 0x02CBF, 499, - 0x02CC1, 499, - 0x02CC3, 499, - 0x02CC5, 499, - 0x02CC7, 499, - 0x02CC9, 499, - 0x02CCB, 499, - 0x02CCD, 499, - 0x02CCF, 499, - 0x02CD1, 499, - 0x02CD3, 499, - 0x02CD5, 499, - 0x02CD7, 499, - 0x02CD9, 499, - 0x02CDB, 499, - 0x02CDD, 499, - 0x02CDF, 499, - 0x02CE1, 499, - 0x02CE3, 499, - 0x02CEC, 499, - 0x02CEE, 499, - 0x02CF3, 499, - 0x02D27, -6764, - 0x02D2D, -6764, - 0x0A641, 499, - 0x0A643, 499, - 0x0A645, 499, - 0x0A647, 499, - 0x0A649, 499, - 0x0A64B, 499, - 0x0A64D, 499, - 0x0A64F, 499, - 0x0A651, 499, - 0x0A653, 499, - 0x0A655, 499, - 0x0A657, 499, - 0x0A659, 499, - 0x0A65B, 499, - 0x0A65D, 499, - 0x0A65F, 499, - 0x0A661, 499, - 0x0A663, 499, - 0x0A665, 499, - 0x0A667, 499, - 0x0A669, 499, - 0x0A66B, 499, - 0x0A66D, 499, - 0x0A681, 499, - 0x0A683, 499, - 0x0A685, 499, - 0x0A687, 499, - 0x0A689, 499, - 0x0A68B, 499, - 0x0A68D, 499, - 0x0A68F, 499, - 0x0A691, 499, - 0x0A693, 499, - 0x0A695, 499, - 0x0A697, 499, - 0x0A699, 499, - 0x0A69B, 499, - 0x0A723, 499, - 0x0A725, 499, - 0x0A727, 499, - 0x0A729, 499, - 0x0A72B, 499, - 0x0A72D, 499, - 0x0A72F, 499, - 0x0A733, 499, - 0x0A735, 499, - 0x0A737, 499, - 0x0A739, 499, - 0x0A73B, 499, - 0x0A73D, 499, - 0x0A73F, 499, - 0x0A741, 499, - 0x0A743, 499, - 0x0A745, 499, - 0x0A747, 499, - 0x0A749, 499, - 0x0A74B, 499, - 0x0A74D, 499, - 0x0A74F, 499, - 0x0A751, 499, - 0x0A753, 499, - 0x0A755, 499, - 0x0A757, 499, - 0x0A759, 499, - 0x0A75B, 499, - 0x0A75D, 499, - 0x0A75F, 499, - 0x0A761, 499, - 0x0A763, 499, - 0x0A765, 499, - 0x0A767, 499, - 0x0A769, 499, - 0x0A76B, 499, - 0x0A76D, 499, - 0x0A76F, 499, - 0x0A77A, 499, - 0x0A77C, 499, - 0x0A77F, 499, - 0x0A781, 499, - 0x0A783, 499, - 0x0A785, 499, - 0x0A787, 499, - 0x0A78C, 499, - 0x0A791, 499, - 0x0A793, 499, - 0x0A794, 548, - 0x0A797, 499, - 0x0A799, 499, - 0x0A79B, 499, - 0x0A79D, 499, - 0x0A79F, 499, - 0x0A7A1, 499, - 0x0A7A3, 499, - 0x0A7A5, 499, - 0x0A7A7, 499, - 0x0A7A9, 499, - 0x0A7B5, 499, - 0x0A7B7, 499, - 0x0A7B9, 499, - 0x0A7BB, 499, - 0x0A7BD, 499, - 0x0A7BF, 499, - 0x0A7C3, 499, - 0x0AB53, -428, + 0x000B5'i32, 1243, + 0x000FF'i32, 621, + 0x00101'i32, 499, + 0x00103'i32, 499, + 0x00105'i32, 499, + 0x00107'i32, 499, + 0x00109'i32, 499, + 0x0010B'i32, 499, + 0x0010D'i32, 499, + 0x0010F'i32, 499, + 0x00111'i32, 499, + 0x00113'i32, 499, + 0x00115'i32, 499, + 0x00117'i32, 499, + 0x00119'i32, 499, + 0x0011B'i32, 499, + 0x0011D'i32, 499, + 0x0011F'i32, 499, + 0x00121'i32, 499, + 0x00123'i32, 499, + 0x00125'i32, 499, + 0x00127'i32, 499, + 0x00129'i32, 499, + 0x0012B'i32, 499, + 0x0012D'i32, 499, + 0x0012F'i32, 499, + 0x00131'i32, 268, + 0x00133'i32, 499, + 0x00135'i32, 499, + 0x00137'i32, 499, + 0x0013A'i32, 499, + 0x0013C'i32, 499, + 0x0013E'i32, 499, + 0x00140'i32, 499, + 0x00142'i32, 499, + 0x00144'i32, 499, + 0x00146'i32, 499, + 0x00148'i32, 499, + 0x0014B'i32, 499, + 0x0014D'i32, 499, + 0x0014F'i32, 499, + 0x00151'i32, 499, + 0x00153'i32, 499, + 0x00155'i32, 499, + 0x00157'i32, 499, + 0x00159'i32, 499, + 0x0015B'i32, 499, + 0x0015D'i32, 499, + 0x0015F'i32, 499, + 0x00161'i32, 499, + 0x00163'i32, 499, + 0x00165'i32, 499, + 0x00167'i32, 499, + 0x00169'i32, 499, + 0x0016B'i32, 499, + 0x0016D'i32, 499, + 0x0016F'i32, 499, + 0x00171'i32, 499, + 0x00173'i32, 499, + 0x00175'i32, 499, + 0x00177'i32, 499, + 0x0017A'i32, 499, + 0x0017C'i32, 499, + 0x0017E'i32, 499, + 0x0017F'i32, 200, + 0x00180'i32, 695, + 0x00183'i32, 499, + 0x00185'i32, 499, + 0x00188'i32, 499, + 0x0018C'i32, 499, + 0x00192'i32, 499, + 0x00195'i32, 597, + 0x00199'i32, 499, + 0x0019A'i32, 663, + 0x0019E'i32, 630, + 0x001A1'i32, 499, + 0x001A3'i32, 499, + 0x001A5'i32, 499, + 0x001A8'i32, 499, + 0x001AD'i32, 499, + 0x001B0'i32, 499, + 0x001B4'i32, 499, + 0x001B6'i32, 499, + 0x001B9'i32, 499, + 0x001BD'i32, 499, + 0x001BF'i32, 556, + 0x001C5'i32, 499, + 0x001C6'i32, 498, + 0x001C8'i32, 499, + 0x001C9'i32, 498, + 0x001CB'i32, 499, + 0x001CC'i32, 498, + 0x001CE'i32, 499, + 0x001D0'i32, 499, + 0x001D2'i32, 499, + 0x001D4'i32, 499, + 0x001D6'i32, 499, + 0x001D8'i32, 499, + 0x001DA'i32, 499, + 0x001DC'i32, 499, + 0x001DD'i32, 421, + 0x001DF'i32, 499, + 0x001E1'i32, 499, + 0x001E3'i32, 499, + 0x001E5'i32, 499, + 0x001E7'i32, 499, + 0x001E9'i32, 499, + 0x001EB'i32, 499, + 0x001ED'i32, 499, + 0x001EF'i32, 499, + 0x001F2'i32, 499, + 0x001F3'i32, 498, + 0x001F5'i32, 499, + 0x001F9'i32, 499, + 0x001FB'i32, 499, + 0x001FD'i32, 499, + 0x001FF'i32, 499, + 0x00201'i32, 499, + 0x00203'i32, 499, + 0x00205'i32, 499, + 0x00207'i32, 499, + 0x00209'i32, 499, + 0x0020B'i32, 499, + 0x0020D'i32, 499, + 0x0020F'i32, 499, + 0x00211'i32, 499, + 0x00213'i32, 499, + 0x00215'i32, 499, + 0x00217'i32, 499, + 0x00219'i32, 499, + 0x0021B'i32, 499, + 0x0021D'i32, 499, + 0x0021F'i32, 499, + 0x00223'i32, 499, + 0x00225'i32, 499, + 0x00227'i32, 499, + 0x00229'i32, 499, + 0x0022B'i32, 499, + 0x0022D'i32, 499, + 0x0022F'i32, 499, + 0x00231'i32, 499, + 0x00233'i32, 499, + 0x0023C'i32, 499, + 0x00242'i32, 499, + 0x00247'i32, 499, + 0x00249'i32, 499, + 0x0024B'i32, 499, + 0x0024D'i32, 499, + 0x0024F'i32, 499, + 0x00250'i32, 11283, + 0x00251'i32, 11280, + 0x00252'i32, 11282, + 0x00253'i32, 290, + 0x00254'i32, 294, + 0x00259'i32, 298, + 0x0025B'i32, 297, + 0x0025C'i32, 42819, + 0x00260'i32, 295, + 0x00261'i32, 42815, + 0x00263'i32, 293, + 0x00265'i32, 42780, + 0x00266'i32, 42808, + 0x00268'i32, 291, + 0x00269'i32, 289, + 0x0026A'i32, 42808, + 0x0026B'i32, 11243, + 0x0026C'i32, 42805, + 0x0026F'i32, 289, + 0x00271'i32, 11249, + 0x00272'i32, 287, + 0x00275'i32, 286, + 0x0027D'i32, 11227, + 0x00280'i32, 282, + 0x00282'i32, 42807, + 0x00283'i32, 282, + 0x00287'i32, 42782, + 0x00288'i32, 282, + 0x00289'i32, 431, + 0x0028C'i32, 429, + 0x00292'i32, 281, + 0x0029D'i32, 42761, + 0x0029E'i32, 42758, + 0x00371'i32, 499, + 0x00373'i32, 499, + 0x00377'i32, 499, + 0x003AC'i32, 462, + 0x003C2'i32, 469, + 0x003CC'i32, 436, + 0x003D0'i32, 438, + 0x003D1'i32, 443, + 0x003D5'i32, 453, + 0x003D6'i32, 446, + 0x003D7'i32, 492, + 0x003D9'i32, 499, + 0x003DB'i32, 499, + 0x003DD'i32, 499, + 0x003DF'i32, 499, + 0x003E1'i32, 499, + 0x003E3'i32, 499, + 0x003E5'i32, 499, + 0x003E7'i32, 499, + 0x003E9'i32, 499, + 0x003EB'i32, 499, + 0x003ED'i32, 499, + 0x003EF'i32, 499, + 0x003F0'i32, 414, + 0x003F1'i32, 420, + 0x003F2'i32, 507, + 0x003F3'i32, 384, + 0x003F5'i32, 404, + 0x003F8'i32, 499, + 0x003FB'i32, 499, + 0x00461'i32, 499, + 0x00463'i32, 499, + 0x00465'i32, 499, + 0x00467'i32, 499, + 0x00469'i32, 499, + 0x0046B'i32, 499, + 0x0046D'i32, 499, + 0x0046F'i32, 499, + 0x00471'i32, 499, + 0x00473'i32, 499, + 0x00475'i32, 499, + 0x00477'i32, 499, + 0x00479'i32, 499, + 0x0047B'i32, 499, + 0x0047D'i32, 499, + 0x0047F'i32, 499, + 0x00481'i32, 499, + 0x0048B'i32, 499, + 0x0048D'i32, 499, + 0x0048F'i32, 499, + 0x00491'i32, 499, + 0x00493'i32, 499, + 0x00495'i32, 499, + 0x00497'i32, 499, + 0x00499'i32, 499, + 0x0049B'i32, 499, + 0x0049D'i32, 499, + 0x0049F'i32, 499, + 0x004A1'i32, 499, + 0x004A3'i32, 499, + 0x004A5'i32, 499, + 0x004A7'i32, 499, + 0x004A9'i32, 499, + 0x004AB'i32, 499, + 0x004AD'i32, 499, + 0x004AF'i32, 499, + 0x004B1'i32, 499, + 0x004B3'i32, 499, + 0x004B5'i32, 499, + 0x004B7'i32, 499, + 0x004B9'i32, 499, + 0x004BB'i32, 499, + 0x004BD'i32, 499, + 0x004BF'i32, 499, + 0x004C2'i32, 499, + 0x004C4'i32, 499, + 0x004C6'i32, 499, + 0x004C8'i32, 499, + 0x004CA'i32, 499, + 0x004CC'i32, 499, + 0x004CE'i32, 499, + 0x004CF'i32, 485, + 0x004D1'i32, 499, + 0x004D3'i32, 499, + 0x004D5'i32, 499, + 0x004D7'i32, 499, + 0x004D9'i32, 499, + 0x004DB'i32, 499, + 0x004DD'i32, 499, + 0x004DF'i32, 499, + 0x004E1'i32, 499, + 0x004E3'i32, 499, + 0x004E5'i32, 499, + 0x004E7'i32, 499, + 0x004E9'i32, 499, + 0x004EB'i32, 499, + 0x004ED'i32, 499, + 0x004EF'i32, 499, + 0x004F1'i32, 499, + 0x004F3'i32, 499, + 0x004F5'i32, 499, + 0x004F7'i32, 499, + 0x004F9'i32, 499, + 0x004FB'i32, 499, + 0x004FD'i32, 499, + 0x004FF'i32, 499, + 0x00501'i32, 499, + 0x00503'i32, 499, + 0x00505'i32, 499, + 0x00507'i32, 499, + 0x00509'i32, 499, + 0x0050B'i32, 499, + 0x0050D'i32, 499, + 0x0050F'i32, 499, + 0x00511'i32, 499, + 0x00513'i32, 499, + 0x00515'i32, 499, + 0x00517'i32, 499, + 0x00519'i32, 499, + 0x0051B'i32, 499, + 0x0051D'i32, 499, + 0x0051F'i32, 499, + 0x00521'i32, 499, + 0x00523'i32, 499, + 0x00525'i32, 499, + 0x00527'i32, 499, + 0x00529'i32, 499, + 0x0052B'i32, 499, + 0x0052D'i32, 499, + 0x0052F'i32, 499, + 0x01C80'i32, -5754, + 0x01C81'i32, -5753, + 0x01C82'i32, -5744, + 0x01C85'i32, -5743, + 0x01C86'i32, -5736, + 0x01C87'i32, -5681, + 0x01C88'i32, 35766, + 0x01D79'i32, 35832, + 0x01D7D'i32, 4314, + 0x01D8E'i32, 35884, + 0x01E01'i32, 499, + 0x01E03'i32, 499, + 0x01E05'i32, 499, + 0x01E07'i32, 499, + 0x01E09'i32, 499, + 0x01E0B'i32, 499, + 0x01E0D'i32, 499, + 0x01E0F'i32, 499, + 0x01E11'i32, 499, + 0x01E13'i32, 499, + 0x01E15'i32, 499, + 0x01E17'i32, 499, + 0x01E19'i32, 499, + 0x01E1B'i32, 499, + 0x01E1D'i32, 499, + 0x01E1F'i32, 499, + 0x01E21'i32, 499, + 0x01E23'i32, 499, + 0x01E25'i32, 499, + 0x01E27'i32, 499, + 0x01E29'i32, 499, + 0x01E2B'i32, 499, + 0x01E2D'i32, 499, + 0x01E2F'i32, 499, + 0x01E31'i32, 499, + 0x01E33'i32, 499, + 0x01E35'i32, 499, + 0x01E37'i32, 499, + 0x01E39'i32, 499, + 0x01E3B'i32, 499, + 0x01E3D'i32, 499, + 0x01E3F'i32, 499, + 0x01E41'i32, 499, + 0x01E43'i32, 499, + 0x01E45'i32, 499, + 0x01E47'i32, 499, + 0x01E49'i32, 499, + 0x01E4B'i32, 499, + 0x01E4D'i32, 499, + 0x01E4F'i32, 499, + 0x01E51'i32, 499, + 0x01E53'i32, 499, + 0x01E55'i32, 499, + 0x01E57'i32, 499, + 0x01E59'i32, 499, + 0x01E5B'i32, 499, + 0x01E5D'i32, 499, + 0x01E5F'i32, 499, + 0x01E61'i32, 499, + 0x01E63'i32, 499, + 0x01E65'i32, 499, + 0x01E67'i32, 499, + 0x01E69'i32, 499, + 0x01E6B'i32, 499, + 0x01E6D'i32, 499, + 0x01E6F'i32, 499, + 0x01E71'i32, 499, + 0x01E73'i32, 499, + 0x01E75'i32, 499, + 0x01E77'i32, 499, + 0x01E79'i32, 499, + 0x01E7B'i32, 499, + 0x01E7D'i32, 499, + 0x01E7F'i32, 499, + 0x01E81'i32, 499, + 0x01E83'i32, 499, + 0x01E85'i32, 499, + 0x01E87'i32, 499, + 0x01E89'i32, 499, + 0x01E8B'i32, 499, + 0x01E8D'i32, 499, + 0x01E8F'i32, 499, + 0x01E91'i32, 499, + 0x01E93'i32, 499, + 0x01E95'i32, 499, + 0x01E9B'i32, 441, + 0x01EA1'i32, 499, + 0x01EA3'i32, 499, + 0x01EA5'i32, 499, + 0x01EA7'i32, 499, + 0x01EA9'i32, 499, + 0x01EAB'i32, 499, + 0x01EAD'i32, 499, + 0x01EAF'i32, 499, + 0x01EB1'i32, 499, + 0x01EB3'i32, 499, + 0x01EB5'i32, 499, + 0x01EB7'i32, 499, + 0x01EB9'i32, 499, + 0x01EBB'i32, 499, + 0x01EBD'i32, 499, + 0x01EBF'i32, 499, + 0x01EC1'i32, 499, + 0x01EC3'i32, 499, + 0x01EC5'i32, 499, + 0x01EC7'i32, 499, + 0x01EC9'i32, 499, + 0x01ECB'i32, 499, + 0x01ECD'i32, 499, + 0x01ECF'i32, 499, + 0x01ED1'i32, 499, + 0x01ED3'i32, 499, + 0x01ED5'i32, 499, + 0x01ED7'i32, 499, + 0x01ED9'i32, 499, + 0x01EDB'i32, 499, + 0x01EDD'i32, 499, + 0x01EDF'i32, 499, + 0x01EE1'i32, 499, + 0x01EE3'i32, 499, + 0x01EE5'i32, 499, + 0x01EE7'i32, 499, + 0x01EE9'i32, 499, + 0x01EEB'i32, 499, + 0x01EED'i32, 499, + 0x01EEF'i32, 499, + 0x01EF1'i32, 499, + 0x01EF3'i32, 499, + 0x01EF5'i32, 499, + 0x01EF7'i32, 499, + 0x01EF9'i32, 499, + 0x01EFB'i32, 499, + 0x01EFD'i32, 499, + 0x01EFF'i32, 499, + 0x01F51'i32, 508, + 0x01F53'i32, 508, + 0x01F55'i32, 508, + 0x01F57'i32, 508, + 0x01FB3'i32, 509, + 0x01FBE'i32, -6705, + 0x01FC3'i32, 509, + 0x01FE5'i32, 507, + 0x01FF3'i32, 509, + 0x0214E'i32, 472, + 0x02184'i32, 499, + 0x02C61'i32, 499, + 0x02C65'i32, -10295, + 0x02C66'i32, -10292, + 0x02C68'i32, 499, + 0x02C6A'i32, 499, + 0x02C6C'i32, 499, + 0x02C73'i32, 499, + 0x02C76'i32, 499, + 0x02C81'i32, 499, + 0x02C83'i32, 499, + 0x02C85'i32, 499, + 0x02C87'i32, 499, + 0x02C89'i32, 499, + 0x02C8B'i32, 499, + 0x02C8D'i32, 499, + 0x02C8F'i32, 499, + 0x02C91'i32, 499, + 0x02C93'i32, 499, + 0x02C95'i32, 499, + 0x02C97'i32, 499, + 0x02C99'i32, 499, + 0x02C9B'i32, 499, + 0x02C9D'i32, 499, + 0x02C9F'i32, 499, + 0x02CA1'i32, 499, + 0x02CA3'i32, 499, + 0x02CA5'i32, 499, + 0x02CA7'i32, 499, + 0x02CA9'i32, 499, + 0x02CAB'i32, 499, + 0x02CAD'i32, 499, + 0x02CAF'i32, 499, + 0x02CB1'i32, 499, + 0x02CB3'i32, 499, + 0x02CB5'i32, 499, + 0x02CB7'i32, 499, + 0x02CB9'i32, 499, + 0x02CBB'i32, 499, + 0x02CBD'i32, 499, + 0x02CBF'i32, 499, + 0x02CC1'i32, 499, + 0x02CC3'i32, 499, + 0x02CC5'i32, 499, + 0x02CC7'i32, 499, + 0x02CC9'i32, 499, + 0x02CCB'i32, 499, + 0x02CCD'i32, 499, + 0x02CCF'i32, 499, + 0x02CD1'i32, 499, + 0x02CD3'i32, 499, + 0x02CD5'i32, 499, + 0x02CD7'i32, 499, + 0x02CD9'i32, 499, + 0x02CDB'i32, 499, + 0x02CDD'i32, 499, + 0x02CDF'i32, 499, + 0x02CE1'i32, 499, + 0x02CE3'i32, 499, + 0x02CEC'i32, 499, + 0x02CEE'i32, 499, + 0x02CF3'i32, 499, + 0x02D27'i32, -6764, + 0x02D2D'i32, -6764, + 0x0A641'i32, 499, + 0x0A643'i32, 499, + 0x0A645'i32, 499, + 0x0A647'i32, 499, + 0x0A649'i32, 499, + 0x0A64B'i32, 499, + 0x0A64D'i32, 499, + 0x0A64F'i32, 499, + 0x0A651'i32, 499, + 0x0A653'i32, 499, + 0x0A655'i32, 499, + 0x0A657'i32, 499, + 0x0A659'i32, 499, + 0x0A65B'i32, 499, + 0x0A65D'i32, 499, + 0x0A65F'i32, 499, + 0x0A661'i32, 499, + 0x0A663'i32, 499, + 0x0A665'i32, 499, + 0x0A667'i32, 499, + 0x0A669'i32, 499, + 0x0A66B'i32, 499, + 0x0A66D'i32, 499, + 0x0A681'i32, 499, + 0x0A683'i32, 499, + 0x0A685'i32, 499, + 0x0A687'i32, 499, + 0x0A689'i32, 499, + 0x0A68B'i32, 499, + 0x0A68D'i32, 499, + 0x0A68F'i32, 499, + 0x0A691'i32, 499, + 0x0A693'i32, 499, + 0x0A695'i32, 499, + 0x0A697'i32, 499, + 0x0A699'i32, 499, + 0x0A69B'i32, 499, + 0x0A723'i32, 499, + 0x0A725'i32, 499, + 0x0A727'i32, 499, + 0x0A729'i32, 499, + 0x0A72B'i32, 499, + 0x0A72D'i32, 499, + 0x0A72F'i32, 499, + 0x0A733'i32, 499, + 0x0A735'i32, 499, + 0x0A737'i32, 499, + 0x0A739'i32, 499, + 0x0A73B'i32, 499, + 0x0A73D'i32, 499, + 0x0A73F'i32, 499, + 0x0A741'i32, 499, + 0x0A743'i32, 499, + 0x0A745'i32, 499, + 0x0A747'i32, 499, + 0x0A749'i32, 499, + 0x0A74B'i32, 499, + 0x0A74D'i32, 499, + 0x0A74F'i32, 499, + 0x0A751'i32, 499, + 0x0A753'i32, 499, + 0x0A755'i32, 499, + 0x0A757'i32, 499, + 0x0A759'i32, 499, + 0x0A75B'i32, 499, + 0x0A75D'i32, 499, + 0x0A75F'i32, 499, + 0x0A761'i32, 499, + 0x0A763'i32, 499, + 0x0A765'i32, 499, + 0x0A767'i32, 499, + 0x0A769'i32, 499, + 0x0A76B'i32, 499, + 0x0A76D'i32, 499, + 0x0A76F'i32, 499, + 0x0A77A'i32, 499, + 0x0A77C'i32, 499, + 0x0A77F'i32, 499, + 0x0A781'i32, 499, + 0x0A783'i32, 499, + 0x0A785'i32, 499, + 0x0A787'i32, 499, + 0x0A78C'i32, 499, + 0x0A791'i32, 499, + 0x0A793'i32, 499, + 0x0A794'i32, 548, + 0x0A797'i32, 499, + 0x0A799'i32, 499, + 0x0A79B'i32, 499, + 0x0A79D'i32, 499, + 0x0A79F'i32, 499, + 0x0A7A1'i32, 499, + 0x0A7A3'i32, 499, + 0x0A7A5'i32, 499, + 0x0A7A7'i32, 499, + 0x0A7A9'i32, 499, + 0x0A7B5'i32, 499, + 0x0A7B7'i32, 499, + 0x0A7B9'i32, 499, + 0x0A7BB'i32, 499, + 0x0A7BD'i32, 499, + 0x0A7BF'i32, 499, + 0x0A7C3'i32, 499, + 0x0AB53'i32, -428, ] toTitleSinglets = [ - 0x001C4, 501, - 0x001C6, 499, - 0x001C7, 501, - 0x001C9, 499, - 0x001CA, 501, - 0x001CC, 499, - 0x001F1, 501, - 0x001F3, 499, + 0x001C4'i32, 501, + 0x001C6'i32, 499, + 0x001C7'i32, 501, + 0x001C9'i32, 499, + 0x001CA'i32, 501, + 0x001CC'i32, 499, + 0x001F1'i32, 501, + 0x001F3'i32, 499, ] alphaRanges = [ - 0x00041, 0x0005A, - 0x00061, 0x0007A, - 0x000C0, 0x000D6, - 0x000D8, 0x000F6, - 0x000F8, 0x002C1, - 0x002C6, 0x002D1, - 0x002E0, 0x002E4, - 0x00370, 0x00374, - 0x00376, 0x00377, - 0x0037A, 0x0037D, - 0x00388, 0x0038A, - 0x0038E, 0x003A1, - 0x003A3, 0x003F5, - 0x003F7, 0x00481, - 0x0048A, 0x0052F, - 0x00531, 0x00556, - 0x00560, 0x00588, - 0x005D0, 0x005EA, - 0x005EF, 0x005F2, - 0x00620, 0x0064A, - 0x0066E, 0x0066F, - 0x00671, 0x006D3, - 0x006E5, 0x006E6, - 0x006EE, 0x006EF, - 0x006FA, 0x006FC, - 0x00712, 0x0072F, - 0x0074D, 0x007A5, - 0x007CA, 0x007EA, - 0x007F4, 0x007F5, - 0x00800, 0x00815, - 0x00840, 0x00858, - 0x00860, 0x0086A, - 0x008A0, 0x008B4, - 0x008B6, 0x008BD, - 0x00904, 0x00939, - 0x00958, 0x00961, - 0x00971, 0x00980, - 0x00985, 0x0098C, - 0x0098F, 0x00990, - 0x00993, 0x009A8, - 0x009AA, 0x009B0, - 0x009B6, 0x009B9, - 0x009DC, 0x009DD, - 0x009DF, 0x009E1, - 0x009F0, 0x009F1, - 0x00A05, 0x00A0A, - 0x00A0F, 0x00A10, - 0x00A13, 0x00A28, - 0x00A2A, 0x00A30, - 0x00A32, 0x00A33, - 0x00A35, 0x00A36, - 0x00A38, 0x00A39, - 0x00A59, 0x00A5C, - 0x00A72, 0x00A74, - 0x00A85, 0x00A8D, - 0x00A8F, 0x00A91, - 0x00A93, 0x00AA8, - 0x00AAA, 0x00AB0, - 0x00AB2, 0x00AB3, - 0x00AB5, 0x00AB9, - 0x00AE0, 0x00AE1, - 0x00B05, 0x00B0C, - 0x00B0F, 0x00B10, - 0x00B13, 0x00B28, - 0x00B2A, 0x00B30, - 0x00B32, 0x00B33, - 0x00B35, 0x00B39, - 0x00B5C, 0x00B5D, - 0x00B5F, 0x00B61, - 0x00B85, 0x00B8A, - 0x00B8E, 0x00B90, - 0x00B92, 0x00B95, - 0x00B99, 0x00B9A, - 0x00B9E, 0x00B9F, - 0x00BA3, 0x00BA4, - 0x00BA8, 0x00BAA, - 0x00BAE, 0x00BB9, - 0x00C05, 0x00C0C, - 0x00C0E, 0x00C10, - 0x00C12, 0x00C28, - 0x00C2A, 0x00C39, - 0x00C58, 0x00C5A, - 0x00C60, 0x00C61, - 0x00C85, 0x00C8C, - 0x00C8E, 0x00C90, - 0x00C92, 0x00CA8, - 0x00CAA, 0x00CB3, - 0x00CB5, 0x00CB9, - 0x00CE0, 0x00CE1, - 0x00CF1, 0x00CF2, - 0x00D05, 0x00D0C, - 0x00D0E, 0x00D10, - 0x00D12, 0x00D3A, - 0x00D54, 0x00D56, - 0x00D5F, 0x00D61, - 0x00D7A, 0x00D7F, - 0x00D85, 0x00D96, - 0x00D9A, 0x00DB1, - 0x00DB3, 0x00DBB, - 0x00DC0, 0x00DC6, - 0x00E01, 0x00E30, - 0x00E32, 0x00E33, - 0x00E40, 0x00E46, - 0x00E81, 0x00E82, - 0x00E86, 0x00E8A, - 0x00E8C, 0x00EA3, - 0x00EA7, 0x00EB0, - 0x00EB2, 0x00EB3, - 0x00EC0, 0x00EC4, - 0x00EDC, 0x00EDF, - 0x00F40, 0x00F47, - 0x00F49, 0x00F6C, - 0x00F88, 0x00F8C, - 0x01000, 0x0102A, - 0x01050, 0x01055, - 0x0105A, 0x0105D, - 0x01065, 0x01066, - 0x0106E, 0x01070, - 0x01075, 0x01081, - 0x010A0, 0x010C5, - 0x010D0, 0x010FA, - 0x010FC, 0x01248, - 0x0124A, 0x0124D, - 0x01250, 0x01256, - 0x0125A, 0x0125D, - 0x01260, 0x01288, - 0x0128A, 0x0128D, - 0x01290, 0x012B0, - 0x012B2, 0x012B5, - 0x012B8, 0x012BE, - 0x012C2, 0x012C5, - 0x012C8, 0x012D6, - 0x012D8, 0x01310, - 0x01312, 0x01315, - 0x01318, 0x0135A, - 0x01380, 0x0138F, - 0x013A0, 0x013F5, - 0x013F8, 0x013FD, - 0x01401, 0x0166C, - 0x0166F, 0x0167F, - 0x01681, 0x0169A, - 0x016A0, 0x016EA, - 0x016F1, 0x016F8, - 0x01700, 0x0170C, - 0x0170E, 0x01711, - 0x01720, 0x01731, - 0x01740, 0x01751, - 0x01760, 0x0176C, - 0x0176E, 0x01770, - 0x01780, 0x017B3, - 0x01820, 0x01878, - 0x01880, 0x01884, - 0x01887, 0x018A8, - 0x018B0, 0x018F5, - 0x01900, 0x0191E, - 0x01950, 0x0196D, - 0x01970, 0x01974, - 0x01980, 0x019AB, - 0x019B0, 0x019C9, - 0x01A00, 0x01A16, - 0x01A20, 0x01A54, - 0x01B05, 0x01B33, - 0x01B45, 0x01B4B, - 0x01B83, 0x01BA0, - 0x01BAE, 0x01BAF, - 0x01BBA, 0x01BE5, - 0x01C00, 0x01C23, - 0x01C4D, 0x01C4F, - 0x01C5A, 0x01C7D, - 0x01C80, 0x01C88, - 0x01C90, 0x01CBA, - 0x01CBD, 0x01CBF, - 0x01CE9, 0x01CEC, - 0x01CEE, 0x01CF3, - 0x01CF5, 0x01CF6, - 0x01D00, 0x01DBF, - 0x01E00, 0x01F15, - 0x01F18, 0x01F1D, - 0x01F20, 0x01F45, - 0x01F48, 0x01F4D, - 0x01F50, 0x01F57, - 0x01F5F, 0x01F7D, - 0x01F80, 0x01FB4, - 0x01FB6, 0x01FBC, - 0x01FC2, 0x01FC4, - 0x01FC6, 0x01FCC, - 0x01FD0, 0x01FD3, - 0x01FD6, 0x01FDB, - 0x01FE0, 0x01FEC, - 0x01FF2, 0x01FF4, - 0x01FF6, 0x01FFC, - 0x02090, 0x0209C, - 0x0210A, 0x02113, - 0x02119, 0x0211D, - 0x0212A, 0x0212D, - 0x0212F, 0x02139, - 0x0213C, 0x0213F, - 0x02145, 0x02149, - 0x02183, 0x02184, - 0x02C00, 0x02C2E, - 0x02C30, 0x02C5E, - 0x02C60, 0x02CE4, - 0x02CEB, 0x02CEE, - 0x02CF2, 0x02CF3, - 0x02D00, 0x02D25, - 0x02D30, 0x02D67, - 0x02D80, 0x02D96, - 0x02DA0, 0x02DA6, - 0x02DA8, 0x02DAE, - 0x02DB0, 0x02DB6, - 0x02DB8, 0x02DBE, - 0x02DC0, 0x02DC6, - 0x02DC8, 0x02DCE, - 0x02DD0, 0x02DD6, - 0x02DD8, 0x02DDE, - 0x03005, 0x03006, - 0x03031, 0x03035, - 0x0303B, 0x0303C, - 0x03041, 0x03096, - 0x0309D, 0x0309F, - 0x030A1, 0x030FA, - 0x030FC, 0x030FF, - 0x03105, 0x0312F, - 0x03131, 0x0318E, - 0x031A0, 0x031BA, - 0x031F0, 0x031FF, - 0x0A000, 0x0A48C, - 0x0A4D0, 0x0A4FD, - 0x0A500, 0x0A60C, - 0x0A610, 0x0A61F, - 0x0A62A, 0x0A62B, - 0x0A640, 0x0A66E, - 0x0A67F, 0x0A69D, - 0x0A6A0, 0x0A6E5, - 0x0A717, 0x0A71F, - 0x0A722, 0x0A788, - 0x0A78B, 0x0A7BF, - 0x0A7C2, 0x0A7C6, - 0x0A7F7, 0x0A801, - 0x0A803, 0x0A805, - 0x0A807, 0x0A80A, - 0x0A80C, 0x0A822, - 0x0A840, 0x0A873, - 0x0A882, 0x0A8B3, - 0x0A8F2, 0x0A8F7, - 0x0A8FD, 0x0A8FE, - 0x0A90A, 0x0A925, - 0x0A930, 0x0A946, - 0x0A960, 0x0A97C, - 0x0A984, 0x0A9B2, - 0x0A9E0, 0x0A9E4, - 0x0A9E6, 0x0A9EF, - 0x0A9FA, 0x0A9FE, - 0x0AA00, 0x0AA28, - 0x0AA40, 0x0AA42, - 0x0AA44, 0x0AA4B, - 0x0AA60, 0x0AA76, - 0x0AA7E, 0x0AAAF, - 0x0AAB5, 0x0AAB6, - 0x0AAB9, 0x0AABD, - 0x0AADB, 0x0AADD, - 0x0AAE0, 0x0AAEA, - 0x0AAF2, 0x0AAF4, - 0x0AB01, 0x0AB06, - 0x0AB09, 0x0AB0E, - 0x0AB11, 0x0AB16, - 0x0AB20, 0x0AB26, - 0x0AB28, 0x0AB2E, - 0x0AB30, 0x0AB5A, - 0x0AB5C, 0x0AB67, - 0x0AB70, 0x0ABE2, - 0x0D7B0, 0x0D7C6, - 0x0D7CB, 0x0D7FB, - 0x0F900, 0x0FA6D, - 0x0FA70, 0x0FAD9, - 0x0FB00, 0x0FB06, - 0x0FB13, 0x0FB17, - 0x0FB1F, 0x0FB28, - 0x0FB2A, 0x0FB36, - 0x0FB38, 0x0FB3C, - 0x0FB40, 0x0FB41, - 0x0FB43, 0x0FB44, - 0x0FB46, 0x0FBB1, - 0x0FBD3, 0x0FD3D, - 0x0FD50, 0x0FD8F, - 0x0FD92, 0x0FDC7, - 0x0FDF0, 0x0FDFB, - 0x0FE70, 0x0FE74, - 0x0FE76, 0x0FEFC, - 0x0FF21, 0x0FF3A, - 0x0FF41, 0x0FF5A, - 0x0FF66, 0x0FFBE, - 0x0FFC2, 0x0FFC7, - 0x0FFCA, 0x0FFCF, - 0x0FFD2, 0x0FFD7, - 0x0FFDA, 0x0FFDC, - 0x10000, 0x1000B, - 0x1000D, 0x10026, - 0x10028, 0x1003A, - 0x1003C, 0x1003D, - 0x1003F, 0x1004D, - 0x10050, 0x1005D, - 0x10080, 0x100FA, - 0x10280, 0x1029C, - 0x102A0, 0x102D0, - 0x10300, 0x1031F, - 0x1032D, 0x10340, - 0x10342, 0x10349, - 0x10350, 0x10375, - 0x10380, 0x1039D, - 0x103A0, 0x103C3, - 0x103C8, 0x103CF, - 0x10400, 0x1049D, - 0x104B0, 0x104D3, - 0x104D8, 0x104FB, - 0x10500, 0x10527, - 0x10530, 0x10563, - 0x10600, 0x10736, - 0x10740, 0x10755, - 0x10760, 0x10767, - 0x10800, 0x10805, - 0x1080A, 0x10835, - 0x10837, 0x10838, - 0x1083F, 0x10855, - 0x10860, 0x10876, - 0x10880, 0x1089E, - 0x108E0, 0x108F2, - 0x108F4, 0x108F5, - 0x10900, 0x10915, - 0x10920, 0x10939, - 0x10980, 0x109B7, - 0x109BE, 0x109BF, - 0x10A10, 0x10A13, - 0x10A15, 0x10A17, - 0x10A19, 0x10A35, - 0x10A60, 0x10A7C, - 0x10A80, 0x10A9C, - 0x10AC0, 0x10AC7, - 0x10AC9, 0x10AE4, - 0x10B00, 0x10B35, - 0x10B40, 0x10B55, - 0x10B60, 0x10B72, - 0x10B80, 0x10B91, - 0x10C00, 0x10C48, - 0x10C80, 0x10CB2, - 0x10CC0, 0x10CF2, - 0x10D00, 0x10D23, - 0x10F00, 0x10F1C, - 0x10F30, 0x10F45, - 0x10FE0, 0x10FF6, - 0x11003, 0x11037, - 0x11083, 0x110AF, - 0x110D0, 0x110E8, - 0x11103, 0x11126, - 0x11150, 0x11172, - 0x11183, 0x111B2, - 0x111C1, 0x111C4, - 0x11200, 0x11211, - 0x11213, 0x1122B, - 0x11280, 0x11286, - 0x1128A, 0x1128D, - 0x1128F, 0x1129D, - 0x1129F, 0x112A8, - 0x112B0, 0x112DE, - 0x11305, 0x1130C, - 0x1130F, 0x11310, - 0x11313, 0x11328, - 0x1132A, 0x11330, - 0x11332, 0x11333, - 0x11335, 0x11339, - 0x1135D, 0x11361, - 0x11400, 0x11434, - 0x11447, 0x1144A, - 0x11480, 0x114AF, - 0x114C4, 0x114C5, - 0x11580, 0x115AE, - 0x115D8, 0x115DB, - 0x11600, 0x1162F, - 0x11680, 0x116AA, - 0x11700, 0x1171A, - 0x11800, 0x1182B, - 0x118A0, 0x118DF, - 0x119A0, 0x119A7, - 0x119AA, 0x119D0, - 0x11A0B, 0x11A32, - 0x11A5C, 0x11A89, - 0x11AC0, 0x11AF8, - 0x11C00, 0x11C08, - 0x11C0A, 0x11C2E, - 0x11C72, 0x11C8F, - 0x11D00, 0x11D06, - 0x11D08, 0x11D09, - 0x11D0B, 0x11D30, - 0x11D60, 0x11D65, - 0x11D67, 0x11D68, - 0x11D6A, 0x11D89, - 0x11EE0, 0x11EF2, - 0x12000, 0x12399, - 0x12480, 0x12543, - 0x13000, 0x1342E, - 0x14400, 0x14646, - 0x16800, 0x16A38, - 0x16A40, 0x16A5E, - 0x16AD0, 0x16AED, - 0x16B00, 0x16B2F, - 0x16B40, 0x16B43, - 0x16B63, 0x16B77, - 0x16B7D, 0x16B8F, - 0x16E40, 0x16E7F, - 0x16F00, 0x16F4A, - 0x16F93, 0x16F9F, - 0x16FE0, 0x16FE1, - 0x18800, 0x18AF2, - 0x1B000, 0x1B11E, - 0x1B150, 0x1B152, - 0x1B164, 0x1B167, - 0x1B170, 0x1B2FB, - 0x1BC00, 0x1BC6A, - 0x1BC70, 0x1BC7C, - 0x1BC80, 0x1BC88, - 0x1BC90, 0x1BC99, - 0x1D400, 0x1D454, - 0x1D456, 0x1D49C, - 0x1D49E, 0x1D49F, - 0x1D4A5, 0x1D4A6, - 0x1D4A9, 0x1D4AC, - 0x1D4AE, 0x1D4B9, - 0x1D4BD, 0x1D4C3, - 0x1D4C5, 0x1D505, - 0x1D507, 0x1D50A, - 0x1D50D, 0x1D514, - 0x1D516, 0x1D51C, - 0x1D51E, 0x1D539, - 0x1D53B, 0x1D53E, - 0x1D540, 0x1D544, - 0x1D54A, 0x1D550, - 0x1D552, 0x1D6A5, - 0x1D6A8, 0x1D6C0, - 0x1D6C2, 0x1D6DA, - 0x1D6DC, 0x1D6FA, - 0x1D6FC, 0x1D714, - 0x1D716, 0x1D734, - 0x1D736, 0x1D74E, - 0x1D750, 0x1D76E, - 0x1D770, 0x1D788, - 0x1D78A, 0x1D7A8, - 0x1D7AA, 0x1D7C2, - 0x1D7C4, 0x1D7CB, - 0x1E100, 0x1E12C, - 0x1E137, 0x1E13D, - 0x1E2C0, 0x1E2EB, - 0x1E800, 0x1E8C4, - 0x1E900, 0x1E943, - 0x1EE00, 0x1EE03, - 0x1EE05, 0x1EE1F, - 0x1EE21, 0x1EE22, - 0x1EE29, 0x1EE32, - 0x1EE34, 0x1EE37, - 0x1EE4D, 0x1EE4F, - 0x1EE51, 0x1EE52, - 0x1EE61, 0x1EE62, - 0x1EE67, 0x1EE6A, - 0x1EE6C, 0x1EE72, - 0x1EE74, 0x1EE77, - 0x1EE79, 0x1EE7C, - 0x1EE80, 0x1EE89, - 0x1EE8B, 0x1EE9B, - 0x1EEA1, 0x1EEA3, - 0x1EEA5, 0x1EEA9, - 0x1EEAB, 0x1EEBB, - 0x2F800, 0x2FA1D, + 0x00041'i32, 0x0005A'i32, + 0x00061'i32, 0x0007A'i32, + 0x000C0'i32, 0x000D6'i32, + 0x000D8'i32, 0x000F6'i32, + 0x000F8'i32, 0x002C1'i32, + 0x002C6'i32, 0x002D1'i32, + 0x002E0'i32, 0x002E4'i32, + 0x00370'i32, 0x00374'i32, + 0x00376'i32, 0x00377'i32, + 0x0037A'i32, 0x0037D'i32, + 0x00388'i32, 0x0038A'i32, + 0x0038E'i32, 0x003A1'i32, + 0x003A3'i32, 0x003F5'i32, + 0x003F7'i32, 0x00481'i32, + 0x0048A'i32, 0x0052F'i32, + 0x00531'i32, 0x00556'i32, + 0x00560'i32, 0x00588'i32, + 0x005D0'i32, 0x005EA'i32, + 0x005EF'i32, 0x005F2'i32, + 0x00620'i32, 0x0064A'i32, + 0x0066E'i32, 0x0066F'i32, + 0x00671'i32, 0x006D3'i32, + 0x006E5'i32, 0x006E6'i32, + 0x006EE'i32, 0x006EF'i32, + 0x006FA'i32, 0x006FC'i32, + 0x00712'i32, 0x0072F'i32, + 0x0074D'i32, 0x007A5'i32, + 0x007CA'i32, 0x007EA'i32, + 0x007F4'i32, 0x007F5'i32, + 0x00800'i32, 0x00815'i32, + 0x00840'i32, 0x00858'i32, + 0x00860'i32, 0x0086A'i32, + 0x008A0'i32, 0x008B4'i32, + 0x008B6'i32, 0x008BD'i32, + 0x00904'i32, 0x00939'i32, + 0x00958'i32, 0x00961'i32, + 0x00971'i32, 0x00980'i32, + 0x00985'i32, 0x0098C'i32, + 0x0098F'i32, 0x00990'i32, + 0x00993'i32, 0x009A8'i32, + 0x009AA'i32, 0x009B0'i32, + 0x009B6'i32, 0x009B9'i32, + 0x009DC'i32, 0x009DD'i32, + 0x009DF'i32, 0x009E1'i32, + 0x009F0'i32, 0x009F1'i32, + 0x00A05'i32, 0x00A0A'i32, + 0x00A0F'i32, 0x00A10'i32, + 0x00A13'i32, 0x00A28'i32, + 0x00A2A'i32, 0x00A30'i32, + 0x00A32'i32, 0x00A33'i32, + 0x00A35'i32, 0x00A36'i32, + 0x00A38'i32, 0x00A39'i32, + 0x00A59'i32, 0x00A5C'i32, + 0x00A72'i32, 0x00A74'i32, + 0x00A85'i32, 0x00A8D'i32, + 0x00A8F'i32, 0x00A91'i32, + 0x00A93'i32, 0x00AA8'i32, + 0x00AAA'i32, 0x00AB0'i32, + 0x00AB2'i32, 0x00AB3'i32, + 0x00AB5'i32, 0x00AB9'i32, + 0x00AE0'i32, 0x00AE1'i32, + 0x00B05'i32, 0x00B0C'i32, + 0x00B0F'i32, 0x00B10'i32, + 0x00B13'i32, 0x00B28'i32, + 0x00B2A'i32, 0x00B30'i32, + 0x00B32'i32, 0x00B33'i32, + 0x00B35'i32, 0x00B39'i32, + 0x00B5C'i32, 0x00B5D'i32, + 0x00B5F'i32, 0x00B61'i32, + 0x00B85'i32, 0x00B8A'i32, + 0x00B8E'i32, 0x00B90'i32, + 0x00B92'i32, 0x00B95'i32, + 0x00B99'i32, 0x00B9A'i32, + 0x00B9E'i32, 0x00B9F'i32, + 0x00BA3'i32, 0x00BA4'i32, + 0x00BA8'i32, 0x00BAA'i32, + 0x00BAE'i32, 0x00BB9'i32, + 0x00C05'i32, 0x00C0C'i32, + 0x00C0E'i32, 0x00C10'i32, + 0x00C12'i32, 0x00C28'i32, + 0x00C2A'i32, 0x00C39'i32, + 0x00C58'i32, 0x00C5A'i32, + 0x00C60'i32, 0x00C61'i32, + 0x00C85'i32, 0x00C8C'i32, + 0x00C8E'i32, 0x00C90'i32, + 0x00C92'i32, 0x00CA8'i32, + 0x00CAA'i32, 0x00CB3'i32, + 0x00CB5'i32, 0x00CB9'i32, + 0x00CE0'i32, 0x00CE1'i32, + 0x00CF1'i32, 0x00CF2'i32, + 0x00D05'i32, 0x00D0C'i32, + 0x00D0E'i32, 0x00D10'i32, + 0x00D12'i32, 0x00D3A'i32, + 0x00D54'i32, 0x00D56'i32, + 0x00D5F'i32, 0x00D61'i32, + 0x00D7A'i32, 0x00D7F'i32, + 0x00D85'i32, 0x00D96'i32, + 0x00D9A'i32, 0x00DB1'i32, + 0x00DB3'i32, 0x00DBB'i32, + 0x00DC0'i32, 0x00DC6'i32, + 0x00E01'i32, 0x00E30'i32, + 0x00E32'i32, 0x00E33'i32, + 0x00E40'i32, 0x00E46'i32, + 0x00E81'i32, 0x00E82'i32, + 0x00E86'i32, 0x00E8A'i32, + 0x00E8C'i32, 0x00EA3'i32, + 0x00EA7'i32, 0x00EB0'i32, + 0x00EB2'i32, 0x00EB3'i32, + 0x00EC0'i32, 0x00EC4'i32, + 0x00EDC'i32, 0x00EDF'i32, + 0x00F40'i32, 0x00F47'i32, + 0x00F49'i32, 0x00F6C'i32, + 0x00F88'i32, 0x00F8C'i32, + 0x01000'i32, 0x0102A'i32, + 0x01050'i32, 0x01055'i32, + 0x0105A'i32, 0x0105D'i32, + 0x01065'i32, 0x01066'i32, + 0x0106E'i32, 0x01070'i32, + 0x01075'i32, 0x01081'i32, + 0x010A0'i32, 0x010C5'i32, + 0x010D0'i32, 0x010FA'i32, + 0x010FC'i32, 0x01248'i32, + 0x0124A'i32, 0x0124D'i32, + 0x01250'i32, 0x01256'i32, + 0x0125A'i32, 0x0125D'i32, + 0x01260'i32, 0x01288'i32, + 0x0128A'i32, 0x0128D'i32, + 0x01290'i32, 0x012B0'i32, + 0x012B2'i32, 0x012B5'i32, + 0x012B8'i32, 0x012BE'i32, + 0x012C2'i32, 0x012C5'i32, + 0x012C8'i32, 0x012D6'i32, + 0x012D8'i32, 0x01310'i32, + 0x01312'i32, 0x01315'i32, + 0x01318'i32, 0x0135A'i32, + 0x01380'i32, 0x0138F'i32, + 0x013A0'i32, 0x013F5'i32, + 0x013F8'i32, 0x013FD'i32, + 0x01401'i32, 0x0166C'i32, + 0x0166F'i32, 0x0167F'i32, + 0x01681'i32, 0x0169A'i32, + 0x016A0'i32, 0x016EA'i32, + 0x016F1'i32, 0x016F8'i32, + 0x01700'i32, 0x0170C'i32, + 0x0170E'i32, 0x01711'i32, + 0x01720'i32, 0x01731'i32, + 0x01740'i32, 0x01751'i32, + 0x01760'i32, 0x0176C'i32, + 0x0176E'i32, 0x01770'i32, + 0x01780'i32, 0x017B3'i32, + 0x01820'i32, 0x01878'i32, + 0x01880'i32, 0x01884'i32, + 0x01887'i32, 0x018A8'i32, + 0x018B0'i32, 0x018F5'i32, + 0x01900'i32, 0x0191E'i32, + 0x01950'i32, 0x0196D'i32, + 0x01970'i32, 0x01974'i32, + 0x01980'i32, 0x019AB'i32, + 0x019B0'i32, 0x019C9'i32, + 0x01A00'i32, 0x01A16'i32, + 0x01A20'i32, 0x01A54'i32, + 0x01B05'i32, 0x01B33'i32, + 0x01B45'i32, 0x01B4B'i32, + 0x01B83'i32, 0x01BA0'i32, + 0x01BAE'i32, 0x01BAF'i32, + 0x01BBA'i32, 0x01BE5'i32, + 0x01C00'i32, 0x01C23'i32, + 0x01C4D'i32, 0x01C4F'i32, + 0x01C5A'i32, 0x01C7D'i32, + 0x01C80'i32, 0x01C88'i32, + 0x01C90'i32, 0x01CBA'i32, + 0x01CBD'i32, 0x01CBF'i32, + 0x01CE9'i32, 0x01CEC'i32, + 0x01CEE'i32, 0x01CF3'i32, + 0x01CF5'i32, 0x01CF6'i32, + 0x01D00'i32, 0x01DBF'i32, + 0x01E00'i32, 0x01F15'i32, + 0x01F18'i32, 0x01F1D'i32, + 0x01F20'i32, 0x01F45'i32, + 0x01F48'i32, 0x01F4D'i32, + 0x01F50'i32, 0x01F57'i32, + 0x01F5F'i32, 0x01F7D'i32, + 0x01F80'i32, 0x01FB4'i32, + 0x01FB6'i32, 0x01FBC'i32, + 0x01FC2'i32, 0x01FC4'i32, + 0x01FC6'i32, 0x01FCC'i32, + 0x01FD0'i32, 0x01FD3'i32, + 0x01FD6'i32, 0x01FDB'i32, + 0x01FE0'i32, 0x01FEC'i32, + 0x01FF2'i32, 0x01FF4'i32, + 0x01FF6'i32, 0x01FFC'i32, + 0x02090'i32, 0x0209C'i32, + 0x0210A'i32, 0x02113'i32, + 0x02119'i32, 0x0211D'i32, + 0x0212A'i32, 0x0212D'i32, + 0x0212F'i32, 0x02139'i32, + 0x0213C'i32, 0x0213F'i32, + 0x02145'i32, 0x02149'i32, + 0x02183'i32, 0x02184'i32, + 0x02C00'i32, 0x02C2E'i32, + 0x02C30'i32, 0x02C5E'i32, + 0x02C60'i32, 0x02CE4'i32, + 0x02CEB'i32, 0x02CEE'i32, + 0x02CF2'i32, 0x02CF3'i32, + 0x02D00'i32, 0x02D25'i32, + 0x02D30'i32, 0x02D67'i32, + 0x02D80'i32, 0x02D96'i32, + 0x02DA0'i32, 0x02DA6'i32, + 0x02DA8'i32, 0x02DAE'i32, + 0x02DB0'i32, 0x02DB6'i32, + 0x02DB8'i32, 0x02DBE'i32, + 0x02DC0'i32, 0x02DC6'i32, + 0x02DC8'i32, 0x02DCE'i32, + 0x02DD0'i32, 0x02DD6'i32, + 0x02DD8'i32, 0x02DDE'i32, + 0x03005'i32, 0x03006'i32, + 0x03031'i32, 0x03035'i32, + 0x0303B'i32, 0x0303C'i32, + 0x03041'i32, 0x03096'i32, + 0x0309D'i32, 0x0309F'i32, + 0x030A1'i32, 0x030FA'i32, + 0x030FC'i32, 0x030FF'i32, + 0x03105'i32, 0x0312F'i32, + 0x03131'i32, 0x0318E'i32, + 0x031A0'i32, 0x031BA'i32, + 0x031F0'i32, 0x031FF'i32, + 0x03400'i32, 0x04DB5'i32, + 0x04E00'i32, 0x09FEF'i32, + 0x0A000'i32, 0x0A48C'i32, + 0x0A4D0'i32, 0x0A4FD'i32, + 0x0A500'i32, 0x0A60C'i32, + 0x0A610'i32, 0x0A61F'i32, + 0x0A62A'i32, 0x0A62B'i32, + 0x0A640'i32, 0x0A66E'i32, + 0x0A67F'i32, 0x0A69D'i32, + 0x0A6A0'i32, 0x0A6E5'i32, + 0x0A717'i32, 0x0A71F'i32, + 0x0A722'i32, 0x0A788'i32, + 0x0A78B'i32, 0x0A7BF'i32, + 0x0A7C2'i32, 0x0A7C6'i32, + 0x0A7F7'i32, 0x0A801'i32, + 0x0A803'i32, 0x0A805'i32, + 0x0A807'i32, 0x0A80A'i32, + 0x0A80C'i32, 0x0A822'i32, + 0x0A840'i32, 0x0A873'i32, + 0x0A882'i32, 0x0A8B3'i32, + 0x0A8F2'i32, 0x0A8F7'i32, + 0x0A8FD'i32, 0x0A8FE'i32, + 0x0A90A'i32, 0x0A925'i32, + 0x0A930'i32, 0x0A946'i32, + 0x0A960'i32, 0x0A97C'i32, + 0x0A984'i32, 0x0A9B2'i32, + 0x0A9E0'i32, 0x0A9E4'i32, + 0x0A9E6'i32, 0x0A9EF'i32, + 0x0A9FA'i32, 0x0A9FE'i32, + 0x0AA00'i32, 0x0AA28'i32, + 0x0AA40'i32, 0x0AA42'i32, + 0x0AA44'i32, 0x0AA4B'i32, + 0x0AA60'i32, 0x0AA76'i32, + 0x0AA7E'i32, 0x0AAAF'i32, + 0x0AAB5'i32, 0x0AAB6'i32, + 0x0AAB9'i32, 0x0AABD'i32, + 0x0AADB'i32, 0x0AADD'i32, + 0x0AAE0'i32, 0x0AAEA'i32, + 0x0AAF2'i32, 0x0AAF4'i32, + 0x0AB01'i32, 0x0AB06'i32, + 0x0AB09'i32, 0x0AB0E'i32, + 0x0AB11'i32, 0x0AB16'i32, + 0x0AB20'i32, 0x0AB26'i32, + 0x0AB28'i32, 0x0AB2E'i32, + 0x0AB30'i32, 0x0AB5A'i32, + 0x0AB5C'i32, 0x0AB67'i32, + 0x0AB70'i32, 0x0ABE2'i32, + 0x0AC00'i32, 0x0D7A3'i32, + 0x0D7B0'i32, 0x0D7C6'i32, + 0x0D7CB'i32, 0x0D7FB'i32, + 0x0F900'i32, 0x0FA6D'i32, + 0x0FA70'i32, 0x0FAD9'i32, + 0x0FB00'i32, 0x0FB06'i32, + 0x0FB13'i32, 0x0FB17'i32, + 0x0FB1F'i32, 0x0FB28'i32, + 0x0FB2A'i32, 0x0FB36'i32, + 0x0FB38'i32, 0x0FB3C'i32, + 0x0FB40'i32, 0x0FB41'i32, + 0x0FB43'i32, 0x0FB44'i32, + 0x0FB46'i32, 0x0FBB1'i32, + 0x0FBD3'i32, 0x0FD3D'i32, + 0x0FD50'i32, 0x0FD8F'i32, + 0x0FD92'i32, 0x0FDC7'i32, + 0x0FDF0'i32, 0x0FDFB'i32, + 0x0FE70'i32, 0x0FE74'i32, + 0x0FE76'i32, 0x0FEFC'i32, + 0x0FF21'i32, 0x0FF3A'i32, + 0x0FF41'i32, 0x0FF5A'i32, + 0x0FF66'i32, 0x0FFBE'i32, + 0x0FFC2'i32, 0x0FFC7'i32, + 0x0FFCA'i32, 0x0FFCF'i32, + 0x0FFD2'i32, 0x0FFD7'i32, + 0x0FFDA'i32, 0x0FFDC'i32, + 0x10000'i32, 0x1000B'i32, + 0x1000D'i32, 0x10026'i32, + 0x10028'i32, 0x1003A'i32, + 0x1003C'i32, 0x1003D'i32, + 0x1003F'i32, 0x1004D'i32, + 0x10050'i32, 0x1005D'i32, + 0x10080'i32, 0x100FA'i32, + 0x10280'i32, 0x1029C'i32, + 0x102A0'i32, 0x102D0'i32, + 0x10300'i32, 0x1031F'i32, + 0x1032D'i32, 0x10340'i32, + 0x10342'i32, 0x10349'i32, + 0x10350'i32, 0x10375'i32, + 0x10380'i32, 0x1039D'i32, + 0x103A0'i32, 0x103C3'i32, + 0x103C8'i32, 0x103CF'i32, + 0x10400'i32, 0x1049D'i32, + 0x104B0'i32, 0x104D3'i32, + 0x104D8'i32, 0x104FB'i32, + 0x10500'i32, 0x10527'i32, + 0x10530'i32, 0x10563'i32, + 0x10600'i32, 0x10736'i32, + 0x10740'i32, 0x10755'i32, + 0x10760'i32, 0x10767'i32, + 0x10800'i32, 0x10805'i32, + 0x1080A'i32, 0x10835'i32, + 0x10837'i32, 0x10838'i32, + 0x1083F'i32, 0x10855'i32, + 0x10860'i32, 0x10876'i32, + 0x10880'i32, 0x1089E'i32, + 0x108E0'i32, 0x108F2'i32, + 0x108F4'i32, 0x108F5'i32, + 0x10900'i32, 0x10915'i32, + 0x10920'i32, 0x10939'i32, + 0x10980'i32, 0x109B7'i32, + 0x109BE'i32, 0x109BF'i32, + 0x10A10'i32, 0x10A13'i32, + 0x10A15'i32, 0x10A17'i32, + 0x10A19'i32, 0x10A35'i32, + 0x10A60'i32, 0x10A7C'i32, + 0x10A80'i32, 0x10A9C'i32, + 0x10AC0'i32, 0x10AC7'i32, + 0x10AC9'i32, 0x10AE4'i32, + 0x10B00'i32, 0x10B35'i32, + 0x10B40'i32, 0x10B55'i32, + 0x10B60'i32, 0x10B72'i32, + 0x10B80'i32, 0x10B91'i32, + 0x10C00'i32, 0x10C48'i32, + 0x10C80'i32, 0x10CB2'i32, + 0x10CC0'i32, 0x10CF2'i32, + 0x10D00'i32, 0x10D23'i32, + 0x10F00'i32, 0x10F1C'i32, + 0x10F30'i32, 0x10F45'i32, + 0x10FE0'i32, 0x10FF6'i32, + 0x11003'i32, 0x11037'i32, + 0x11083'i32, 0x110AF'i32, + 0x110D0'i32, 0x110E8'i32, + 0x11103'i32, 0x11126'i32, + 0x11150'i32, 0x11172'i32, + 0x11183'i32, 0x111B2'i32, + 0x111C1'i32, 0x111C4'i32, + 0x11200'i32, 0x11211'i32, + 0x11213'i32, 0x1122B'i32, + 0x11280'i32, 0x11286'i32, + 0x1128A'i32, 0x1128D'i32, + 0x1128F'i32, 0x1129D'i32, + 0x1129F'i32, 0x112A8'i32, + 0x112B0'i32, 0x112DE'i32, + 0x11305'i32, 0x1130C'i32, + 0x1130F'i32, 0x11310'i32, + 0x11313'i32, 0x11328'i32, + 0x1132A'i32, 0x11330'i32, + 0x11332'i32, 0x11333'i32, + 0x11335'i32, 0x11339'i32, + 0x1135D'i32, 0x11361'i32, + 0x11400'i32, 0x11434'i32, + 0x11447'i32, 0x1144A'i32, + 0x11480'i32, 0x114AF'i32, + 0x114C4'i32, 0x114C5'i32, + 0x11580'i32, 0x115AE'i32, + 0x115D8'i32, 0x115DB'i32, + 0x11600'i32, 0x1162F'i32, + 0x11680'i32, 0x116AA'i32, + 0x11700'i32, 0x1171A'i32, + 0x11800'i32, 0x1182B'i32, + 0x118A0'i32, 0x118DF'i32, + 0x119A0'i32, 0x119A7'i32, + 0x119AA'i32, 0x119D0'i32, + 0x11A0B'i32, 0x11A32'i32, + 0x11A5C'i32, 0x11A89'i32, + 0x11AC0'i32, 0x11AF8'i32, + 0x11C00'i32, 0x11C08'i32, + 0x11C0A'i32, 0x11C2E'i32, + 0x11C72'i32, 0x11C8F'i32, + 0x11D00'i32, 0x11D06'i32, + 0x11D08'i32, 0x11D09'i32, + 0x11D0B'i32, 0x11D30'i32, + 0x11D60'i32, 0x11D65'i32, + 0x11D67'i32, 0x11D68'i32, + 0x11D6A'i32, 0x11D89'i32, + 0x11EE0'i32, 0x11EF2'i32, + 0x12000'i32, 0x12399'i32, + 0x12480'i32, 0x12543'i32, + 0x13000'i32, 0x1342E'i32, + 0x14400'i32, 0x14646'i32, + 0x16800'i32, 0x16A38'i32, + 0x16A40'i32, 0x16A5E'i32, + 0x16AD0'i32, 0x16AED'i32, + 0x16B00'i32, 0x16B2F'i32, + 0x16B40'i32, 0x16B43'i32, + 0x16B63'i32, 0x16B77'i32, + 0x16B7D'i32, 0x16B8F'i32, + 0x16E40'i32, 0x16E7F'i32, + 0x16F00'i32, 0x16F4A'i32, + 0x16F93'i32, 0x16F9F'i32, + 0x16FE0'i32, 0x16FE1'i32, + 0x17000'i32, 0x187F7'i32, + 0x18800'i32, 0x18AF2'i32, + 0x1B000'i32, 0x1B11E'i32, + 0x1B150'i32, 0x1B152'i32, + 0x1B164'i32, 0x1B167'i32, + 0x1B170'i32, 0x1B2FB'i32, + 0x1BC00'i32, 0x1BC6A'i32, + 0x1BC70'i32, 0x1BC7C'i32, + 0x1BC80'i32, 0x1BC88'i32, + 0x1BC90'i32, 0x1BC99'i32, + 0x1D400'i32, 0x1D454'i32, + 0x1D456'i32, 0x1D49C'i32, + 0x1D49E'i32, 0x1D49F'i32, + 0x1D4A5'i32, 0x1D4A6'i32, + 0x1D4A9'i32, 0x1D4AC'i32, + 0x1D4AE'i32, 0x1D4B9'i32, + 0x1D4BD'i32, 0x1D4C3'i32, + 0x1D4C5'i32, 0x1D505'i32, + 0x1D507'i32, 0x1D50A'i32, + 0x1D50D'i32, 0x1D514'i32, + 0x1D516'i32, 0x1D51C'i32, + 0x1D51E'i32, 0x1D539'i32, + 0x1D53B'i32, 0x1D53E'i32, + 0x1D540'i32, 0x1D544'i32, + 0x1D54A'i32, 0x1D550'i32, + 0x1D552'i32, 0x1D6A5'i32, + 0x1D6A8'i32, 0x1D6C0'i32, + 0x1D6C2'i32, 0x1D6DA'i32, + 0x1D6DC'i32, 0x1D6FA'i32, + 0x1D6FC'i32, 0x1D714'i32, + 0x1D716'i32, 0x1D734'i32, + 0x1D736'i32, 0x1D74E'i32, + 0x1D750'i32, 0x1D76E'i32, + 0x1D770'i32, 0x1D788'i32, + 0x1D78A'i32, 0x1D7A8'i32, + 0x1D7AA'i32, 0x1D7C2'i32, + 0x1D7C4'i32, 0x1D7CB'i32, + 0x1E100'i32, 0x1E12C'i32, + 0x1E137'i32, 0x1E13D'i32, + 0x1E2C0'i32, 0x1E2EB'i32, + 0x1E800'i32, 0x1E8C4'i32, + 0x1E900'i32, 0x1E943'i32, + 0x1EE00'i32, 0x1EE03'i32, + 0x1EE05'i32, 0x1EE1F'i32, + 0x1EE21'i32, 0x1EE22'i32, + 0x1EE29'i32, 0x1EE32'i32, + 0x1EE34'i32, 0x1EE37'i32, + 0x1EE4D'i32, 0x1EE4F'i32, + 0x1EE51'i32, 0x1EE52'i32, + 0x1EE61'i32, 0x1EE62'i32, + 0x1EE67'i32, 0x1EE6A'i32, + 0x1EE6C'i32, 0x1EE72'i32, + 0x1EE74'i32, 0x1EE77'i32, + 0x1EE79'i32, 0x1EE7C'i32, + 0x1EE80'i32, 0x1EE89'i32, + 0x1EE8B'i32, 0x1EE9B'i32, + 0x1EEA1'i32, 0x1EEA3'i32, + 0x1EEA5'i32, 0x1EEA9'i32, + 0x1EEAB'i32, 0x1EEBB'i32, + 0x20000'i32, 0x2A6D6'i32, + 0x2A700'i32, 0x2B734'i32, + 0x2B740'i32, 0x2B81D'i32, + 0x2B820'i32, 0x2CEA1'i32, + 0x2CEB0'i32, 0x2EBE0'i32, + 0x2F800'i32, 0x2FA1D'i32, ] alphaSinglets = [ - 0x000AA, - 0x000B5, - 0x000BA, - 0x002EC, - 0x002EE, - 0x0037F, - 0x00386, - 0x0038C, - 0x00559, - 0x006D5, - 0x006FF, - 0x00710, - 0x007B1, - 0x007FA, - 0x0081A, - 0x00824, - 0x00828, - 0x0093D, - 0x00950, - 0x009B2, - 0x009BD, - 0x009CE, - 0x009FC, - 0x00A5E, - 0x00ABD, - 0x00AD0, - 0x00AF9, - 0x00B3D, - 0x00B71, - 0x00B83, - 0x00B9C, - 0x00BD0, - 0x00C3D, - 0x00C80, - 0x00CBD, - 0x00CDE, - 0x00D3D, - 0x00D4E, - 0x00DBD, - 0x00E84, - 0x00EA5, - 0x00EBD, - 0x00EC6, - 0x00F00, - 0x0103F, - 0x01061, - 0x0108E, - 0x010C7, - 0x010CD, - 0x01258, - 0x012C0, - 0x017D7, - 0x017DC, - 0x018AA, - 0x01AA7, - 0x01CFA, - 0x01F59, - 0x01F5B, - 0x01F5D, - 0x01FBE, - 0x02071, - 0x0207F, - 0x02102, - 0x02107, - 0x02115, - 0x02124, - 0x02126, - 0x02128, - 0x0214E, - 0x02D27, - 0x02D2D, - 0x02D6F, - 0x02E2F, - 0x03400, - 0x04DB5, - 0x04E00, - 0x09FEF, - 0x0A8FB, - 0x0A9CF, - 0x0AA7A, - 0x0AAB1, - 0x0AAC0, - 0x0AAC2, - 0x0AC00, - 0x0D7A3, - 0x0FB1D, - 0x0FB3E, - 0x10808, - 0x1083C, - 0x10A00, - 0x10F27, - 0x11144, - 0x11176, - 0x111DA, - 0x111DC, - 0x11288, - 0x1133D, - 0x11350, - 0x1145F, - 0x114C7, - 0x11644, - 0x116B8, - 0x118FF, - 0x119E1, - 0x119E3, - 0x11A00, - 0x11A3A, - 0x11A50, - 0x11A9D, - 0x11C40, - 0x11D46, - 0x11D98, - 0x16F50, - 0x16FE3, - 0x17000, - 0x187F7, - 0x1D4A2, - 0x1D4BB, - 0x1D546, - 0x1E14E, - 0x1E94B, - 0x1EE24, - 0x1EE27, - 0x1EE39, - 0x1EE3B, - 0x1EE42, - 0x1EE47, - 0x1EE49, - 0x1EE4B, - 0x1EE54, - 0x1EE57, - 0x1EE59, - 0x1EE5B, - 0x1EE5D, - 0x1EE5F, - 0x1EE64, - 0x1EE7E, - 0x20000, - 0x2A6D6, - 0x2A700, - 0x2B734, - 0x2B740, - 0x2B81D, - 0x2B820, - 0x2CEA1, - 0x2CEB0, - 0x2EBE0, + 0x000AA'i32, + 0x000B5'i32, + 0x000BA'i32, + 0x002EC'i32, + 0x002EE'i32, + 0x0037F'i32, + 0x00386'i32, + 0x0038C'i32, + 0x00559'i32, + 0x006D5'i32, + 0x006FF'i32, + 0x00710'i32, + 0x007B1'i32, + 0x007FA'i32, + 0x0081A'i32, + 0x00824'i32, + 0x00828'i32, + 0x0093D'i32, + 0x00950'i32, + 0x009B2'i32, + 0x009BD'i32, + 0x009CE'i32, + 0x009FC'i32, + 0x00A5E'i32, + 0x00ABD'i32, + 0x00AD0'i32, + 0x00AF9'i32, + 0x00B3D'i32, + 0x00B71'i32, + 0x00B83'i32, + 0x00B9C'i32, + 0x00BD0'i32, + 0x00C3D'i32, + 0x00C80'i32, + 0x00CBD'i32, + 0x00CDE'i32, + 0x00D3D'i32, + 0x00D4E'i32, + 0x00DBD'i32, + 0x00E84'i32, + 0x00EA5'i32, + 0x00EBD'i32, + 0x00EC6'i32, + 0x00F00'i32, + 0x0103F'i32, + 0x01061'i32, + 0x0108E'i32, + 0x010C7'i32, + 0x010CD'i32, + 0x01258'i32, + 0x012C0'i32, + 0x017D7'i32, + 0x017DC'i32, + 0x018AA'i32, + 0x01AA7'i32, + 0x01CFA'i32, + 0x01F59'i32, + 0x01F5B'i32, + 0x01F5D'i32, + 0x01FBE'i32, + 0x02071'i32, + 0x0207F'i32, + 0x02102'i32, + 0x02107'i32, + 0x02115'i32, + 0x02124'i32, + 0x02126'i32, + 0x02128'i32, + 0x0214E'i32, + 0x02D27'i32, + 0x02D2D'i32, + 0x02D6F'i32, + 0x02E2F'i32, + 0x0A8FB'i32, + 0x0A9CF'i32, + 0x0AA7A'i32, + 0x0AAB1'i32, + 0x0AAC0'i32, + 0x0AAC2'i32, + 0x0FB1D'i32, + 0x0FB3E'i32, + 0x10808'i32, + 0x1083C'i32, + 0x10A00'i32, + 0x10F27'i32, + 0x11144'i32, + 0x11176'i32, + 0x111DA'i32, + 0x111DC'i32, + 0x11288'i32, + 0x1133D'i32, + 0x11350'i32, + 0x1145F'i32, + 0x114C7'i32, + 0x11644'i32, + 0x116B8'i32, + 0x118FF'i32, + 0x119E1'i32, + 0x119E3'i32, + 0x11A00'i32, + 0x11A3A'i32, + 0x11A50'i32, + 0x11A9D'i32, + 0x11C40'i32, + 0x11D46'i32, + 0x11D98'i32, + 0x16F50'i32, + 0x16FE3'i32, + 0x1D4A2'i32, + 0x1D4BB'i32, + 0x1D546'i32, + 0x1E14E'i32, + 0x1E94B'i32, + 0x1EE24'i32, + 0x1EE27'i32, + 0x1EE39'i32, + 0x1EE3B'i32, + 0x1EE42'i32, + 0x1EE47'i32, + 0x1EE49'i32, + 0x1EE4B'i32, + 0x1EE54'i32, + 0x1EE57'i32, + 0x1EE59'i32, + 0x1EE5B'i32, + 0x1EE5D'i32, + 0x1EE5F'i32, + 0x1EE64'i32, + 0x1EE7E'i32, ] spaceRanges = [ - 0x00009, 0x0000D, - 0x00020, 0x00020, - 0x00085, 0x00085, - 0x000A0, 0x000A0, - 0x01680, 0x01680, - 0x02000, 0x0200A, - 0x02028, 0x02029, - 0x0202F, 0x0202F, - 0x0205F, 0x0205F, - 0x03000, 0x03000, + 0x00009'i32, 0x0000D'i32, + 0x00020'i32, 0x00020'i32, + 0x00085'i32, 0x00085'i32, + 0x000A0'i32, 0x000A0'i32, + 0x01680'i32, 0x01680'i32, + 0x02000'i32, 0x0200A'i32, + 0x02028'i32, 0x02029'i32, + 0x0202F'i32, 0x0202F'i32, + 0x0205F'i32, 0x0205F'i32, + 0x03000'i32, 0x03000'i32, ] unicodeSpaces = [ diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim index 510de8c51..10658b78e 100644 --- a/lib/pure/ioselects/ioselectors_epoll.nim +++ b/lib/pure/ioselects/ioselectors_epoll.nim @@ -9,7 +9,7 @@ # This module implements Linux epoll(). -import posix, times, epoll +import std/[posix, times, epoll] # Maximum number of events that can be returned const MAX_EPOLL_EVENTS = 64 diff --git a/lib/pure/ioselects/ioselectors_kqueue.nim b/lib/pure/ioselects/ioselectors_kqueue.nim index 68be969c7..513578eda 100644 --- a/lib/pure/ioselects/ioselectors_kqueue.nim +++ b/lib/pure/ioselects/ioselectors_kqueue.nim @@ -9,7 +9,7 @@ # This module implements BSD kqueue(). -import posix, times, kqueue, nativesockets +import std/[posix, times, kqueue, nativesockets] const # Maximum number of events that can be returned. @@ -194,7 +194,9 @@ when hasThreadSupport: if s.changesLength > 0: if kevent(s.kqFD, addr(s.changes[0]), cint(s.changesLength), nil, 0, nil) == -1: - raiseIOSelectorsError(osLastError()) + let res = osLastError() + if cint(res) != ENOENT: # ignore pipes whose read end is closed + raiseIOSelectorsError(res) s.changesLength = 0 else: template modifyKQueue[T](s: Selector[T], nident: uint, nfilter: cshort, @@ -211,7 +213,9 @@ else: if length > 0: if kevent(s.kqFD, addr(s.changes[0]), length, nil, 0, nil) == -1: - raiseIOSelectorsError(osLastError()) + let res = osLastError() + if cint(res) != ENOENT: # ignore pipes whose read end is closed + raiseIOSelectorsError(res) s.changes.setLen(0) proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle, diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim index 12812ac80..7c5347156 100644 --- a/lib/pure/ioselects/ioselectors_poll.nim +++ b/lib/pure/ioselects/ioselectors_poll.nim @@ -9,7 +9,7 @@ # This module implements Posix poll(). -import posix, times +import std/[posix, times] # Maximum number of events that can be returned const MAX_POLL_EVENTS = 64 diff --git a/lib/pure/ioselects/ioselectors_select.nim b/lib/pure/ioselects/ioselectors_select.nim index a6f54e791..6c516395b 100644 --- a/lib/pure/ioselects/ioselectors_select.nim +++ b/lib/pure/ioselects/ioselectors_select.nim @@ -9,10 +9,10 @@ # This module implements Posix and Windows select(). -import times, nativesockets +import std/[times, nativesockets] when defined(windows): - import winlean + import std/winlean when defined(gcc): {.passl: "-lws2_32".} elif defined(vcc): @@ -314,7 +314,7 @@ proc selectInto*[T](s: Selector[T], timeout: int, if timeout != -1: when defined(genode) or defined(freertos) or defined(zephyr) or defined(nuttx): - tv.tv_sec = Time(timeout div 1_000) + tv.tv_sec = posix.Time(timeout div 1_000) else: tv.tv_sec = timeout.int32 div 1_000 tv.tv_usec = (timeout.int32 %% 1_000) * 1_000 diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 8c1f19fd3..53fa7553a 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -165,9 +165,9 @@ runnableExamples: a1, a2, a0, a3, a4: int doAssert $(%* Foo()) == """{"a1":0,"a2":0,"a0":0,"a3":0,"a4":0}""" -import hashes, tables, strutils, lexbase, streams, macros, parsejson +import std/[hashes, tables, strutils, lexbase, streams, macros, parsejson] -import options # xxx remove this dependency using same approach as https://github.com/nim-lang/Nim/pull/14563 +import std/options # xxx remove this dependency using same approach as https://github.com/nim-lang/Nim/pull/14563 import std/private/since when defined(nimPreviewSlimSystem): @@ -549,7 +549,7 @@ proc `[]`*[U, V](a: JsonNode, x: HSlice[U, V]): JsonNode = ## ## Returns the inclusive range `[a[x.a], a[x.b]]`: runnableExamples: - import json + import std/json let arr = %[0,1,2,3,4,5] doAssert arr[2..4] == %[2,3,4] doAssert arr[2..^2] == %[2,3,4] @@ -634,7 +634,7 @@ proc delete*(obj: JsonNode, key: string) = obj.fields.del(key) proc copy*(p: JsonNode): JsonNode = - ## Performs a deep copy of `a`. + ## Performs a deep copy of `p`. case p.kind of JString: result = newJString(p.str) @@ -965,7 +965,7 @@ proc parseJson*(s: Stream, filename: string = ""; rawIntegers = false, rawFloats p.close() when defined(js): - from math import `mod` + from std/math import `mod` from std/jsffi import JsObject, `[]`, to from std/private/jsutils import getProtoName, isInteger, isSafeInteger @@ -991,9 +991,9 @@ when defined(js): else: assert false proc len(x: JsObject): int = - asm """ + {.emit: """ `result` = `x`.length; - """ + """.} proc convertObject(x: JsObject): JsonNode = var isRawNumber = false @@ -1004,14 +1004,15 @@ when defined(js): result.add(x[i].convertObject()) of JObject: result = newJObject() - asm """for (var property in `x`) { + {.emit: """for (var property in `x`) { if (`x`.hasOwnProperty(property)) { - """ + """.} + var nimProperty: cstring var nimValue: JsObject - asm "`nimProperty` = property; `nimValue` = `x`[property];" + {.emit: "`nimProperty` = property; `nimValue` = `x`[property];".} result[$nimProperty] = nimValue.convertObject() - asm "}}" + {.emit: "}}".} of JInt: result = newJInt(x.to(int)) of JFloat: @@ -1366,7 +1367,7 @@ proc to*[T](node: JsonNode, t: typedesc[T]): T = initFromJson(result, node, jsonPath) when false: - import os + import std/os var s = newFileStream(paramStr(1), fmRead) if s == nil: quit("cannot open the file" & paramStr(1)) var x: JsonParser diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim index 336a57ec1..1efd97b24 100644 --- a/lib/pure/lexbase.nim +++ b/lib/pure/lexbase.nim @@ -12,7 +12,7 @@ ## needs refilling. import - strutils, streams + std/[strutils, streams] when defined(nimPreviewSlimSystem): import std/assertions @@ -104,9 +104,9 @@ proc fillBaseLexer(L: var BaseLexer, pos: int): int = result = 0 proc handleCR*(L: var BaseLexer, pos: int): int = - ## Call this if you scanned over '\c' in the buffer; it returns the + ## Call this if you scanned over `'\c'` in the buffer; it returns the ## position to continue the scanning from. `pos` must be the position - ## of the '\c'. + ## of the `'\c'`. assert(L.buf[pos] == '\c') inc(L.lineNumber) result = fillBaseLexer(L, pos) @@ -115,9 +115,9 @@ proc handleCR*(L: var BaseLexer, pos: int): int = L.lineStart = result proc handleLF*(L: var BaseLexer, pos: int): int = - ## Call this if you scanned over '\L' in the buffer; it returns the + ## Call this if you scanned over `'\L'` in the buffer; it returns the ## position to continue the scanning from. `pos` must be the position - ## of the '\L'. + ## of the `'\L'`. assert(L.buf[pos] == '\L') inc(L.lineNumber) result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result; diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim index 1767ee3f6..c30f68af8 100644 --- a/lib/pure/logging.nim +++ b/lib/pure/logging.nim @@ -146,9 +146,9 @@ ## * `strscans module<strscans.html>`_ for ``scanf`` and ``scanp`` macros, which ## offer easier substring extraction than regular expressions -import strutils, times +import std/[strutils, times] when not defined(js): - import os + import std/os when defined(nimPreviewSlimSystem): import std/syncio @@ -839,6 +839,7 @@ proc addHandler*(handler: Logger) = ## each of those threads. ## ## See also: + ## * `removeHandler proc`_ ## * `getHandlers proc<#getHandlers>`_ runnableExamples: var logger = newConsoleLogger() @@ -846,6 +847,16 @@ proc addHandler*(handler: Logger) = doAssert logger in getHandlers() handlers.add(handler) +proc removeHandler*(handler: Logger) = + ## Removes a logger from the list of registered handlers. + ## + ## Note that for n times a logger is registered, n calls to this proc + ## are required to remove that logger. + for i, hnd in handlers: + if hnd == handler: + handlers.delete(i) + return + proc getHandlers*(): seq[Logger] = ## Returns a list of all the registered handlers. ## diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim index 7c092973f..f9b3d3e4c 100644 --- a/lib/pure/marshal.nim +++ b/lib/pure/marshal.nim @@ -54,7 +54,7 @@ Please use alternative packages for serialization. It is possible to reimplement this module using generics and type traits. Please contribute a new implementation.""".} -import streams, typeinfo, json, intsets, tables, unicode +import std/[streams, typeinfo, json, intsets, tables, unicode] when defined(nimPreviewSlimSystem): import std/[assertions, formatfloat] @@ -210,7 +210,8 @@ proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) = setPointer(a, nil) next(p) of jsonInt: - setPointer(a, t.getOrDefault(p.getInt)) + var raw = t.getOrDefault(p.getInt) + setPointer(a, addr raw) next(p) of jsonArrayStart: next(p) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 4bc720a46..ed7d2382f 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -57,13 +57,14 @@ import std/private/since {.push debugger: off.} # the user does not want to trace a part # of the standard library! -import bitops, fenv +import std/[bitops, fenv] +import system/countbits_impl when defined(nimPreviewSlimSystem): import std/assertions -when defined(c) or defined(cpp): +when not defined(js) and not defined(nimscript): # C proc c_isnan(x: float): bool {.importc: "isnan", header: "<math.h>".} # a generic like `x: SomeFloat` might work too if this is implemented via a C macro. @@ -155,7 +156,7 @@ func fac*(n: int): int = {.push checks: off, line_dir: off, stack_trace: off.} -when defined(posix) and not defined(genode): +when defined(posix) and not defined(genode) and not defined(macosx): {.passl: "-lm".} const @@ -200,7 +201,7 @@ func isNaN*(x: SomeFloat): bool {.inline, since: (1,5,1).} = template fn: untyped = result = x != x when nimvm: fn() else: - when defined(js): fn() + when defined(js) or defined(nimscript): fn() else: result = c_isnan(x) when defined(js): @@ -219,13 +220,13 @@ when defined(js): let a = newFloat64Array(buffer) let b = newUint32Array(buffer) a[0] = x - asm """ + {.emit: """ function updateBit(num, bitPos, bitVal) { return (num & ~(1 << bitPos)) | (bitVal << bitPos); } `b`[1] = updateBit(`b`[1], 31, `sgn`); - `result` = `a`[0] - """ + `result` = `a`[0]; + """.} proc signbit*(x: SomeFloat): bool {.inline, since: (1, 5, 1).} = ## Returns true if `x` is negative, false otherwise. @@ -270,7 +271,6 @@ func classify*(x: float): FloatClass = ## Classifies a floating point value. ## ## Returns `x`'s class as specified by the `FloatClass enum<#FloatClass>`_. - ## Doesn't work with `--passc:-ffast-math`. runnableExamples: doAssert classify(0.3) == fcNormal doAssert classify(0.0) == fcZero @@ -279,6 +279,7 @@ func classify*(x: float): FloatClass = doAssert classify(5.0e-324) == fcSubnormal # JavaScript and most C compilers have no classify: + if isNan(x): return fcNan if x == 0.0: if 1.0 / x == Inf: return fcZero @@ -287,7 +288,6 @@ func classify*(x: float): FloatClass = if x * 0.5 == x: if x > 0.0: return fcInf else: return fcNegInf - if x != x: return fcNan if abs(x) < MinFloatNormal: return fcSubnormal return fcNormal @@ -1230,40 +1230,42 @@ func gcd*[T](x, y: T): T = swap x, y abs x -func gcd*(x, y: SomeInteger): SomeInteger = - ## Computes the greatest common (positive) divisor of `x` and `y`, - ## using the binary GCD (aka Stein's) algorithm. - ## - ## **See also:** - ## * `gcd func <#gcd,T,T>`_ for a float version - ## * `lcm func <#lcm,T,T>`_ - runnableExamples: - doAssert gcd(12, 8) == 4 - doAssert gcd(17, 63) == 1 - - when x is SomeSignedInt: - var x = abs(x) - else: - var x = x - when y is SomeSignedInt: - var y = abs(y) - else: - var y = y - - if x == 0: - return y - if y == 0: - return x - - let shift = countTrailingZeroBits(x or y) - y = y shr countTrailingZeroBits(y) - while x != 0: - x = x shr countTrailingZeroBits(x) - if y > x: - swap y, x - x -= y - y shl shift - +when useBuiltins: + ## this func uses bitwise comparisons from C compilers, which are not always available. + func gcd*(x, y: SomeInteger): SomeInteger = + ## Computes the greatest common (positive) divisor of `x` and `y`, + ## using the binary GCD (aka Stein's) algorithm. + ## + ## **See also:** + ## * `gcd func <#gcd,T,T>`_ for a float version + ## * `lcm func <#lcm,T,T>`_ + runnableExamples: + doAssert gcd(12, 8) == 4 + doAssert gcd(17, 63) == 1 + + when x is SomeSignedInt: + var x = abs(x) + else: + var x = x + when y is SomeSignedInt: + var y = abs(y) + else: + var y = y + + if x == 0: + return y + if y == 0: + return x + + let shift = countTrailingZeroBits(x or y) + y = y shr countTrailingZeroBits(y) + while x != 0: + x = x shr countTrailingZeroBits(x) + if y > x: + swap y, x + x -= y + y shl shift + func gcd*[T](x: openArray[T]): T {.since: (1, 1).} = ## Computes the greatest common (positive) divisor of the elements of `x`. ## diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index c65a9c2da..9c3f6d51b 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -100,32 +100,19 @@ proc decode(dest: var openArray[uint8], src: openArray[uint32]) = dest[i+3] = uint8(src[j] shr 24 and 0xff'u32) inc(i, 4) -template slice(s: string, a, b): openArray[uint8] = - when nimvm: - # toOpenArray is not implemented in VM - var s2 = newSeq[uint8](s.len) - for i in 0 ..< s2.len: - s2[i] = uint8(s[i]) - s2 - else: - s.toOpenArrayByte(a, b) - template slice(s: cstring, a, b): openArray[uint8] = when nimvm: # toOpenArray is not implemented in VM - slice($s, a, b) + toOpenArrayByte($s, a, b) else: when defined(js): # toOpenArrayByte for cstring is not implemented in JS - slice($s, a, b) + toOpenArrayByte($s, a, b) else: s.toOpenArrayByte(a, b) template slice(s: openArray[uint8], a, b): openArray[uint8] = - when nimvm: - s[a .. b] - else: - s.toOpenArray(a, b) + s.toOpenArray(a, b) const useMem = declared(copyMem) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index e27f9a79c..8eec551c4 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -16,15 +16,15 @@ ## other "line-like", variable length, delimited records). when defined(windows): - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/widestrs elif defined(posix): - import posix + import std/posix else: {.error: "the memfiles module is not supported on your operating system!".} -import streams +import std/streams import std/oserrors when defined(nimPreviewSlimSystem): @@ -35,12 +35,12 @@ proc newEIO(msg: string): ref IOError = new(result) result.msg = msg -proc setFileSize(fh: FileHandle, newFileSize = -1): OSErrorCode = - ## Set the size of open file pointed to by `fh` to `newFileSize` if != -1. - ## Space is only allocated if that is cheaper than writing to the file. This - ## routine returns the last OSErrorCode found rather than raising to support - ## old rollback/clean-up code style. [ Should maybe move to std/osfiles. ] - if newFileSize == -1: +proc setFileSize(fh: FileHandle, newFileSize = -1, oldSize = -1): OSErrorCode = + ## Set the size of open file pointed to by `fh` to `newFileSize` if != -1, + ## allocating | freeing space from the file system. This routine returns the + ## last OSErrorCode found rather than raising to support old rollback/clean-up + ## code style. [ Should maybe move to std/osfiles. ] + if newFileSize < 0 or newFileSize == oldSize: return when defined(windows): var sizeHigh = int32(newFileSize shr 32) @@ -51,14 +51,18 @@ proc setFileSize(fh: FileHandle, newFileSize = -1): OSErrorCode = setEndOfFile(fh) == 0: result = lastErr else: - var e: cint # posix_fallocate truncates up when needed. - when declared(posix_fallocate): - while (e = posix_fallocate(fh, 0, newFileSize); e == EINTR): - discard - if e in [EINVAL, EOPNOTSUPP] and ftruncate(fh, newFileSize) == -1: - result = osLastError() # fallback arguable; Most portable, but allows SEGV - elif e != 0: - result = osLastError() + if newFileSize > oldSize: # grow the file + var e: cint # posix_fallocate truncates up when needed. + when declared(posix_fallocate): + while (e = posix_fallocate(fh, 0, newFileSize); e == EINTR): + discard + if e in [EINVAL, EOPNOTSUPP] and ftruncate(fh, newFileSize) == -1: + result = osLastError() # fallback arguable; Most portable BUT allows SEGV + elif e != 0: + result = osLastError() + else: # shrink the file + if ftruncate(fh.cint, newFileSize) == -1: + result = osLastError() type MemFile* = object ## represents a memory mapped file @@ -255,41 +259,31 @@ proc open*(filename: string, mode: FileMode = fmRead, flags = flags or O_CREAT or O_TRUNC var permissionsMode = S_IRUSR or S_IWUSR result.handle = open(filename, flags, permissionsMode) + if result.handle != -1: + if (let e = setFileSize(result.handle.FileHandle, newFileSize); + e != 0.OSErrorCode): fail(e, "error setting file size") else: result.handle = open(filename, flags) if result.handle == -1: - # XXX: errno is supposed to be set here - # Is there an exception that wraps it? fail(osLastError(), "error opening file") - if (let e = setFileSize(result.handle.FileHandle, newFileSize); - e != 0.OSErrorCode): fail(e, "error setting file size") - - if mappedSize != -1: - result.size = mappedSize - else: - var stat: Stat + if mappedSize != -1: #XXX Logic here differs from `when windows` branch .. + result.size = mappedSize #.. which always fstats&Uses min(mappedSize, st). + else: # if newFileSize!=-1: result.size=newFileSize # if trust setFileSize + var stat: Stat #^^.. BUT some FSes (eg. Linux HugeTLBfs) round to 2MiB. if fstat(result.handle, stat) != -1: - # XXX: Hmm, this could be unsafe - # Why is mmap taking int anyway? - result.size = int(stat.st_size) + result.size = stat.st_size.int # int may be 32-bit-unsafe for 2..<4 GiB else: fail(osLastError(), "error getting file size") result.flags = if mapFlags == cint(-1): MAP_SHARED else: mapFlags - #Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set + # Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set if int(result.flags and MAP_PRIVATE) == 0: result.flags = result.flags or MAP_SHARED - result.mem = mmap( - nil, - result.size, - if readonly: PROT_READ else: PROT_READ or PROT_WRITE, - result.flags, - result.handle, - offset) - + let pr = if readonly: PROT_READ else: PROT_READ or PROT_WRITE + result.mem = mmap(nil, result.size, pr, result.flags, result.handle, offset) if result.mem == cast[pointer](MAP_FAILED): fail(osLastError(), "file mapping failed") @@ -353,7 +347,7 @@ proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} = raise newException(IOError, "Cannot resize MemFile opened with allowRemap=false") if newFileSize != f.size: - if (let e = setFileSize(f.handle.FileHandle, newFileSize); + if (let e = setFileSize(f.handle.FileHandle, newFileSize, f.size); e != 0.OSErrorCode): raiseOSError(e) when defined(linux): #Maybe NetBSD, too? # On Linux this can be over 100 times faster than a munmap,mmap cycle. @@ -418,7 +412,7 @@ proc `==`*(x, y: MemSlice): bool = proc `$`*(ms: MemSlice): string {.inline.} = ## Return a Nim string built from a MemSlice. result.setLen(ms.size) - copyMem(addr(result[0]), ms.data, ms.size) + copyMem(result.cstring, ms.data, ms.size) iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline.} = ## Iterates over \[optional `eat`] `delim`-delimited slices in MemFile `mfile`. diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim index 346fb39ee..ff639e8e5 100644 --- a/lib/pure/mimetypes.nim +++ b/lib/pure/mimetypes.nim @@ -26,8 +26,8 @@ runnableExamples: doAssert m.getMimetype("fakext") == "text/fakelang" doAssert m.getMimetype("FaKeXT") == "text/fakelang" -import tables -from strutils import startsWith, toLowerAscii, strip +import std/tables +from std/strutils import startsWith, toLowerAscii, strip when defined(nimPreviewSlimSystem): import std/assertions @@ -38,1848 +38,704 @@ type mimes: OrderedTable[string, string] const mimes* = { - "123": "application/vnd.lotus-1-2-3", - "1km": "application/vnd.1000minds.decision-model+xml", - "323": "text/h323", - "3dm": "text/vnd.in3d.3dml", - "3dmf": "x-world/x-3dmf", - "3dml": "text/vnd.in3d.3dml", - "3ds": "image/x-3ds", - "3g2": "video/3gpp2", - "3gp": "video/3gpp", - "3gpp": "audio/3gpp", - "3gpp2": "video/3gpp2", - "3mf": "application/vnd.ms-3mfdocument", - "669": "audio/x-mod", - "726": "audio/32kadpcm", - "7z": "application/x-7z-compressed", - "a": "text/plain", - "a2l": "application/a2l", - "aa3": "audio/atrac3", - "aab": "application/x-authorware-bin", - "aac": "audio/x-aac", - "aal": "audio/atrac-advanced-lossless", - "aam": "application/x-authorware-map", - "aas": "application/x-authorware-seg", - "abc": "text/vnd.abc", - "abw": "application/x-abiword", + "ez": "application/andrew-inset", + "aw": "application/applixware", + "atom": "application/atom+xml", + "atomcat": "application/atomcat+xml", + "atomsvc": "application/atomsvc+xml", + "ccxml": "application/ccxml+xml", + "cdmia": "application/cdmi-capability", + "cdmic": "application/cdmi-container", + "cdmid": "application/cdmi-domain", + "cdmio": "application/cdmi-object", + "cdmiq": "application/cdmi-queue", + "cu": "application/cu-seeme", + "davmount": "application/davmount+xml", + "dbk": "application/docbook+xml", + "dssc": "application/dssc+der", + "xdssc": "application/dssc+xml", + "ecma": "application/ecmascript", + "emma": "application/emma+xml", + "epub": "application/epub+zip", + "exi": "application/exi", + "pfr": "application/font-tdpfr", + "gml": "application/gml+xml", + "gpx": "application/gpx+xml", + "gxf": "application/gxf", + "stk": "application/hyperstudio", + "ink": "application/inkml+xml", + "inkml": "application/inkml+xml", + "ipfix": "application/ipfix", + "jar": "application/java-archive", + "ser": "application/java-serialized-object", + "class": "application/java-vm", + "json": "application/json", + "jsonml": "application/jsonml+json", + "lostxml": "application/lost+xml", + "hqx": "application/mac-binhex40", + "cpt": "application/mac-compactpro", + "mads": "application/mads+xml", + "mrc": "application/marc", + "mrcx": "application/marcxml+xml", + "ma": "application/mathematica", + "nb": "application/mathematica", + "mb": "application/mathematica", + "mathml": "application/mathml+xml", + "mbox": "application/mbox", + "mscml": "application/mediaservercontrol+xml", + "metalink": "application/metalink+xml", + "meta4": "application/metalink4+xml", + "mets": "application/mets+xml", + "mods": "application/mods+xml", + "m21": "application/mp21", + "mp21": "application/mp21", + "mp4s": "application/mp4", + "doc": "application/msword", + "dot": "application/msword", + "mxf": "application/mxf", + "bin": "application/octet-stream", + "dms": "application/octet-stream", + "lrf": "application/octet-stream", + "mar": "application/octet-stream", + "so": "application/octet-stream", + "dist": "application/octet-stream", + "distz": "application/octet-stream", + "pkg": "application/octet-stream", + "bpk": "application/octet-stream", + "dump": "application/octet-stream", + "elc": "application/octet-stream", + "deploy": "application/octet-stream", + "oda": "application/oda", + "opf": "application/oebps-package+xml", + "ogx": "application/ogg", + "omdoc": "application/omdoc+xml", + "onetoc": "application/onenote", + "onetoc2": "application/onenote", + "onetmp": "application/onenote", + "onepkg": "application/onenote", + "oxps": "application/oxps", + "xer": "application/patch-ops-error+xml", + "pdf": "application/pdf", + "pgp": "application/pgp-encrypted", + "asc": "application/pgp-signature", + "sig": "application/pgp-signature", + "prf": "application/pics-rules", + "p10": "application/pkcs10", + "p7m": "application/pkcs7-mime", + "p7c": "application/pkcs7-mime", + "p7s": "application/pkcs7-signature", + "p8": "application/pkcs8", "ac": "application/pkix-attr-cert", - "ac3": "audio/ac3", - "acc": "application/vnd.americandynamics.acc", - "ace": "application/x-ace-compressed", - "acn": "audio/asc", - "acu": "application/vnd.acucobol", - "acutc": "application/vnd.acucorp", - "acx": "application/internet-property-stream", - "adp": "audio/adpcm", - "aep": "application/vnd.audiograph", - "afl": "video/animaflex", - "afm": "application/x-font-type1", - "afp": "application/vnd.ibm.modcap", - "ahead": "application/vnd.ahead.space", + "cer": "application/pkix-cert", + "crl": "application/pkix-crl", + "pkipath": "application/pkix-pkipath", + "pki": "application/pkixcmp", + "pls": "application/pls+xml", "ai": "application/postscript", - "aif": "audio/x-aiff", - "aifc": "audio/x-aiff", - "aiff": "audio/x-aiff", - "aim": "application/x-aim", - "aip": "text/x-audiosoft-intra", - "air": "application/vnd.adobe.air-application-installer-package+zip", - "ait": "application/vnd.dvb.ait", - "alc": "chemical/x-alchemy", - "ami": "application/vnd.amiga.ami", - "aml": "application/aml", - "amr": "audio/amr", - "ani": "application/x-navi-animation", - "anx": "application/x-annodex", - "aos": "application/x-nokia-9000-communicator-add-on-software", - "apinotes": "text/apinotes", - "apk": "application/vnd.android.package-archive", - "apkg": "application/vnd.anki", - "apng": "image/apng", - "appcache": "text/cache-manifest", - "appimage": "application/appimage", - "application": "application/x-ms-application", - "apr": "application/vnd.lotus-approach", - "aps": "application/mime", - "apxml": "application/auth-policy+xml", - "arc": "application/x-freearc", - "arj": "application/x-arj", - "art": "message/rfc822", - "asar": "binary/asar", - "asc": "text/plain", - "ascii": "text/vnd.ascii-art", - "asf": "application/vnd.ms-asf", - "asice": "application/vnd.etsi.asic-e+zip", - "asics": "application/vnd.etsi.asic-s+zip", - "asm": "text/x-asm", - "asn": "chemical/x-ncbi-asn1-spec", + "eps": "application/postscript", + "ps": "application/postscript", + "cww": "application/prs.cww", + "pskcxml": "application/pskc+xml", + "rdf": "application/rdf+xml", + "rif": "application/reginfo+xml", + "rnc": "application/relax-ng-compact-syntax", + "rl": "application/resource-lists+xml", + "rld": "application/resource-lists-diff+xml", + "rs": "application/rls-services+xml", + "gbr": "application/rpki-ghostbusters", + "mft": "application/rpki-manifest", + "roa": "application/rpki-roa", + "rsd": "application/rsd+xml", + "rss": "application/rss+xml", + "rtf": "application/rtf", + "sbml": "application/sbml+xml", + "scq": "application/scvp-cv-request", + "scs": "application/scvp-cv-response", + "spq": "application/scvp-vp-request", + "spp": "application/scvp-vp-response", + "sdp": "application/sdp", + "setpay": "application/set-payment-initiation", + "setreg": "application/set-registration-initiation", + "shf": "application/shf+xml", + "smi": "application/smil+xml", + "smil": "application/smil+xml", + "rq": "application/sparql-query", + "srx": "application/sparql-results+xml", + "gram": "application/srgs", + "grxml": "application/srgs+xml", + "sru": "application/sru+xml", + "ssdl": "application/ssdl+xml", + "ssml": "application/ssml+xml", + "tei": "application/tei+xml", + "teicorpus": "application/tei+xml", + "tfi": "application/thraud+xml", + "tsd": "application/timestamped-data", + "plb": "application/vnd.3gpp.pic-bw-large", + "psb": "application/vnd.3gpp.pic-bw-small", + "pvb": "application/vnd.3gpp.pic-bw-var", + "tcap": "application/vnd.3gpp2.tcap", + "pwn": "application/vnd.3m.post-it-notes", "aso": "application/vnd.accpac.simply.aso", - "asp": "text/asp", - "asr": "video/x-ms-asf", - "asx": "video/x-ms-asf", - "at3": "audio/atrac3", + "imp": "application/vnd.accpac.simply.imp", + "acu": "application/vnd.acucobol", "atc": "application/vnd.acucorp", - "atf": "application/atf", - "atfx": "application/atfx", - "atom": "application/atom+xml", - "atomcat": "application/atomcat+xml", - "atomdeleted": "application/atomdeleted+xml", - "atomsrv": "application/atomserv+xml", - "atomsvc": "application/atomsvc+xml", - "atx": "application/vnd.antix.game-component", - "atxml": "application/atxml", - "au": "audio/basic", - "auc": "application/tamp-apex-update-confirm", - "avi": "video/x-msvideo", - "avs": "video/avs-video", - "aw": "application/applixware", - "awb": "audio/amr-wb", - "axa": "audio/x-annodex", - "axs": "application/olescript", - "axv": "video/x-annodex", + "acutc": "application/vnd.acucorp", + "air": "application/vnd.adobe.air-application-installer-package+zip", + "fcdt": "application/vnd.adobe.formscentral.fcdt", + "fxp": "application/vnd.adobe.fxp", + "fxpl": "application/vnd.adobe.fxp", + "xdp": "application/vnd.adobe.xdp+xml", + "xfdf": "application/vnd.adobe.xfdf", + "ahead": "application/vnd.ahead.space", "azf": "application/vnd.airzip.filesecure.azf", "azs": "application/vnd.airzip.filesecure.azs", - "azv": "image/vnd.airzip.accelerator.azv", "azw": "application/vnd.amazon.ebook", - "azw3": "application/vnd.amazon.mobi8-ebook", - "b": "chemical/x-molconn-Z", - "bak": "application/x-trash", - "bar": "application/vnd.qualcomm.brew-app-res", - "bas": "text/plain", - "bash": "text/shell", - "bat": "application/x-msdos-program", - "bcpio": "application/x-bcpio", - "bdf": "application/x-font-bdf", - "bdm": "application/vnd.syncml.dm+wbxml", - "bdoc": "application/bdoc", - "bed": "application/vnd.realvnc.bed", - "bh2": "application/vnd.fujitsu.oasysprs", - "bib": "text/x-bibtex", - "bik": "video/vnd.radgamettools.bink", - "bin": "application/octet-stream", - "bk2": "video/vnd.radgamettools.bink", - "bkm": "application/vnd.nervana", - "blb": "application/x-blorb", - "blend": "binary/blender", - "blorb": "application/x-blorb", - "bm": "image/bmp", - "bmed": "multipart/vnd.bint.med-plus", + "acc": "application/vnd.americandynamics.acc", + "ami": "application/vnd.amiga.ami", + "apk": "application/vnd.android.package-archive", + "cii": "application/vnd.anser-web-certificate-issue-initiation", + "fti": "application/vnd.anser-web-funds-transfer-initiation", + "atx": "application/vnd.antix.game-component", + "mpkg": "application/vnd.apple.installer+xml", + "m3u8": "application/vnd.apple.mpegurl", + "swi": "application/vnd.aristanetworks.swi", + "iota": "application/vnd.astraea-software.iota", + "aep": "application/vnd.audiograph", + "mpm": "application/vnd.blueice.multipass", "bmi": "application/vnd.bmi", - "bmml": "application/vnd.balsamiq.bmml+xml", - "bmp": "image/bmp", - "bmpr": "application/vnd.balsamiq.bmpr", - "boo": "application/book", - "book": "application/book", - "box": "application/vnd.previewsystems.box", - "boz": "application/x-bzip2", - "bpd": "application/vnd.hbci", - "bpk": "application/octet-stream", - "brf": "text/plain", - "bsd": "chemical/x-crossfire", - "bsh": "application/x-bsh", - "bsp": "model/vnd.valve.source.compiled-map", - "btf": "image/prs.btif", - "btif": "image/prs.btif", - "bz": "application/x-bzip", - "bz2": "application/x-bzip2", - "c": "text/x-csrc", - "c++": "text/x-c++src", - "c11amc": "application/vnd.cluetrust.cartomobile-config", - "c11amz": "application/vnd.cluetrust.cartomobile-config-pkg", - "c3d": "chemical/x-chem3d", - "c3ex": "application/cccex", + "rep": "application/vnd.businessobjects", + "cdxml": "application/vnd.chemdraw+xml", + "mmd": "application/vnd.chipnuts.karaoke-mmd", + "cdy": "application/vnd.cinderella", + "cla": "application/vnd.claymore", + "rp9": "application/vnd.cloanto.rp9", + "c4g": "application/vnd.clonk.c4group", "c4d": "application/vnd.clonk.c4group", "c4f": "application/vnd.clonk.c4group", - "c4g": "application/vnd.clonk.c4group", "c4p": "application/vnd.clonk.c4group", "c4u": "application/vnd.clonk.c4group", - "cab": "application/vnd.ms-cab-compressed", - "cac": "chemical/x-cache", - "cache": "application/x-cache", - "caf": "audio/x-caf", - "cap": "application/vnd.tcpdump.pcap", - "car": "application/vnd.curl.car", - "cascii": "chemical/x-cactvs-binary", - "cat": "application/vnd.ms-pki.seccat", - "cb7": "application/x-cbr", - "cba": "application/x-cbr", - "cbin": "chemical/x-cactvs-binary", - "cbor": "application/cbor", - "cbr": "application/x-cbr", - "cbt": "application/x-cbr", - "cbz": "application/vnd.comicbook+zip", - "cc": "text/plain", - "ccad": "application/clariscad", - "ccc": "text/vnd.net2phone.commcenter.command", - "ccmp": "application/ccmp+xml", - "cco": "application/x-cocoa", - "cct": "application/x-director", - "ccxml": "application/ccxml+xml", - "cda": "application/x-cdf", + "c11amc": "application/vnd.cluetrust.cartomobile-config", + "c11amz": "application/vnd.cluetrust.cartomobile-config-pkg", + "csp": "application/vnd.commonspace", "cdbcmsg": "application/vnd.contact.cmsg", - "cdf": "application/x-netcdf", - "cdfx": "application/cdfx+xml", - "cdkey": "application/vnd.mediastation.cdkey", - "cdmia": "application/cdmi-capability", - "cdmic": "application/cdmi-container", - "cdmid": "application/cdmi-domain", - "cdmio": "application/cdmi-object", - "cdmiq": "application/cdmi-queue", - "cdr": "image/x-coreldraw", - "cdt": "image/x-coreldrawtemplate", - "cdx": "chemical/x-cdx", - "cdxml": "application/vnd.chemdraw+xml", - "cdy": "application/vnd.cinderella", - "cea": "application/cea", - "cef": "chemical/x-cxf", - "cellml": "application/cellml+xml", - "cer": "application/pkix-cert", - "cfg": "text/cfg", - "cfs": "application/x-cfs-compressed", - "cgm": "image/cgm", - "cha": "application/x-chat", - "chat": "application/x-chat", - "chm": "application/vnd.ms-htmlhelp", - "chrt": "application/vnd.kde.kchart", - "cif": "chemical/x-cif", - "cii": "application/vnd.anser-web-certificate-issue-initiation", - "cil": "application/vnd.ms-artgalry", - "cl": "application/simple-filter+xml", - "cla": "application/vnd.claymore", - "class": "application/java-vm", + "cmc": "application/vnd.cosmocaller", + "clkx": "application/vnd.crick.clicker", "clkk": "application/vnd.crick.clicker.keyboard", "clkp": "application/vnd.crick.clicker.palette", "clkt": "application/vnd.crick.clicker.template", "clkw": "application/vnd.crick.clicker.wordbank", - "clkx": "application/vnd.crick.clicker", - "clp": "application/x-msclip", - "cls": "text/x-tex", - "clue": "application/clue_info+xml", - "cmake": "text/cmake", - "cmc": "application/vnd.cosmocaller", - "cmdf": "chemical/x-cmdf", - "cml": "chemical/x-cml", - "cmp": "application/vnd.yellowriver-custom-menu", - "cmsc": "application/cms", - "cmx": "image/x-cmx", - "cnd": "text/jcr-cnd", - "cnf": "text/cnf", - "cod": "application/vnd.rim.cod", - "coffee": "application/vnd.coffeescript", - "com": "application/x-msdos-program", - "conf": "text/plain", - "copyright": "text/vnd.debian.copyright", - "cpa": "chemical/x-compass", - "cpio": "application/x-cpio", - "cpkg": "application/vnd.xmpie.cpkg", - "cpl": "application/cpl+xml", - "cpp": "text/x-c++src", - "cpt": "application/mac-compactpro", - "cr2": "image/x-canon-cr2", - "crd": "application/x-mscardfile", - "crl": "application/pkix-crl", - "crt": "application/x-x509-ca-cert", - "crtr": "application/vnd.multiad.creator", - "crw": "image/x-canon-crw", - "crx": "application/x-chrome-extension", - "cryptonote": "application/vnd.rig.cryptonote", - "cs": "text/c#", - "csf": "chemical/x-cache-csf", - "csh": "application/x-csh", - "csl": "application/vnd.citationstyles.style+xml", - "csm": "chemical/x-csml", - "csml": "chemical/x-csml", - "cson": "text/cson", - "csp": "application/vnd.commonspace", - "csrattrs": "application/csrattrs", - "css": "text/css", - "cst": "application/vnd.commonspace", - "csv": "text/csv", - "csvs": "text/csv-schema", - "ctab": "chemical/x-cactvs-binary", - "ctx": "chemical/x-ctx", - "cu": "application/cu-seeme", - "cub": "chemical/x-gaussian-cube", - "cuc": "application/tamp-community-update-confirm", - "curl": "text/vnd.curl", - "cw": "application/prs.cww", - "cww": "application/prs.cww", - "cxf": "chemical/x-cxf", - "cxt": "application/x-director", - "cxx": "text/plain", - "d": "text/x-dsrc", - "dae": "model/vnd.collada+xml", - "daf": "application/vnd.mobius.daf", + "wbs": "application/vnd.criticaltools.wbs+xml", + "pml": "application/vnd.ctc-posml", + "ppd": "application/vnd.cups-ppd", + "car": "application/vnd.curl.car", + "pcurl": "application/vnd.curl.pcurl", "dart": "application/vnd.dart", - "dat": "application/x-ns-proxy-autoconfig", - "dataless": "application/vnd.fdsn.seed", - "davmount": "application/davmount+xml", - "dbk": "application/docbook+xml", - "dcd": "application/dcd", - "dcf": "application/vnd.oma.drm.content", - "dcm": "application/dicom", - "dcr": "application/x-director", - "dcurl": "text/vnd.curl.dcurl", - "dd": "application/vnd.oma.dd+xml", - "dd2": "application/vnd.oma.dd2+xml", - "ddd": "application/vnd.fujixerox.ddd", - "ddf": "application/vnd.syncml.dmddf+xml", - "deb": "application/vnd.debian.binary-package", - "deepv": "application/x-deepv", - "def": "text/plain", - "deploy": "application/octet-stream", - "der": "application/x-x509-ca-cert", - "dfac": "application/vnd.dreamfactory", - "dgc": "application/x-dgc-compressed", - "dib": "image/bmp", - "dic": "text/x-c", - "dif": "video/x-dv", - "diff": "text/x-diff", - "dii": "application/dii", - "dim": "application/vnd.fastcopy-disk-image", - "dir": "application/x-director", - "dis": "application/vnd.mobius.dis", - "disposition-notification": "message/disposition-notification", - "dist": "application/vnd.apple.installer+xml", - "distz": "application/vnd.apple.installer+xml", - "dit": "application/dit", - "djv": "image/vnd.djvu", - "djvu": "image/vnd.djvu", - "dl": "video/dl", - "dll": "application/x-msdos-program", - "dls": "audio/dls", - "dm": "application/vnd.oma.drm.message", - "dmg": "application/x-apple-diskimage", - "dmp": "application/vnd.tcpdump.pcap", - "dms": "text/vnd.dmclientscript", + "rdz": "application/vnd.data-vision.rdz", + "uvf": "application/vnd.dece.data", + "uvvf": "application/vnd.dece.data", + "uvd": "application/vnd.dece.data", + "uvvd": "application/vnd.dece.data", + "uvt": "application/vnd.dece.ttml+xml", + "uvvt": "application/vnd.dece.ttml+xml", + "uvx": "application/vnd.dece.unspecified", + "uvvx": "application/vnd.dece.unspecified", + "uvz": "application/vnd.dece.zip", + "uvvz": "application/vnd.dece.zip", + "fe_launch": "application/vnd.denovo.fcselayout-link", "dna": "application/vnd.dna", - "doc": "application/msword", - "docjson": "application/vnd.document+json", - "docm": "application/vnd.ms-word.document.macroenabled.12", - "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "dor": "model/vnd.gdl", - "dot": "text/vnd.graphviz", - "dotm": "application/vnd.ms-word.template.macroenabled.12", - "dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", - "dp": "application/vnd.osgi.dp", + "mlp": "application/vnd.dolby.mlp", "dpg": "application/vnd.dpgraph", - "dpgraph": "application/vnd.dpgraph", - "dpkg": "application/vnd.xmpie.dpkg", - "dr": "application/vnd.oma.drm.rights+xml", - "dra": "audio/vnd.dra", - "drc": "application/vnd.oma.drm.rights+wbxml", - "drle": "image/dicom-rle", - "drw": "application/drafting", - "dsc": "text/prs.lines.tag", - "dsm": "application/vnd.desmume.movie", - "dssc": "application/dssc+der", - "dtb": "application/x-dtbook+xml", - "dtd": "application/xml-dtd", - "dts": "audio/vnd.dts", - "dtshd": "audio/vnd.dts.hd", - "dump": "application/octet-stream", - "dv": "video/x-dv", - "dvb": "video/vnd.dvb.file", - "dvc": "application/dvcs", - "dvi": "application/x-dvi", - "dwf": "model/vnd.dwf", - "dwg": "image/vnd.dwg", - "dx": "chemical/x-jcamp-dx", - "dxf": "image/vnd.dxf", - "dxp": "application/vnd.spotfire.dxp", - "dxr": "application/x-director", - "dzr": "application/vnd.dzr", - "ear": "binary/zip", - "ecelp4800": "audio/vnd.nuera.ecelp4800", - "ecelp7470": "audio/vnd.nuera.ecelp7470", - "ecelp9600": "audio/vnd.nuera.ecelp9600", - "ecig": "application/vnd.evolv.ecig.settings", - "ecigprofile": "application/vnd.evolv.ecig.profile", - "ecigtheme": "application/vnd.evolv.ecig.theme", - "ecma": "application/ecmascript", - "edm": "application/vnd.novadigm.edm", - "edx": "application/vnd.novadigm.edx", - "efi": "application/efi", - "efif": "application/vnd.picsel", - "ei6": "application/vnd.pg.osasli", - "ejs": "text/ejs", - "el": "text/plain", - "elc": "application/x-bytecode.elisp", - "emb": "chemical/x-embl-dl-nucleotide", - "embl": "chemical/x-embl-dl-nucleotide", - "emf": "image/emf", - "eml": "message/rfc822", - "emm": "application/vnd.ibm.electronic-media", - "emma": "application/emma+xml", - "emotionml": "application/emotionml+xml", - "emz": "application/x-msmetafile", - "ent": "text/xml-external-parsed-entity", - "entity": "application/vnd.nervana", - "env": "application/x-envoy", - "enw": "audio/evrcnw", - "eol": "audio/vnd.digital-winds", - "eot": "application/vnd.ms-fontobject", - "ep": "application/vnd.bluetooth.ep.oob", - "eps": "application/postscript", - "eps2": "application/postscript", - "eps3": "application/postscript", - "epsf": "application/postscript", - "epsi": "application/postscript", - "epub": "application/epub+zip", - "erb": "text/erb", - "erf": "image/x-epson-erf", - "es": "application/ecmascript", - "es3": "application/vnd.eszigno3+xml", - "esa": "application/vnd.osgi.subsystem", - "escn": "text/godot", + "dfac": "application/vnd.dreamfactory", + "kpxx": "application/vnd.ds-keypoint", + "ait": "application/vnd.dvb.ait", + "svc": "application/vnd.dvb.service", + "geo": "application/vnd.dynageo", + "mag": "application/vnd.ecowin.chart", + "nml": "application/vnd.enliven", "esf": "application/vnd.epson.esf", - "espass": "application/vnd.espass-espass+zip", + "msf": "application/vnd.epson.msf", + "qam": "application/vnd.epson.quickanime", + "slt": "application/vnd.epson.salt", + "ssf": "application/vnd.epson.ssf", + "es3": "application/vnd.eszigno3+xml", "et3": "application/vnd.eszigno3+xml", - "etx": "text/x-setext", - "eva": "application/x-eva", - "evb": "audio/evrcb", - "evc": "audio/evrc", - "evw": "audio/evrcwb", - "evy": "application/x-envoy", - "exe": "application/x-msdos-program", - "exi": "application/exi", - "exr": "image/aces", - "ext": "application/vnd.novadigm.ext", - "eyaml": "text/yaml", - "ez": "application/andrew-inset", "ez2": "application/vnd.ezpix-album", "ez3": "application/vnd.ezpix-package", - "f": "text/x-fortran", - "f4v": "video/x-f4v", - "f77": "text/x-fortran", - "f90": "text/plain", - "fb": "application/x-maker", - "fbdoc": "application/x-maker", - "fbs": "image/vnd.fastbidsheet", - "fbx": "model/filmbox", - "fcdt": "application/vnd.adobe.formscentral.fcdt", - "fch": "chemical/x-gaussian-checkpoint", - "fchk": "chemical/x-gaussian-checkpoint", - "fcs": "application/vnd.isac.fcs", "fdf": "application/vnd.fdf", - "fdt": "application/fdt+xml", - "fe_launch": "application/vnd.denovo.fcselayout-link", - "feature": "text/gherkin", - "fg5": "application/vnd.fujitsu.oasysgp", - "fgd": "application/x-director", - "fh": "image/x-freehand", - "fh4": "image/x-freehand", - "fh5": "image/x-freehand", - "fh7": "image/x-freehand", - "fhc": "image/x-freehand", - "fif": "image/fif", - "fig": "application/x-xfig", - "finf": "application/fastinfoset", - "fish": "text/fish", - "fit": "image/fits", - "fits": "image/fits", - "fla": "application/vnd.dtg.local.flash", - "flac": "audio/x-flac", - "fli": "video/x-fli", - "flo": "application/vnd.micrografx.flo", - "flr": "x-world/x-vrml", - "flv": "video/x-flv", - "flw": "application/vnd.kde.kivio", - "flx": "text/vnd.fmi.flexstor", - "fly": "text/vnd.fly", + "mseed": "application/vnd.fdsn.mseed", + "seed": "application/vnd.fdsn.seed", + "dataless": "application/vnd.fdsn.seed", + "gph": "application/vnd.flographit", + "ftc": "application/vnd.fluxtime.clip", "fm": "application/vnd.framemaker", - "fmf": "video/x-atomic3d-feature", - "fnc": "application/vnd.frogans.fnc", - "fo": "application/vnd.software602.filler.form+xml", - "for": "text/x-fortran", - "fpx": "image/vnd.fpx", "frame": "application/vnd.framemaker", - "frl": "application/freeloader", - "frm": "application/vnd.ufdl", + "maker": "application/vnd.framemaker", + "book": "application/vnd.framemaker", + "fnc": "application/vnd.frogans.fnc", + "ltf": "application/vnd.frogans.ltf", "fsc": "application/vnd.fsc.weblaunch", - "fst": "image/vnd.fst", - "ftc": "application/vnd.fluxtime.clip", - "fti": "application/vnd.anser-web-funds-transfer-initiation", - "fts": "image/fits", - "funk": "audio/make", - "fvt": "video/vnd.fvt", - "fxm": "video/x-javafx", - "fxp": "application/vnd.adobe.fxp", - "fxpl": "application/vnd.adobe.fxp", + "oas": "application/vnd.fujitsu.oasys", + "oa2": "application/vnd.fujitsu.oasys2", + "oa3": "application/vnd.fujitsu.oasys3", + "fg5": "application/vnd.fujitsu.oasysgp", + "bh2": "application/vnd.fujitsu.oasysprs", + "ddd": "application/vnd.fujixerox.ddd", + "xdw": "application/vnd.fujixerox.docuworks", + "xbd": "application/vnd.fujixerox.docuworks.binder", "fzs": "application/vnd.fuzzysheet", - "g": "text/plain", - "g2w": "application/vnd.geoplan", - "g3": "image/g3fax", - "g3w": "application/vnd.geospace", - "gac": "application/vnd.groove-account", - "gal": "chemical/x-gaussian-log", - "gam": "application/x-tads", - "gamin": "chemical/x-gamess-input", - "gau": "chemical/x-gaussian-input", - "gbr": "application/rpki-ghostbusters", - "gca": "application/x-gca-compressed", - "gcd": "text/x-pcs-gcd", - "gcf": "application/x-graphing-calculator", - "gcg": "chemical/x-gcg8-sequence", - "gdl": "model/vnd.gdl", - "gdoc": "application/vnd.google-apps.document", - "gemspec": "text/ruby", - "gen": "chemical/x-genbank", - "geo": "application/vnd.dynageo", - "geojson": "application/geo+json", - "gex": "application/vnd.geometry-explorer", - "gf": "application/x-tex-gf", + "txd": "application/vnd.genomatix.tuxedo", "ggb": "application/vnd.geogebra.file", + "ggs": "application/vnd.geogebra.slides", "ggt": "application/vnd.geogebra.tool", - "ghf": "application/vnd.groove-help", - "gif": "image/gif", - "gim": "application/vnd.groove-identity-message", - "gjc": "chemical/x-gaussian-input", - "gjf": "chemical/x-gaussian-input", - "gl": "video/gl", - "glb": "model/gltf-binary", - "gltf": "model/gltf+json", - "gml": "application/gml+xml", + "gex": "application/vnd.geometry-explorer", + "gre": "application/vnd.geometry-explorer", + "gxt": "application/vnd.geonext", + "g2w": "application/vnd.geoplan", + "g3w": "application/vnd.geospace", "gmx": "application/vnd.gmx", - "gnumeric": "application/x-gnumeric", - "go": "text/go", - "gotmpl": "text/gotmpl", - "gph": "application/vnd.flographit", - "gpt": "chemical/x-mopac-graph", - "gpx": "application/gpx+xml", + "kml": "application/vnd.google-earth.kml+xml", + "kmz": "application/vnd.google-earth.kmz", "gqf": "application/vnd.grafeq", "gqs": "application/vnd.grafeq", - "gradle": "text/groovy", - "gram": "application/srgs", - "gramps": "application/x-gramps-xml", - "gre": "application/vnd.geometry-explorer", - "groovy": "text/groovy", + "gac": "application/vnd.groove-account", + "ghf": "application/vnd.groove-help", + "gim": "application/vnd.groove-identity-message", "grv": "application/vnd.groove-injector", - "grxml": "application/srgs+xml", - "gsd": "audio/x-gsm", - "gsf": "application/x-font-ghostscript", - "gsheet": "application/vnd.google-apps.spreadsheet", - "gslides": "application/vnd.google-apps.presentation", - "gsm": "model/vnd.gdl", - "gsp": "application/x-gsp", - "gss": "application/x-gss", - "gtar": "application/x-gtar", "gtm": "application/vnd.groove-tool-message", - "gtw": "model/vnd.gtw", - "gv": "text/vnd.graphviz", - "gxf": "application/gxf", - "gxt": "application/vnd.geonext", - "gyb": "text/gyb", - "gyp": "text/gyp", - "gypi": "text/gyp", - "gz": "application/gzip", - "h": "text/x-chdr", - "h++": "text/x-c++hdr", - "h261": "video/h261", - "h263": "video/h263", - "h264": "video/h264", + "tpl": "application/vnd.groove-tool-template", + "vcg": "application/vnd.groove-vcard", "hal": "application/vnd.hal+xml", - "hbc": "application/vnd.hbci", + "zmm": "application/vnd.handheld-entertainment+xml", "hbci": "application/vnd.hbci", - "hbs": "text/x-handlebars-template", - "hdd": "application/x-virtualbox-hdd", - "hdf": "application/x-hdf", - "hdr": "image/vnd.radiance", - "hdt": "application/vnd.hdt", - "heic": "image/heic", - "heics": "image/heic-sequence", - "heif": "image/heif", - "heifs": "image/heif-sequence", - "help": "application/x-helpfile", - "hgl": "application/vnd.hp-hpgl", - "hh": "text/plain", - "hin": "chemical/x-hin", - "hjson": "application/hjson", - "hlb": "text/x-script", - "hlp": "application/winhlp", - "hpg": "application/vnd.hp-hpgl", + "les": "application/vnd.hhe.lesson-player", "hpgl": "application/vnd.hp-hpgl", - "hpi": "application/vnd.hp-hpid", "hpid": "application/vnd.hp-hpid", - "hpp": "text/x-c++hdr", "hps": "application/vnd.hp-hps", - "hpub": "application/prs.hpub+zip", - "hqx": "application/mac-binhex40", - "hs": "text/x-haskell", - "hta": "application/hta", - "htc": "text/x-component", - "htke": "application/vnd.kenameaapp", - "html": "text/html", - "htt": "text/webviewhtml", - "hvd": "application/vnd.yamaha.hv-dic", - "hvp": "application/vnd.yamaha.hv-voice", - "hvs": "application/vnd.yamaha.hv-script", - "hx": "text/haxe", - "hxml": "text/haxe", - "hxx": "text/plain", - "i2g": "application/vnd.intergeo", - "ic0": "application/vnd.commerce-battelle", - "ic1": "application/vnd.commerce-battelle", - "ic2": "application/vnd.commerce-battelle", - "ic3": "application/vnd.commerce-battelle", - "ic4": "application/vnd.commerce-battelle", - "ic5": "application/vnd.commerce-battelle", - "ic6": "application/vnd.commerce-battelle", - "ic7": "application/vnd.commerce-battelle", - "ic8": "application/vnd.commerce-battelle", - "ica": "application/vnd.commerce-battelle", + "jlt": "application/vnd.hp-jlyt", + "pcl": "application/vnd.hp-pcl", + "pclxl": "application/vnd.hp-pclxl", + "sfd-hdstx": "application/vnd.hydrostatix.sof-data", + "mpy": "application/vnd.ibm.minipay", + "afp": "application/vnd.ibm.modcap", + "listafp": "application/vnd.ibm.modcap", + "list3820": "application/vnd.ibm.modcap", + "irm": "application/vnd.ibm.rights-management", + "sc": "application/vnd.ibm.secure-container", "icc": "application/vnd.iccprofile", - "icd": "application/vnd.commerce-battelle", - "ice": "x-conference/x-cooltalk", - "icf": "application/vnd.commerce-battelle", "icm": "application/vnd.iccprofile", - "icns": "binary/icns", - "ico": "image/x-icon", - "ics": "text/calendar", - "icz": "text/calendar", - "idc": "text/plain", - "idl": "text/idl", - "ief": "image/ief", - "iefs": "image/ief", - "ifb": "text/calendar", - "ifm": "application/vnd.shana.informed.formdata", - "iges": "model/iges", "igl": "application/vnd.igloader", - "igm": "application/vnd.insors.igm", - "ign": "application/vnd.coreos.ignition+json", - "ignition": "application/vnd.coreos.ignition+json", - "igs": "model/iges", - "igx": "application/vnd.micrografx.igx", - "iif": "application/vnd.shana.informed.interchange", - "iii": "application/x-iphone", - "ima": "application/x-ima", - "imap": "application/x-httpd-imap", - "imf": "application/vnd.imagemeter.folder+zip", - "img": "application/octet-stream", - "imgcal": "application/vnd.3lightssoftware.imagescal", - "imi": "application/vnd.imagemeter.image+zip", - "imp": "application/vnd.accpac.simply.imp", - "ims": "application/vnd.ms-ims", - "imscc": "application/vnd.ims.imsccv1p1", - "in": "text/plain", - "inc": "text/inc", - "inf": "application/inf", - "info": "application/x-info", - "ini": "text/ini", - "ink": "application/inkml+xml", - "inkml": "application/inkml+xml", - "inp": "chemical/x-gamess-input", - "ins": "application/x-internet-signup", - "install": "application/x-install-instructions", - "iota": "application/vnd.astraea-software.iota", - "ip": "application/x-ip2", - "ipfix": "application/ipfix", - "ipk": "application/vnd.shana.informed.package", - "irm": "application/vnd.ibm.rights-management", - "irp": "application/vnd.irepository.package+xml", - "ism": "model/vnd.gdl", - "iso": "application/x-iso9660-image", - "isp": "application/x-internet-signup", - "ist": "chemical/x-isostar", - "istr": "chemical/x-isostar", - "isu": "video/x-isvideo", - "it": "audio/it", - "itp": "application/vnd.shana.informed.formtemplate", - "its": "application/its+xml", - "iv": "application/x-inventor", "ivp": "application/vnd.immervision-ivp", - "ivr": "i-world/i-vrml", "ivu": "application/vnd.immervision-ivu", - "ivy": "application/x-livescreen", - "j2": "text/jinja", - "jad": "text/vnd.sun.j2me.app-descriptor", - "jade": "text/jade", + "igm": "application/vnd.insors.igm", + "xpw": "application/vnd.intercon.formnet", + "xpx": "application/vnd.intercon.formnet", + "i2g": "application/vnd.intergeo", + "qbo": "application/vnd.intu.qbo", + "qfx": "application/vnd.intu.qfx", + "rcprofile": "application/vnd.ipunplugged.rcprofile", + "irp": "application/vnd.irepository.package+xml", + "xpr": "application/vnd.is-xpr", + "fcs": "application/vnd.isac.fcs", "jam": "application/vnd.jam", - "jar": "application/x-java-archive", - "jardiff": "application/x-java-archive-diff", - "java": "text/x-java-source", - "jcm": "application/x-java-commerce", - "jdx": "chemical/x-jcamp-dx", - "jenkinsfile": "text/groovy", - "jfif": "image/jpeg", - "jinja": "text/jinja", - "jinja2": "text/jinja", + "rms": "application/vnd.jcp.javame.midlet-rms", "jisp": "application/vnd.jisp", - "jls": "image/jls", - "jlt": "application/vnd.hp-jlyt", - "jl": "text/julia", - "jmz": "application/x-jmol", - "jng": "image/x-jng", - "jnlp": "application/x-java-jnlp-file", "joda": "application/vnd.joost.joda-archive", - "jp2": "image/jp2", - "jpe": "image/jpeg", - "jpeg": "image/jpeg", - "jpf": "image/jpx", - "jpg": "image/jpeg", - "jpg2": "image/jp2", - "jpgm": "image/jpm", - "jpgv": "video/jpeg", - "jpm": "image/jpm", - "jps": "image/x-jps", - "jpx": "image/jpx", - "jrd": "application/jrd+json", - "js": "application/javascript", - "json": "application/json", - "json-patch": "application/json-patch+json", - "json5": "application/json5", - "jsonld": "application/ld+json", - "jsonml": "application/jsonml+json", - "jsx": "text/jsx", - "jtd": "text/vnd.esmertec.theme-descriptor", - "jut": "image/jutvision", - "kar": "audio/midi", + "ktz": "application/vnd.kahootz", + "ktr": "application/vnd.kahootz", "karbon": "application/vnd.kde.karbon", - "kcm": "application/vnd.nervana", - "key": "application/pgp-keys", - "keynote": "application/vnd.apple.keynote", + "chrt": "application/vnd.kde.kchart", "kfo": "application/vnd.kde.kformula", - "kia": "application/vnd.kidspiration", - "kil": "application/x-killustrator", - "kin": "chemical/x-kinemage", - "kml": "application/vnd.google-earth.kml+xml", - "kmz": "application/vnd.google-earth.kmz", - "kne": "application/vnd.kinar", - "knp": "application/vnd.kinar", - "kom": "application/vnd.hbci", + "flw": "application/vnd.kde.kivio", "kon": "application/vnd.kde.kontour", - "koz": "audio/vnd.audikoz", "kpr": "application/vnd.kde.kpresenter", "kpt": "application/vnd.kde.kpresenter", - "kpxx": "application/vnd.ds-keypoint", - "ksh": "application/x-ksh", "ksp": "application/vnd.kde.kspread", - "kt": "text/kotlin", - "ktr": "application/vnd.kahootz", - "ktx": "image/ktx", - "ktz": "application/vnd.kahootz", "kwd": "application/vnd.kde.kword", "kwt": "application/vnd.kde.kword", - "l16": "audio/l16", - "la": "audio/nspaudio", - "lam": "audio/x-liveaudio", - "lasjson": "application/vnd.las.las+json", + "htke": "application/vnd.kenameaapp", + "kia": "application/vnd.kidspiration", + "kne": "application/vnd.kinar", + "knp": "application/vnd.kinar", + "skp": "application/vnd.koan", + "skd": "application/vnd.koan", + "skt": "application/vnd.koan", + "skm": "application/vnd.koan", + "sse": "application/vnd.kodak-descriptor", "lasxml": "application/vnd.las.las+xml", - "latex": "application/x-latex", - "lbc": "audio/ilbc", "lbd": "application/vnd.llamagraphics.life-balance.desktop", "lbe": "application/vnd.llamagraphics.life-balance.exchange+xml", - "le": "application/vnd.bluetooth.le.oob", - "les": "application/vnd.hhe.lesson-player", - "less": "text/less", - "lgr": "application/lgr+xml", - "lha": "application/octet-stream", - "lhs": "text/x-literate-haskell", - "lhx": "application/octet-stream", - "lin": "application/bbolin", - "link66": "application/vnd.route66.link66+xml", - "list": "text/plain", - "list3820": "application/vnd.ibm.modcap", - "listafp": "application/vnd.ibm.modcap", - "lmp": "model/vnd.gdl", - "lnk": "application/x-ms-shortcut", - "log": "text/plain", - "lostsyncxml": "application/lostsync+xml", - "lostxml": "application/lost+xml", - "lrf": "application/octet-stream", - "lrm": "application/vnd.ms-lrm", - "lsf": "video/x-la-asf", - "lsp": "text/x-script.lisp", - "lst": "text/plain", - "lsx": "video/x-la-asf", - "ltf": "application/vnd.frogans.ltf", - "ltx": "application/x-latex", - "lua": "text/x-lua", - "luac": "application/x-lua-bytecode", - "lvp": "audio/vnd.lucent.voice", + "123": "application/vnd.lotus-1-2-3", + "apr": "application/vnd.lotus-approach", + "pre": "application/vnd.lotus-freelance", + "nsf": "application/vnd.lotus-notes", + "org": "application/vnd.lotus-organizer", + "scm": "application/vnd.lotus-screencam", "lwp": "application/vnd.lotus-wordpro", - "lxf": "application/lxf", - "lyx": "application/x-lyx", - "lzh": "application/octet-stream", - "lzx": "application/x-lzx", - "m": "application/vnd.wolfram.mathematica.package", - "m13": "application/x-msmediaview", - "m14": "application/x-msmediaview", - "m15": "audio/x-mod", - "m1v": "video/mpeg", - "m21": "application/mp21", - "m2a": "audio/mpeg", - "m2v": "video/mpeg", - "m3a": "audio/mpeg", - "m3g": "application/m3g", - "m3u": "audio/x-mpegurl", - "m3u8": "application/vnd.apple.mpegurl", - "m4a": "audio/x-m4a", - "m4s": "video/iso.segment", - "m4u": "video/vnd.mpegurl", - "m4v": "video/x-m4v", - "ma": "application/mathematica", - "mads": "application/mads+xml", - "mag": "application/vnd.ecowin.chart", - "mail": "message/rfc822", - "maker": "application/vnd.framemaker", - "man": "application/x-troff-man", - "manifest": "text/cache-manifest", - "map": "application/x-navimap", - "mar": "text/plain", - "markdown": "text/markdown", - "mathml": "application/mathml+xml", - "mb": "application/mathematica", - "mbd": "application/mbedlet", - "mbk": "application/vnd.mobius.mbk", - "mbox": "application/mbox", - "mc$": "application/x-magic-cap-package-1.0", - "mc1": "application/vnd.medcalcdata", + "portpkg": "application/vnd.macports.portpkg", "mcd": "application/vnd.mcd", - "mcf": "image/vasa", - "mcif": "chemical/x-mmcif", - "mcm": "chemical/x-macmolecule", - "mcp": "application/netmc", - "mcurl": "text/vnd.curl.mcurl", - "md": "text/markdown", - "mdb": "application/x-msaccess", - "mdc": "application/vnd.marlin.drm.mdcf", - "mdi": "image/vnd.ms-modi", - "me": "application/x-troff-me", - "med": "audio/x-mod", - "mesh": "model/mesh", - "meta4": "application/metalink4+xml", - "metalink": "application/metalink+xml", - "mets": "application/mets+xml", - "mf4": "application/mf4", + "mc1": "application/vnd.medcalcdata", + "cdkey": "application/vnd.mediastation.cdkey", + "mwf": "application/vnd.mfer", "mfm": "application/vnd.mfmp", - "mft": "application/rpki-manifest", - "mgp": "application/vnd.osgeo.mapguide.package", - "mgz": "application/vnd.proteus.magazine", - "mht": "message/rfc822", - "mhtml": "message/rfc822", - "mib": "text/mib", - "mid": "audio/midi", - "midi": "audio/midi", - "mie": "application/x-mie", - "mif": "application/x-mif", - "mime": "message/rfc822", - "miz": "text/mizar", - "mj2": "video/mj2", - "mjf": "audio/x-vnd.audioexplosion.mjuicemediafile", - "mjp2": "video/mj2", - "mjpg": "video/x-motion-jpeg", - "mjs": "application/javascript", - "mk": "text/makefile", - "mk3d": "video/x-matroska-3d", - "mka": "audio/x-matroska", - "mkd": "text/x-markdown", - "mks": "video/x-matroska", - "mkv": "video/x-matroska", - "mlp": "application/vnd.dolby.mlp", - "mm": "application/x-freemind", - "mmd": "application/vnd.chipnuts.karaoke-mmd", - "mmdb": "application/vnd.maxmind.maxmind-db", - "mme": "application/base64", - "mmf": "application/vnd.smaf", - "mml": "text/mathml", - "mmod": "chemical/x-macromodel-input", - "mmr": "image/vnd.fujixerox.edmics-mmr", - "mms": "application/vnd.wap.mms-message", - "mng": "video/x-mng", - "mny": "application/x-msmoney", - "mobi": "application/x-mobipocket-ebook", - "moc": "text/x-moc", - "mod": "audio/x-mod", - "model-inter": "application/vnd.vd-study", - "mods": "application/mods+xml", - "modulemap": "text/modulemap", - "mol": "chemical/x-mdl-molfile", - "mol2": "chemical/x-mol2", - "moml": "model/vnd.moml+xml", - "moo": "chemical/x-mopac-out", - "moov": "video/quicktime", - "mop": "chemical/x-mopac-input", - "mopcrt": "chemical/x-mopac-input", - "mov": "video/quicktime", - "movie": "video/x-sgi-movie", - "mp1": "audio/mpeg", - "mp2": "audio/mpeg", - "mp21": "application/mp21", - "mp2a": "audio/mpeg", - "mp3": "audio/mp3", - "mp4": "video/mp4", - "mp4a": "audio/mp4", - "mp4s": "application/mp4", - "mp4v": "video/mp4", - "mpa": "video/mpeg", - "mpc": "application/vnd.mophun.certificate", - "mpd": "application/dash+xml", - "mpdd": "application/dashdelta", - "mpe": "video/mpeg", - "mpeg": "video/mpeg", - "mpega": "audio/mpeg", - "mpf": "text/vnd.ms-mediapackage", - "mpg": "video/mpeg", - "mpg4": "video/mp4", - "mpga": "audio/mpeg", - "mpkg": "application/vnd.apple.installer+xml", - "mpm": "application/vnd.blueice.multipass", + "flo": "application/vnd.micrografx.flo", + "igx": "application/vnd.micrografx.igx", + "mif": "application/vnd.mif", + "daf": "application/vnd.mobius.daf", + "dis": "application/vnd.mobius.dis", + "mbk": "application/vnd.mobius.mbk", + "mqy": "application/vnd.mobius.mqy", + "msl": "application/vnd.mobius.msl", + "plc": "application/vnd.mobius.plc", + "txf": "application/vnd.mobius.txf", "mpn": "application/vnd.mophun.application", + "mpc": "application/vnd.mophun.certificate", + "xul": "application/vnd.mozilla.xul+xml", + "cil": "application/vnd.ms-artgalry", + "cab": "application/vnd.ms-cab-compressed", + "xls": "application/vnd.ms-excel", + "xlm": "application/vnd.ms-excel", + "xla": "application/vnd.ms-excel", + "xlc": "application/vnd.ms-excel", + "xlt": "application/vnd.ms-excel", + "xlw": "application/vnd.ms-excel", + "xlam": "application/vnd.ms-excel.addin.macroenabled.12", + "xlsb": "application/vnd.ms-excel.sheet.binary.macroenabled.12", + "xlsm": "application/vnd.ms-excel.sheet.macroenabled.12", + "xltm": "application/vnd.ms-excel.template.macroenabled.12", + "eot": "application/vnd.ms-fontobject", + "chm": "application/vnd.ms-htmlhelp", + "ims": "application/vnd.ms-ims", + "lrm": "application/vnd.ms-lrm", + "thmx": "application/vnd.ms-officetheme", + "cat": "application/vnd.ms-pki.seccat", + "stl": "application/vnd.ms-pki.stl", + "ppt": "application/vnd.ms-powerpoint", + "pps": "application/vnd.ms-powerpoint", + "pot": "application/vnd.ms-powerpoint", + "ppam": "application/vnd.ms-powerpoint.addin.macroenabled.12", + "pptm": "application/vnd.ms-powerpoint.presentation.macroenabled.12", + "sldm": "application/vnd.ms-powerpoint.slide.macroenabled.12", + "ppsm": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", + "potm": "application/vnd.ms-powerpoint.template.macroenabled.12", "mpp": "application/vnd.ms-project", "mpt": "application/vnd.ms-project", - "mpv": "application/x-project", - "mpv2": "video/mpeg", - "mpx": "application/x-project", - "mpy": "application/vnd.ibm.minipay", - "mqy": "application/vnd.mobius.mqy", - "mrc": "application/marc", - "mrcx": "application/marcxml+xml", - "ms": "application/x-troff-ms", - "msa": "application/vnd.msa-disk-image", - "mscml": "application/mediaservercontrol+xml", - "msd": "application/vnd.fdsn.mseed", - "mseed": "application/vnd.fdsn.mseed", + "docm": "application/vnd.ms-word.document.macroenabled.12", + "dotm": "application/vnd.ms-word.template.macroenabled.12", + "wps": "application/vnd.ms-works", + "wks": "application/vnd.ms-works", + "wcm": "application/vnd.ms-works", + "wdb": "application/vnd.ms-works", + "wpl": "application/vnd.ms-wpl", + "xps": "application/vnd.ms-xpsdocument", "mseq": "application/vnd.mseq", - "msf": "application/vnd.epson.msf", - "msg": "application/vnd.ms-outlook", - "msh": "model/mesh", - "msi": "application/x-msi", - "msl": "application/vnd.mobius.msl", - "msm": "model/vnd.gdl", - "msty": "application/vnd.muvee.style", - "mtm": "audio/x-mod", - "mts": "model/vnd.mts", - "multitrack": "audio/vnd.presonus.multitrack", "mus": "application/vnd.musician", - "musd": "application/mmt-usd+xml", - "musicxml": "application/vnd.recordare.musicxml+xml", - "mv": "video/x-sgi-movie", - "mvb": "application/x-msmediaview", - "mvt": "application/vnd.mapbox-vector-tile", - "mwc": "application/vnd.dpgraph", - "mwf": "application/vnd.mfer", - "mxf": "application/mxf", - "mxi": "application/vnd.vd-study", - "mxl": "application/vnd.recordare.musicxml", - "mxmf": "audio/mobile-xmf", - "mxml": "application/xv+xml", - "mxs": "application/vnd.triscape.mxs", - "mxu": "video/vnd.mpegurl", - "my": "audio/make", - "mzz": "application/x-vnd.audioexplosion.mzz", - "n-gage": "application/vnd.nokia.n-gage.symbian.install", - "n3": "text/n3", - "nap": "image/naplps", - "naplps": "image/naplps", - "nb": "application/mathematica", - "nbp": "application/vnd.wolfram.player", - "nc": "application/x-netcdf", - "ncm": "application/vnd.nokia.configuration-message", - "ncx": "application/x-dtbncx+xml", - "ndc": "application/vnd.osa.netdeploy", - "ndjson": "application/json", - "ndl": "application/vnd.lotus-notes", - "nds": "application/vnd.nintendo.nitro.rom", - "nef": "image/x-nikon-nef", - "nfo": "text/x-nfo", - "ngdat": "application/vnd.nokia.n-gage.data", - "ngdoc": "text/ngdoc", - "nif": "image/x-niff", - "niff": "image/x-niff", + "msty": "application/vnd.muvee.style", + "taglet": "application/vnd.mynfc", + "nlu": "application/vnd.neurolanguage.nlu", "nim": "text/nim", "nimble": "text/nimble", "nimf": "text/nim", "nims": "text/nim", + "ntf": "application/vnd.nitf", "nitf": "application/vnd.nitf", - "nix": "application/x-mix-transfer", - "nlu": "application/vnd.neurolanguage.nlu", - "nml": "application/vnd.enliven", "nnd": "application/vnd.noblenet-directory", "nns": "application/vnd.noblenet-sealer", "nnw": "application/vnd.noblenet-web", - "notebook": "application/vnd.smart.notebook", - "npx": "image/vnd.net-fpx", - "nq": "application/n-quads", - "ns2": "application/vnd.lotus-notes", - "ns3": "application/vnd.lotus-notes", - "ns4": "application/vnd.lotus-notes", - "nsc": "application/x-conference", - "nsf": "application/vnd.lotus-notes", - "nsg": "application/vnd.lotus-notes", - "nsh": "application/vnd.lotus-notes", - "nt": "application/n-triples", - "ntf": "application/vnd.lotus-notes", - "numbers": "application/vnd.apple.numbers", - "nvd": "application/x-navidoc", - "nwc": "application/x-nwc", - "nws": "message/rfc822", - "nzb": "application/x-nzb", - "o": "application/x-object", - "o4a": "application/vnd.oma.drm.dcf", - "o4v": "application/vnd.oma.drm.dcf", - "oa2": "application/vnd.fujitsu.oasys2", - "oa3": "application/vnd.fujitsu.oasys3", - "oas": "application/vnd.fujitsu.oasys", - "obd": "application/x-msbinder", - "obg": "application/vnd.openblox.game-binary", - "obgx": "application/vnd.openblox.game+xml", - "obj": "application/x-tgif", - "oda": "application/oda", - "odb": "application/vnd.oasis.opendocument.database", + "ngdat": "application/vnd.nokia.n-gage.data", + "n-gage": "application/vnd.nokia.n-gage.symbian.install", + "rpst": "application/vnd.nokia.radio-preset", + "rpss": "application/vnd.nokia.radio-presets", + "edm": "application/vnd.novadigm.edm", + "edx": "application/vnd.novadigm.edx", + "ext": "application/vnd.novadigm.ext", "odc": "application/vnd.oasis.opendocument.chart", - "odd": "application/tei+xml", + "otc": "application/vnd.oasis.opendocument.chart-template", + "odb": "application/vnd.oasis.opendocument.database", "odf": "application/vnd.oasis.opendocument.formula", "odft": "application/vnd.oasis.opendocument.formula-template", "odg": "application/vnd.oasis.opendocument.graphics", - "odi": "application/vnd.oasis.opendocument.image", - "odm": "application/vnd.oasis.opendocument.text-master", - "odp": "application/vnd.oasis.opendocument.presentation", - "ods": "application/vnd.oasis.opendocument.spreadsheet", - "odt": "application/vnd.oasis.opendocument.text", - "odx": "application/odx", - "oeb": "application/vnd.openeye.oeb", - "oga": "audio/ogg", - "ogex": "model/vnd.opengex", - "ogg": "audio/ogg", - "ogv": "video/ogg", - "ogx": "application/ogg", - "old": "application/x-trash", - "omc": "application/x-omc", - "omcd": "application/x-omcdatamaker", - "omcr": "application/x-omcregerator", - "omdoc": "application/omdoc+xml", - "omg": "audio/atrac3", - "onepkg": "application/onenote", - "onetmp": "application/onenote", - "onetoc": "application/onenote", - "onetoc2": "application/onenote", - "opf": "application/oebps-package+xml", - "opml": "text/x-opml", - "oprc": "application/vnd.palm", - "opus": "audio/ogg", - "or2": "application/vnd.lotus-organizer", - "or3": "application/vnd.lotus-organizer", - "orf": "image/x-olympus-orf", - "org": "text/x-org", - "orq": "application/ocsp-request", - "ors": "application/ocsp-response", - "osf": "application/vnd.yamaha.openscoreformat", - "osfpvg": "application/vnd.yamaha.openscoreformat.osfpvg+xml", - "osm": "application/vnd.openstreetmap.data+xml", - "otc": "application/vnd.oasis.opendocument.chart-template", - "otf": "font/otf", "otg": "application/vnd.oasis.opendocument.graphics-template", - "oth": "application/vnd.oasis.opendocument.text-web", + "odi": "application/vnd.oasis.opendocument.image", "oti": "application/vnd.oasis.opendocument.image-template", + "odp": "application/vnd.oasis.opendocument.presentation", "otp": "application/vnd.oasis.opendocument.presentation-template", + "ods": "application/vnd.oasis.opendocument.spreadsheet", "ots": "application/vnd.oasis.opendocument.spreadsheet-template", + "odt": "application/vnd.oasis.opendocument.text", + "odm": "application/vnd.oasis.opendocument.text-master", "ott": "application/vnd.oasis.opendocument.text-template", - "ova": "application/x-virtualbox-ova", - "ovf": "application/x-virtualbox-ovf", - "owx": "application/owl+xml", - "oxlicg": "application/vnd.oxli.countgraph", - "oxps": "application/oxps", + "oth": "application/vnd.oasis.opendocument.text-web", + "xo": "application/vnd.olpc-sugar", + "dd2": "application/vnd.oma.dd2+xml", "oxt": "application/vnd.openofficeorg.extension", - "oza": "application/x-oz-application", - "p": "text/x-pascal", - "p10": "application/pkcs10", - "p12": "application/pkcs12", - "p2p": "application/vnd.wfa.p2p", - "p7a": "application/x-pkcs7-signature", - "p7b": "application/x-pkcs7-certificates", - "p7c": "application/pkcs7-mime", - "p7m": "application/pkcs7-mime", - "p7r": "application/x-pkcs7-certreqresp", - "p7s": "application/pkcs7-signature", - "p8": "application/pkcs8", - "pac": "application/x-ns-proxy-autoconfig", - "pack": "application/x-java-pack200", - "package": "application/vnd.autopackage", - "pages": "application/vnd.apple.pages", - "par": "text/plain-bas", - "part": "application/pro_eng", - "pas": "text/pascal", - "pat": "image/x-coreldrawpattern", - "patch": "text/x-diff", - "paw": "application/vnd.pawaafile", - "pbd": "application/vnd.powerbuilder6", - "pbm": "image/x-portable-bitmap", - "pcap": "application/vnd.tcpdump.pcap", - "pcf": "application/x-font-pcf", - "pcl": "application/vnd.hp-pcl", - "pclxl": "application/vnd.hp-pclxl", - "pct": "image/x-pict", - "pcurl": "application/vnd.curl.pcurl", - "pcx": "image/x-pcx", - "pdb": "application/vnd.palm", - "pde": "text/x-processing", - "pdf": "application/pdf", - "pdx": "application/pdx", - "pem": "text/pem", - "pfa": "application/x-font-type1", - "pfb": "application/x-font-type1", - "pfm": "application/x-font-type1", - "pfr": "application/font-tdpfr", - "pfunk": "audio/make", - "pfx": "application/pkcs12", - "pgb": "image/vnd.globalgraphics.pgb", - "pgm": "image/x-portable-graymap", - "pgn": "application/x-chess-pgn", - "pgp": "application/pgp-encrypted", - "php": "application/x-httpd-php", - "php3": "application/x-httpd-php3", - "php3p": "application/x-httpd-php3-preprocessed", - "php4": "application/x-httpd-php4", - "php5": "application/x-httpd-php5", - "phps": "application/x-httpd-php-source", - "pht": "application/x-httpd-php", - "phtml": "application/x-httpd-php", - "pic": "image/pict", - "pict": "image/pict", - "pil": "application/vnd.piaccess.application-license", - "pk": "application/x-tex-pk", - "pkd": "application/vnd.hbci", - "pkg": "application/vnd.apple.installer+xml", - "pki": "application/pkixcmp", - "pkipath": "application/pkix-pkipath", - "pko": "application/ynd.ms-pkipko", - "pkpass": "application/vnd.apple.pkpass", - "pl": "application/x-perl", - "plantuml": "text/plantuml", - "plb": "application/vnd.3gpp.pic-bw-large", - "plc": "application/vnd.mobius.plc", - "plf": "application/vnd.pocketlearn", - "plj": "audio/vnd.everad.plj", - "plp": "application/vnd.panoply", - "pls": "application/pls+xml", - "plx": "application/x-pixclscript", - "ply": "model/stanford", - "pm": "text/plain", - "pm4": "application/x-pagemaker", - "pm5": "application/x-pagemaker", - "pma": "application/x-perfmon", - "pmc": "application/x-perfmon", - "pml": "application/vnd.ctc-posml", - "pmr": "application/x-perfmon", - "pmw": "application/x-perfmon", - "png": "image/png", - "pnm": "image/x-portable-anymap", - "po": "text/pofile", - "pod": "text/x-pod", - "portpkg": "application/vnd.macports.portpkg", - "pot": "application/vnd.ms-powerpoint", - "potm": "application/vnd.ms-powerpoint.template.macroenabled.12", - "potx": "application/vnd.openxmlformats-officedocument.presentationml.template", - "pov": "model/x-pov", - "pp": "text/puppet", - "ppa": "application/vnd.ms-powerpoint", - "ppam": "application/vnd.ms-powerpoint.addin.macroenabled.12", - "ppd": "application/vnd.cups-ppd", - "ppkg": "application/vnd.xmpie.ppkg", - "ppm": "image/x-portable-pixmap", - "pps": "application/vnd.ms-powerpoint", - "ppsm": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", - "ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", - "ppt": "application/vnd.ms-powerpoint", - "pptm": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "ppz": "application/mspowerpoint", + "sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide", + "ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", + "potx": "application/vnd.openxmlformats-officedocument.presentationml.template", + "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + "mgp": "application/vnd.osgeo.mapguide.package", + "dp": "application/vnd.osgi.dp", + "esa": "application/vnd.osgi.subsystem", + "pdb": "application/vnd.palm", "pqa": "application/vnd.palm", - "prc": "application/vnd.palm", - "pre": "application/vnd.lotus-freelance", - "preminet": "application/vnd.preminet", - "prf": "application/pics-rules", - "proto": "text/proto", - "provn": "text/provenance-notation", - "provx": "application/provenance+xml", - "prt": "application/pro_eng", - "prz": "application/vnd.lotus-freelance", - "ps": "application/postscript", - "psb": "application/vnd.3gpp.pic-bw-small", - "psd": "image/vnd.adobe.photoshop", - "pseg3820": "application/vnd.ibm.modcap", - "psf": "application/x-font-linux-psf", - "psid": "audio/prs.sid", - "pskcxml": "application/pskc+xml", - "pti": "image/prs.pti", - "ptid": "application/vnd.pvi.ptid1", - "pub": "application/x-mspublisher", - "purs": "text/purescript", - "pvb": "application/vnd.3gpp.pic-bw-var", - "pvu": "paleovu/x-pv", - "pwn": "application/vnd.3m.post-it-notes", - "pwz": "application/vnd.ms-powerpoint", - "pxd": "text/cython", - "pxi": "text/cython", - "py": "text/x-script.phyton", - "pya": "audio/vnd.ms-playready.media.pya", - "pyc": "application/x-python-code", - "pyi": "text/pyi", - "pyo": "application/x-python-code", - "pyv": "video/vnd.ms-playready.media.pyv", - "pyx": "text/cython", - "qam": "application/vnd.epson.quickanime", - "qbo": "application/vnd.intu.qbo", - "qca": "application/vnd.ericsson.quickcall", - "qcall": "application/vnd.ericsson.quickcall", - "qcp": "audio/qcelp", - "qd3": "x-world/x-3dmf", - "qd3d": "x-world/x-3dmf", - "qfx": "application/vnd.intu.qfx", - "qgs": "application/x-qgis", - "qif": "image/x-quicktime", + "oprc": "application/vnd.palm", + "paw": "application/vnd.pawaafile", + "str": "application/vnd.pg.format", + "ei6": "application/vnd.pg.osasli", + "efif": "application/vnd.picsel", + "wg": "application/vnd.pmi.widget", + "plf": "application/vnd.pocketlearn", + "pbd": "application/vnd.powerbuilder6", + "box": "application/vnd.previewsystems.box", + "mgz": "application/vnd.proteus.magazine", "qps": "application/vnd.publishare-delta-tree", - "qt": "video/quicktime", - "qtc": "video/x-qtc", - "qti": "image/x-quicktime", - "qtif": "image/x-quicktime", - "qtl": "application/x-quicktimeplayer", - "quiz": "application/vnd.quobject-quoxdocument", - "quox": "application/vnd.quobject-quoxdocument", - "qvd": "application/vnd.theqvd", + "ptid": "application/vnd.pvi.ptid1", + "qxd": "application/vnd.quark.quarkxpress", + "qxt": "application/vnd.quark.quarkxpress", "qwd": "application/vnd.quark.quarkxpress", "qwt": "application/vnd.quark.quarkxpress", - "qxb": "application/vnd.quark.quarkxpress", - "qxd": "application/vnd.quark.quarkxpress", "qxl": "application/vnd.quark.quarkxpress", - "qxt": "application/vnd.quark.quarkxpress", - "r": "text/r", - "ra": "audio/x-realaudio", - "ram": "audio/x-pn-realaudio", - "raml": "application/raml+yaml", - "rapd": "application/route-apd+xml", - "rar": "application/x-rar-compressed", - "ras": "image/x-cmu-raster", - "rast": "image/cmu-raster", - "rb": "application/x-ruby", - "rcprofile": "application/vnd.ipunplugged.rcprofile", - "rct": "application/prs.nprend", - "rd": "chemical/x-mdl-rdfile", - "rda": "text/r", - "rdata": "text/r", - "rds": "text/r", - "rdf": "application/rdf+xml", - "rdf-crypt": "application/prs.rdf-xml-crypt", - "rdz": "application/vnd.data-vision.rdz", - "relo": "application/p2p-overlay+xml", - "rep": "application/vnd.businessobjects", - "request": "application/vnd.nervana", - "res": "application/x-dtbresource+xml", - "rexx": "text/x-script.rexx", - "rf": "image/vnd.rn-realflash", - "rfcxml": "application/rfc+xml", - "rgb": "image/x-rgb", - "rgbe": "image/vnd.radiance", - "rhtml": "application/x-httpd-eruby", - "rif": "application/reginfo+xml", - "rip": "audio/vnd.rip", - "ris": "application/x-research-info-systems", - "rl": "application/resource-lists+xml", - "rlc": "image/vnd.fujixerox.edmics-rlc", - "rld": "application/resource-lists-diff+xml", - "rlib": "text/rust", + "qxb": "application/vnd.quark.quarkxpress", + "bed": "application/vnd.realvnc.bed", + "mxl": "application/vnd.recordare.musicxml", + "musicxml": "application/vnd.recordare.musicxml+xml", + "cryptonote": "application/vnd.rig.cryptonote", + "cod": "application/vnd.rim.cod", "rm": "application/vnd.rn-realmedia", - "rmi": "audio/mid", - "rmm": "audio/x-pn-realaudio", - "rmp": "audio/x-pn-realaudio-plugin", - "rms": "application/vnd.jcp.javame.midlet-rms", "rmvb": "application/vnd.rn-realmedia-vbr", - "rnc": "application/relax-ng-compact-syntax", - "rnd": "application/prs.nprend", - "rng": "text/xml", - "rnx": "application/vnd.rn-realplayer", - "roa": "application/rpki-roa", - "roff": "text/troff", - "ros": "chemical/x-rosdal", - "rp": "image/vnd.rn-realpix", - "rp9": "application/vnd.cloanto.rp9", - "rpm": "application/x-redhat-package-manager", - "rpss": "application/vnd.nokia.radio-presets", - "rpst": "application/vnd.nokia.radio-preset", - "rq": "application/sparql-query", - "rs": "application/rls-services+xml", - "rsd": "application/rsd+xml", - "rsheet": "application/urc-ressheet+xml", - "rsm": "model/vnd.gdl", - "rss": "application/rss+xml", - "rst": "text/prs.fallenstein.rst", - "rt": "text/richtext", - "rtf": "text/rtf", - "rtx": "text/richtext", - "run": "application/x-makeself", - "rusd": "application/route-usd+xml", - "rv": "video/vnd.rn-realvideo", - "rxn": "chemical/x-mdl-rxnfile", - "s": "text/x-asm", - "s11": "video/vnd.sealed.mpeg1", - "s14": "video/vnd.sealed.mpeg4", - "s1a": "application/vnd.sealedmedia.softseal.pdf", - "s1e": "application/vnd.sealed.xls", - "s1g": "image/vnd.sealedmedia.softseal.gif", - "s1h": "application/vnd.sealedmedia.softseal.html", - "s1j": "image/vnd.sealedmedia.softseal.jpg", - "s1m": "audio/vnd.sealedmedia.softseal.mpeg", - "s1n": "image/vnd.sealed.png", - "s1p": "application/vnd.sealed.ppt", - "s1q": "video/vnd.sealedmedia.softseal.mov", - "s1w": "application/vnd.sealed.doc", - "s3df": "application/vnd.sealed.3df", - "s3m": "audio/s3m", - "sac": "application/tamp-sequence-adjust-confirm", - "saf": "application/vnd.yamaha.smaf-audio", - "sam": "application/vnd.lotus-wordpro", - "sandboxed": "text/html-sandboxed", - "sass": "text/x-sass", - "saveme": "application/octet-stream", - "sbk": "application/x-tbook", - "sbml": "application/sbml+xml", - "sc": "application/vnd.ibm.secure-container", - "scala": "text/x-scala", - "scd": "application/x-msschedule", - "sce": "application/vnd.etsi.asic-e+zip", - "scim": "application/scim+json", - "scld": "application/vnd.doremir.scorecloud-binary-document", - "scm": "application/vnd.lotus-screencam", - "scq": "application/scvp-cv-request", - "scr": "application/x-silverlight", - "scs": "application/scvp-cv-response", - "scsf": "application/vnd.sealed.csf", - "scss": "text/x-scss", - "sct": "text/scriptlet", - "scurl": "text/vnd.curl.scurl", - "sd": "chemical/x-mdl-sdfile", - "sd2": "audio/x-sd2", - "sda": "application/vnd.stardivision.draw", - "sdc": "application/vnd.stardivision.calc", - "sdd": "application/vnd.stardivision.impress", - "sdf": "application/vnd.kinar", - "sdkd": "application/vnd.solent.sdkm+xml", - "sdkm": "application/vnd.solent.sdkm+xml", - "sdml": "text/plain", - "sdo": "application/vnd.sealed.doc", - "sdoc": "application/vnd.sealed.doc", - "sdp": "application/sdp", - "sdr": "application/sounder", - "sdw": "application/vnd.stardivision.writer", - "sea": "application/x-sea", + "link66": "application/vnd.route66.link66+xml", + "st": "application/vnd.sailingtracker.track", "see": "application/vnd.seemail", - "seed": "application/vnd.fdsn.seed", - "sem": "application/vnd.sealed.eml", "sema": "application/vnd.sema", "semd": "application/vnd.semd", "semf": "application/vnd.semf", - "seml": "application/vnd.sealed.eml", - "ser": "application/java-serialized-object", - "set": "application/set", - "setpay": "application/set-payment-initiation", - "setreg": "application/set-registration-initiation", - "sfc": "application/vnd.nintendo.snes.rom", - "sfd": "application/vnd.font-fontforge-sfd", - "sfd-hdstx": "application/vnd.hydrostatix.sof-data", + "ifm": "application/vnd.shana.informed.formdata", + "itp": "application/vnd.shana.informed.formtemplate", + "iif": "application/vnd.shana.informed.interchange", + "ipk": "application/vnd.shana.informed.package", + "twd": "application/vnd.simtech-mindmapper", + "twds": "application/vnd.simtech-mindmapper", + "mmf": "application/vnd.smaf", + "teacher": "application/vnd.smart.teacher", + "sdkm": "application/vnd.solent.sdkm+xml", + "sdkd": "application/vnd.solent.sdkm+xml", + "dxp": "application/vnd.spotfire.dxp", "sfs": "application/vnd.spotfire.sfs", - "sfv": "text/x-sfv", - "sgf": "application/x-go-sgf", - "sgi": "image/sgi", - "sgif": "image/vnd.sealedmedia.softseal.gif", - "sgl": "application/vnd.stardivision.writer-global", - "sgm": "text/sgml", - "sgml": "text/sgml", - "sh": "application/x-sh", - "shar": "application/x-shar", - "shex": "text/shex", - "shf": "application/shf+xml", - "shp": "application/x-qgis", - "shx": "application/x-qgis", - "si": "text/vnd.wap.si", - "sic": "application/vnd.wap.sic", - "sid": "image/x-mrsid-image", - "sieve": "application/sieve", - "sig": "application/pgp-signature", - "sik": "application/x-trash", - "sil": "audio/silk", - "silo": "model/mesh", - "sis": "application/vnd.symbian.install", - "sisx": "x-epoc/x-sisx-app", - "sit": "application/x-stuffit", - "sitx": "application/x-stuffitx", - "siv": "application/sieve", - "sjp": "image/vnd.sealedmedia.softseal.jpg", - "sjpg": "image/vnd.sealedmedia.softseal.jpg", - "skd": "application/vnd.koan", - "skm": "application/vnd.koan", - "skp": "application/vnd.koan", - "skt": "application/vnd.koan", - "sl": "text/vnd.wap.sl", - "sla": "application/vnd.scribus", - "slaz": "application/vnd.scribus", - "slc": "application/vnd.wap.slc", - "sldm": "application/vnd.ms-powerpoint.slide.macroenabled.12", - "sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide", - "sls": "application/route-s-tsid+xml", - "slt": "application/vnd.epson.salt", - "sm": "application/vnd.stepmania.stepchart", - "smc": "application/vnd.nintendo.snes.rom", + "sdc": "application/vnd.stardivision.calc", + "sda": "application/vnd.stardivision.draw", + "sdd": "application/vnd.stardivision.impress", "smf": "application/vnd.stardivision.math", - "smh": "application/vnd.sealed.mht", - "smht": "application/vnd.sealed.mht", - "smi": "application/smil+xml", - "smil": "application/smil+xml", - "smk": "video/vnd.radgamettools.smacker", - "sml": "application/smil+xml", - "smo": "video/vnd.sealedmedia.softseal.mov", - "smov": "video/vnd.sealedmedia.softseal.mov", - "smp": "audio/vnd.sealedmedia.softseal.mpeg", - "smp3": "audio/vnd.sealedmedia.softseal.mpeg", - "smpg": "video/vnd.sealed.mpeg1", - "sms": "application/vnd.3gpp2.sms", - "smv": "video/x-smv", + "sdw": "application/vnd.stardivision.writer", + "vor": "application/vnd.stardivision.writer", + "sgl": "application/vnd.stardivision.writer-global", "smzip": "application/vnd.stepmania.package", - "snd": "audio/basic", - "snf": "application/x-font-snf", - "so": "application/octet-stream", - "soa": "text/dns", - "soc": "application/sgml-open-catalog", - "sol": "application/solids", - "spc": "text/x-speech", - "spd": "application/vnd.sealedmedia.softseal.pdf", - "spdf": "application/vnd.sealedmedia.softseal.pdf", - "spec": "text/spec", - "spf": "application/vnd.yamaha.smaf-phrase", - "spl": "application/x-futuresplash", - "spn": "image/vnd.sealed.png", - "spng": "image/vnd.sealed.png", - "spo": "text/vnd.in3d.spot", - "spot": "text/vnd.in3d.spot", - "spp": "application/scvp-vp-response", - "sppt": "application/vnd.sealed.ppt", - "spq": "application/scvp-vp-request", - "spr": "application/x-sprite", - "sprite": "application/x-sprite", - "spx": "audio/ogg", - "sql": "application/x-sql", - "sr": "application/vnd.sigrok.session", - "src": "application/x-wais-source", - "srt": "application/x-subrip", - "sru": "application/sru+xml", - "srx": "application/sparql-results+xml", - "ssdl": "application/ssdl+xml", - "sse": "application/vnd.kodak-descriptor", - "ssf": "application/vnd.epson.ssf", - "ssi": "text/x-server-parsed-html", - "ssm": "application/streamingmedia", - "ssml": "application/ssml+xml", - "sst": "application/vnd.ms-pki.certstore", - "ssw": "video/vnd.sealed.swf", - "sswf": "video/vnd.sealed.swf", - "st": "application/vnd.sailingtracker.track", + "sm": "application/vnd.stepmania.stepchart", + "sxc": "application/vnd.sun.xml.calc", "stc": "application/vnd.sun.xml.calc.template", + "sxd": "application/vnd.sun.xml.draw", "std": "application/vnd.sun.xml.draw.template", - "step": "application/step", - "stf": "application/vnd.wt.stf", + "sxi": "application/vnd.sun.xml.impress", "sti": "application/vnd.sun.xml.impress.template", - "stif": "application/vnd.sealed.tiff", - "stk": "application/hyperstudio", - "stl": "application/vnd.ms-pki.stl", - "stm": "audio/x-stm", - "stml": "application/vnd.sealedmedia.softseal.html", - "stp": "application/step", - "str": "application/vnd.pg.format", - "study-inter": "application/vnd.vd-study", + "sxm": "application/vnd.sun.xml.math", + "sxw": "application/vnd.sun.xml.writer", + "sxg": "application/vnd.sun.xml.writer.global", "stw": "application/vnd.sun.xml.writer.template", - "sty": "text/x-tex", - "styl": "text/stylus", - "sub": "text/vnd.dvb.subtitle", "sus": "application/vnd.sus-calendar", "susp": "application/vnd.sus-calendar", - "sv4cpio": "application/x-sv4cpio", - "sv4crc": "application/x-sv4crc", - "svc": "application/vnd.dvb.service", "svd": "application/vnd.svd", - "svf": "image/x-dwg", - "svg": "image/svg+xml", - "svgz": "image/svg+xml", - "sw": "chemical/x-swissprot", - "swa": "application/x-director", - "swf": "application/x-shockwave-flash", - "swfl": "application/x-shockwave-flash", - "swi": "application/vnd.aristanetworks.swi", - "swift": "text/swift", - "swiftdeps": "text/swiftdeps", - "sxc": "application/vnd.sun.xml.calc", - "sxd": "application/vnd.sun.xml.draw", - "sxg": "application/vnd.sun.xml.writer.global", - "sxi": "application/vnd.sun.xml.impress", - "sxl": "application/vnd.sealed.xls", - "sxls": "application/vnd.sealed.xls", - "sxm": "application/vnd.sun.xml.math", - "sxw": "application/vnd.sun.xml.writer", - "t": "text/troff", - "t3": "application/x-t3vm-image", - "t38": "image/t38", - "tac": "text/twisted", - "tag": "text/prs.lines.tag", - "taglet": "application/vnd.mynfc", - "talk": "text/x-speech", - "tam": "application/vnd.onepager", - "tamp": "application/vnd.onepagertamp", - "tamx": "application/vnd.onepagertamx", + "sis": "application/vnd.symbian.install", + "sisx": "application/vnd.symbian.install", + "xsm": "application/vnd.syncml+xml", + "bdm": "application/vnd.syncml.dm+wbxml", + "xdm": "application/vnd.syncml.dm+xml", "tao": "application/vnd.tao.intent-module-archive", - "tap": "image/vnd.tencent.tap", - "tar": "application/x-tar", - "tat": "application/vnd.onepagertat", - "tatp": "application/vnd.onepagertatp", - "tatx": "application/vnd.onepagertatx", - "tau": "application/tamp-apex-update", - "taz": "application/x-gtar", - "tbk": "application/toolbook", - "tcap": "application/vnd.3gpp2.tcap", - "tcl": "application/x-tcl", - "tcsh": "text/x-script.tcsh", - "tcu": "application/tamp-community-update", - "td": "application/urc-targetdesc+xml", - "teacher": "application/vnd.smart.teacher", - "tei": "application/tei+xml", - "teicorpus": "application/tei+xml", - "ter": "application/tamp-error", - "tex": "application/x-tex", - "texi": "application/x-texinfo", - "texinfo": "application/x-texinfo", - "text": "text/plain", - "tf": "text/terraform", - "tfi": "application/thraud+xml", - "tfm": "application/x-tex-tfm", - "tfx": "image/tiff-fx", - "tga": "image/x-tga", - "tgf": "chemical/x-mdl-tgf", - "tgz": "application/gzip", - "thmx": "application/vnd.ms-officetheme", - "thrift": "text/thrift", - "tif": "image/tiff", - "tiff": "image/tiff", - "tk": "text/x-tcl", - "tlclient": "application/vnd.cendio.thinlinc.clientconf", - "tm": "text/texmacs", + "pcap": "application/vnd.tcpdump.pcap", + "cap": "application/vnd.tcpdump.pcap", + "dmp": "application/vnd.tcpdump.pcap", "tmo": "application/vnd.tmobile-livetv", - "tnef": "application/vnd.ms-tnef", - "tnf": "application/vnd.ms-tnef", - "toml": "text/toml", - "torrent": "application/x-bittorrent", - "tpl": "application/vnd.groove-tool-template", "tpt": "application/vnd.trid.tpt", - "tr": "text/troff", + "mxs": "application/vnd.triscape.mxs", "tra": "application/vnd.trueapp", - "tree": "application/vnd.rainstor.data", - "trig": "application/trig", - "trm": "application/x-msterminal", - "ts": "video/mp2t", - "tsa": "application/tamp-sequence-adjust", - "tscn": "text/godot", - "tsd": "application/timestamped-data", - "tsi": "audio/tsp-audio", - "tsp": "audio/tsplayer", - "tsq": "application/timestamp-query", - "tsr": "application/timestamp-reply", - "tst": "application/vnd.etsi.timestamp-token", - "tsv": "text/tab-separated-values", - "tsx": "text/tsx", - "ttc": "font/collection", - "ttf": "font/ttf", - "ttl": "text/turtle", - "ttml": "application/ttml+xml", - "tuc": "application/tamp-update-confirm", - "tur": "application/tamp-update", - "turbot": "image/florian", - "twd": "application/vnd.simtech-mindmapper", - "twds": "application/vnd.simtech-mindmapper", - "txd": "application/vnd.genomatix.tuxedo", - "txf": "application/vnd.mobius.txf", - "txt": "text/plain", - "u32": "application/x-authorware-bin", - "u8dsn": "message/global-delivery-status", - "u8hdr": "message/global-headers", - "u8mdn": "message/global-disposition-notification", - "u8msg": "message/global", - "udeb": "application/vnd.debian.binary-package", "ufd": "application/vnd.ufdl", "ufdl": "application/vnd.ufdl", - "uil": "text/x-uil", - "uis": "application/urc-uisocketdesc+xml", - "uls": "text/iuls", - "ult": "audio/x-mod", - "ulx": "application/x-glulx", + "utz": "application/vnd.uiq.theme", "umj": "application/vnd.umajin", - "uni": "audio/x-mod", - "unis": "text/uri-list", "unityweb": "application/vnd.unity", - "unv": "application/i-deas", - "uo": "application/vnd.uoml+xml", "uoml": "application/vnd.uoml+xml", - "upa": "application/vnd.hbci", - "uri": "text/uri-list", - "uric": "text/vnd.si.uricatalogue", - "urim": "application/vnd.uri-map", - "urimap": "application/vnd.uri-map", - "uris": "text/uri-list", - "urls": "text/uri-list", - "ustar": "application/x-ustar", - "utz": "application/vnd.uiq.theme", - "uu": "text/x-uuencode", - "uue": "text/x-uuencode", - "uva": "audio/vnd.dece.audio", - "uvd": "application/vnd.dece.data", - "uvf": "application/vnd.dece.data", - "uvg": "image/vnd.dece.graphic", - "uvh": "video/vnd.dece.hd", - "uvi": "image/vnd.dece.graphic", - "uvm": "video/vnd.dece.mobile", - "uvp": "video/vnd.dece.pd", - "uvs": "video/vnd.dece.sd", - "uvt": "application/vnd.dece.ttml+xml", - "uvu": "video/vnd.dece.mp4", - "uvv": "video/vnd.dece.video", - "uvva": "audio/vnd.dece.audio", - "uvvd": "application/vnd.dece.data", - "uvvf": "application/vnd.dece.data", - "uvvg": "image/vnd.dece.graphic", - "uvvh": "video/vnd.dece.hd", - "uvvi": "image/vnd.dece.graphic", - "uvvm": "video/vnd.dece.mobile", - "uvvp": "video/vnd.dece.pd", - "uvvs": "video/vnd.dece.sd", - "uvvt": "application/vnd.dece.ttml+xml", - "uvvu": "video/vnd.dece.mp4", - "uvvv": "video/vnd.dece.video", - "uvvx": "application/vnd.dece.unspecified", - "uvvz": "application/vnd.dece.zip", - "uvx": "application/vnd.dece.unspecified", - "uvz": "application/vnd.dece.zip", - "val": "chemical/x-ncbi-asn1-binary", - "vbk": "audio/vnd.nortel.vbk", - "vbox": "application/x-virtualbox-vbox", - "vbox-extpack": "application/x-virtualbox-vbox-extpack", - "vcard": "text/vcard", - "vcd": "application/x-cdlink", - "vcf": "text/x-vcard", - "vcg": "application/vnd.groove-vcard", - "vcs": "text/x-vcalendar", "vcx": "application/vnd.vcx", - "vda": "application/vda", - "vdi": "application/x-virtualbox-vdi", - "vdo": "video/vdo", - "vdx": "text/vdx", - "vew": "application/vnd.lotus-approach", - "vfr": "application/vnd.tml", - "vhd": "application/x-virtualbox-vhd", - "viaframe": "application/vnd.tml", - "vim": "text/vim", - "vis": "application/vnd.visionary", - "viv": "video/vnd.vivo", - "vivo": "video/vivo", - "vmd": "application/vocaltec-media-desc", - "vmdk": "application/x-virtualbox-vmdk", - "vmf": "application/vocaltec-media-file", - "vms": "chemical/x-vamas-iso14976", - "vmt": "application/vnd.valve.source.material", - "vob": "video/x-ms-vob", - "voc": "audio/voc", - "vor": "application/vnd.stardivision.writer", - "vos": "video/vosaic", - "vox": "audio/voxware", - "vpm": "multipart/voice-message", - "vqe": "audio/x-twinvq-plugin", - "vqf": "audio/x-twinvq", - "vql": "audio/x-twinvq-plugin", - "vrm": "x-world/x-vrml", - "vrml": "model/vrml", - "vrt": "x-world/x-vrt", - "vsc": "application/vnd.vidsoft.vidconference", "vsd": "application/vnd.visio", - "vsf": "application/vnd.vsf", - "vss": "application/vnd.visio", "vst": "application/vnd.visio", + "vss": "application/vnd.visio", "vsw": "application/vnd.visio", - "vtf": "image/vnd.valve.source.texture", - "vtt": "text/vtt", - "vtu": "model/vnd.vtu", - "vue": "text/vue", - "vwx": "application/vnd.vectorworks", - "vxml": "application/voicexml+xml", - "w3d": "application/x-director", - "w60": "application/wordperfect6.0", - "w61": "application/wordperfect6.1", - "w6w": "application/msword", - "wad": "application/x-doom", - "wadl": "application/vnd.sun.wadl+xml", - "war": "binary/zip", - "wasm": "application/wasm", - "wav": "audio/wave", - "wax": "audio/x-ms-wax", - "wb1": "application/x-qpro", - "wbmp": "image/vnd.wap.wbmp", - "wbs": "application/vnd.criticaltools.wbs+xml", + "vis": "application/vnd.visionary", + "vsf": "application/vnd.vsf", "wbxml": "application/vnd.wap.wbxml", - "wcm": "application/vnd.ms-works", - "wdb": "application/vnd.ms-works", - "wdp": "image/vnd.ms-photo", - "web": "application/vnd.xara", - "weba": "audio/webm", - "webapp": "application/x-web-app-manifest+json", - "webm": "video/webm", - "webmanifest": "application/manifest+json", - "webp": "image/webp", - "wg": "application/vnd.pmi.widget", - "wgt": "application/widget", - "whl": "binary/wheel", - "wif": "application/watcherinfo+xml", - "win": "model/vnd.gdl", - "wiz": "application/msword", - "wk": "application/x-123", - "wk1": "application/vnd.lotus-1-2-3", - "wk3": "application/vnd.lotus-1-2-3", - "wk4": "application/vnd.lotus-1-2-3", - "wks": "application/vnd.ms-works", - "wkt": "text/wkt", - "wlnk": "application/link-format", - "wm": "video/x-ms-wm", - "wma": "audio/x-ms-wma", - "wmc": "application/vnd.wmc", - "wmd": "application/x-ms-wmd", - "wmf": "image/wmf", - "wml": "text/vnd.wap.wml", "wmlc": "application/vnd.wap.wmlc", - "wmls": "text/vnd.wap.wmlscript", "wmlsc": "application/vnd.wap.wmlscriptc", - "wmv": "video/x-ms-wmv", - "wmx": "video/x-ms-wmx", - "wmz": "application/x-ms-wmz", - "woff": "font/woff", - "woff2": "font/woff2", - "word": "application/msword", - "wp": "application/wordperfect", - "wp5": "application/wordperfect", - "wp6": "application/wordperfect", + "wtb": "application/vnd.webturbo", + "nbp": "application/vnd.wolfram.player", "wpd": "application/vnd.wordperfect", - "wpl": "application/vnd.ms-wpl", - "wps": "application/vnd.ms-works", - "wq1": "application/x-lotus", "wqd": "application/vnd.wqd", - "wri": "application/x-mswrite", - "wrl": "model/vrml", - "wrz": "model/vrml", - "wsc": "message/vnd.wfa.wsc", + "stf": "application/vnd.wt.stf", + "xar": "application/vnd.xara", + "xfdl": "application/vnd.xfdl", + "hvd": "application/vnd.yamaha.hv-dic", + "hvs": "application/vnd.yamaha.hv-script", + "hvp": "application/vnd.yamaha.hv-voice", + "osf": "application/vnd.yamaha.openscoreformat", + "osfpvg": "application/vnd.yamaha.openscoreformat.osfpvg+xml", + "saf": "application/vnd.yamaha.smaf-audio", + "spf": "application/vnd.yamaha.smaf-phrase", + "cmp": "application/vnd.yellowriver-custom-menu", + "zir": "application/vnd.zul", + "zirz": "application/vnd.zul", + "zaz": "application/vnd.zzazz.deck+xml", + "vxml": "application/voicexml+xml", + "wasm": "application/wasm", + "wgt": "application/widget", + "hlp": "application/winhlp", "wsdl": "application/wsdl+xml", - "wsgi": "text/wsgi", "wspolicy": "application/wspolicy+xml", - "wsrc": "application/x-wais-source", - "wtb": "application/vnd.webturbo", - "wtk": "application/x-wintalk", - "wv": "application/vnd.wv.csp+wbxml", - "wvx": "video/x-ms-wvx", - "wz": "application/x-wingz", - "x-png": "image/png", + "7z": "application/x-7z-compressed", + "abw": "application/x-abiword", + "ace": "application/x-ace-compressed", + "dmg": "application/x-apple-diskimage", + "aab": "application/x-authorware-bin", "x32": "application/x-authorware-bin", - "x3d": "application/vnd.hzn-3d-crossword", - "x3db": "model/x3d+xml", - "x3dbz": "model/x3d+binary", - "x3dv": "model/x3d-vrml", - "x3dvz": "model/x3d-vrml", - "x3dz": "model/x3d+xml", - "x_b": "model/vnd.parasolid.transmit.binary", - "x_t": "model/vnd.parasolid.transmit.text", - "xaf": "x-world/x-vrml", - "xaml": "application/xaml+xml", - "xap": "application/x-silverlight-app", - "xar": "application/vnd.xara", - "xav": "application/xcap-att+xml", + "u32": "application/x-authorware-bin", + "vox": "application/x-authorware-bin", + "aam": "application/x-authorware-map", + "aas": "application/x-authorware-seg", + "bcpio": "application/x-bcpio", + "torrent": "application/x-bittorrent", + "blb": "application/x-blorb", + "blorb": "application/x-blorb", + "bz": "application/x-bzip", + "bz2": "application/x-bzip2", + "boz": "application/x-bzip2", + "cbr": "application/x-cbr", + "cba": "application/x-cbr", + "cbt": "application/x-cbr", + "cbz": "application/x-cbr", + "cb7": "application/x-cbr", + "vcd": "application/x-cdlink", + "cfs": "application/x-cfs-compressed", + "chat": "application/x-chat", + "pgn": "application/x-chess-pgn", + "nsc": "application/x-conference", + "cpio": "application/x-cpio", + "csh": "application/x-csh", + "deb": "application/x-debian-package", + "udeb": "application/x-debian-package", + "dgc": "application/x-dgc-compressed", + "dir": "application/x-director", + "dcr": "application/x-director", + "dxr": "application/x-director", + "cst": "application/x-director", + "cct": "application/x-director", + "cxt": "application/x-director", + "w3d": "application/x-director", + "fgd": "application/x-director", + "swa": "application/x-director", + "wad": "application/x-doom", + "ncx": "application/x-dtbncx+xml", + "dtb": "application/x-dtbook+xml", + "res": "application/x-dtbresource+xml", + "dvi": "application/x-dvi", + "evy": "application/x-envoy", + "eva": "application/x-eva", + "bdf": "application/x-font-bdf", + "gsf": "application/x-font-ghostscript", + "psf": "application/x-font-linux-psf", + "pcf": "application/x-font-pcf", + "snf": "application/x-font-snf", + "pfa": "application/x-font-type1", + "pfb": "application/x-font-type1", + "pfm": "application/x-font-type1", + "afm": "application/x-font-type1", + "arc": "application/x-freearc", + "spl": "application/x-futuresplash", + "gca": "application/x-gca-compressed", + "ulx": "application/x-glulx", + "gnumeric": "application/x-gnumeric", + "gramps": "application/x-gramps-xml", + "gtar": "application/x-gtar", + "hdf": "application/x-hdf", + "install": "application/x-install-instructions", + "iso": "application/x-iso9660-image", + "jnlp": "application/x-java-jnlp-file", + "latex": "application/x-latex", + "lzh": "application/x-lzh-compressed", + "lha": "application/x-lzh-compressed", + "mie": "application/x-mie", + "prc": "application/x-mobipocket-ebook", + "mobi": "application/x-mobipocket-ebook", + "application": "application/x-ms-application", + "lnk": "application/x-ms-shortcut", + "wmd": "application/x-ms-wmd", + "wmz": "application/x-ms-wmz", "xbap": "application/x-ms-xbap", - "xbd": "application/vnd.fujixerox.docuworks.binder", - "xbm": "image/x-xbitmap", - "xca": "application/xcap-caps+xml", - "xcf": "application/x-xcf", - "xcs": "application/calendar+xml", - "xct": "application/vnd.fujixerox.docuworks.container", - "xdd": "application/bacnet-xdd+zip", - "xdf": "application/xcap-diff+xml", - "xdm": "application/vnd.syncml.dm+xml", - "xdp": "application/vnd.adobe.xdp+xml", - "xdr": "video/x-amt-demorun", - "xdssc": "application/dssc+xml", - "xdw": "application/vnd.fujixerox.docuworks", - "xel": "application/xcap-el+xml", - "xenc": "application/xenc+xml", - "xer": "application/patch-ops-error+xml", - "xfd": "application/vnd.xfdl", - "xfdf": "application/vnd.adobe.xfdf", - "xfdl": "application/vnd.xfdl", - "xgz": "xgl/drawing", - "xht": "application/xhtml+xml", - "xhtm": "application/xhtml+xml", - "xhtml": "application/xhtml+xml", - "xhvml": "application/xv+xml", - "xif": "image/vnd.xiff", - "xl": "application/excel", - "xla": "application/vnd.ms-excel", - "xlam": "application/vnd.ms-excel.addin.macroenabled.12", - "xlb": "application/vndms-excel", - "xlc": "application/vnd.ms-excel", + "mdb": "application/x-msaccess", + "obd": "application/x-msbinder", + "crd": "application/x-mscardfile", + "clp": "application/x-msclip", + "exe": "application/x-msdownload", + "dll": "application/x-msdownload", + "com": "application/x-msdownload", + "bat": "application/x-msdownload", + "msi": "application/x-msdownload", + "mvb": "application/x-msmediaview", + "m13": "application/x-msmediaview", + "m14": "application/x-msmediaview", + "wmf": "application/x-msmetafile", + "wmz": "application/x-msmetafile", + "emf": "application/x-msmetafile", + "emz": "application/x-msmetafile", + "mny": "application/x-msmoney", + "pub": "application/x-mspublisher", + "scd": "application/x-msschedule", + "trm": "application/x-msterminal", + "wri": "application/x-mswrite", + "nc": "application/x-netcdf", + "cdf": "application/x-netcdf", + "nzb": "application/x-nzb", + "p12": "application/x-pkcs12", + "pfx": "application/x-pkcs12", + "p7b": "application/x-pkcs7-certificates", + "spc": "application/x-pkcs7-certificates", + "p7r": "application/x-pkcs7-certreqresp", + "rar": "application/x-rar-compressed", + "ris": "application/x-research-info-systems", + "sh": "application/x-sh", + "shar": "application/x-shar", + "swf": "application/x-shockwave-flash", + "xap": "application/x-silverlight-app", + "sql": "application/x-sql", + "sit": "application/x-stuffit", + "sitx": "application/x-stuffitx", + "srt": "application/x-subrip", + "sv4cpio": "application/x-sv4cpio", + "sv4crc": "application/x-sv4crc", + "t3": "application/x-t3vm-image", + "gam": "application/x-tads", + "tar": "application/x-tar", + "tcl": "application/x-tcl", + "tex": "application/x-tex", + "tfm": "application/x-tex-tfm", + "texinfo": "application/x-texinfo", + "texi": "application/x-texinfo", + "obj": "application/x-tgif", + "ustar": "application/x-ustar", + "src": "application/x-wais-source", + "der": "application/x-x509-ca-cert", + "crt": "application/x-x509-ca-cert", + "fig": "application/x-xfig", "xlf": "application/x-xliff+xml", - "xlim": "application/vnd.xmpie.xlim", - "xlm": "application/vnd.ms-excel", - "xls": "application/vnd.ms-excel", - "xlsb": "application/vnd.ms-excel.sheet.binary.macroenabled.12", - "xlsm": "application/vnd.ms-excel.sheet.macroenabled.12", - "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "xlt": "application/vnd.ms-excel", - "xltm": "application/vnd.ms-excel.template.macroenabled.12", - "xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", - "xlw": "application/vnd.ms-excel", - "xm": "audio/xm", - "xml": "text/xml", - "xmls": "application/dskpp+xml", - "xmt_bin": "model/vnd.parasolid.transmit.binary", - "xmt_txt": "model/vnd.parasolid.transmit.text", - "xmz": "xgl/movie", - "xns": "application/xcap-ns+xml", - "xo": "application/vnd.olpc-sugar", - "xof": "x-world/x-vrml", - "xop": "application/xop+xml", - "xpdl": "application/xml", "xpi": "application/x-xpinstall", - "xpix": "application/x-vnd.ls-xpix", - "xpl": "application/xproc+xml", - "xpm": "image/x-xpixmap", - "xpr": "application/vnd.is-xpr", - "xps": "application/vnd.ms-xpsdocument", - "xpw": "application/vnd.intercon.formnet", - "xpx": "application/vnd.intercon.formnet", - "xq": "text/xquery", - "xql": "text/xquery", - "xqm": "text/xquery", - "xqu": "text/xquery", - "xquery": "text/xquery", - "xqy": "text/xquery", - "xsd": "text/xml", - "xsf": "application/prs.xsf+xml", - "xsl": "application/xslt+xml", - "xslt": "application/xslt+xml", - "xsm": "application/vnd.syncml+xml", - "xspf": "application/xspf+xml", - "xsr": "video/x-amt-showrun", - "xtel": "chemical/x-xtel", - "xul": "application/vnd.mozilla.xul+xml", - "xvm": "application/xv+xml", - "xvml": "application/xv+xml", - "xwd": "image/x-xwindowdump", - "xyz": "chemical/x-xyz", - "xyze": "image/vnd.radiance", "xz": "application/x-xz", - "yaml": "text/yaml", - "yang": "application/yang", - "yin": "application/yin+xml", - "yme": "application/vnd.yaoweme", - "yml": "text/yaml", - "ymp": "text/x-suse-ymp", "z1": "application/x-zmachine", "z2": "application/x-zmachine", "z3": "application/x-zmachine", @@ -1888,19 +744,293 @@ const mimes* = { "z6": "application/x-zmachine", "z7": "application/x-zmachine", "z8": "application/x-zmachine", - "zaz": "application/vnd.zzazz.deck+xml", - "zfc": "application/vnd.filmit.zfc", - "zfo": "application/vnd.software602.filler.form-xml-zip", - "zig": "text/zig", + "xaml": "application/xaml+xml", + "xdf": "application/xcap-diff+xml", + "xenc": "application/xenc+xml", + "xhtml": "application/xhtml+xml", + "xht": "application/xhtml+xml", + "xml": "application/xml", + "xsl": "application/xml", + "dtd": "application/xml-dtd", + "xop": "application/xop+xml", + "xpl": "application/xproc+xml", + "xslt": "application/xslt+xml", + "xspf": "application/xspf+xml", + "mxml": "application/xv+xml", + "xhvml": "application/xv+xml", + "xvml": "application/xv+xml", + "xvm": "application/xv+xml", + "yang": "application/yang", + "yin": "application/yin+xml", "zip": "application/zip", - "zir": "application/vnd.zul", - "zirz": "application/vnd.zul", - "zmm": "application/vnd.handheld-entertainment+xml", - "zmt": "chemical/x-mopac-input", - "zone": "text/dns", - "zoo": "application/octet-stream", - "zsh": "text/x-script.zsh", - "~": "application/x-trash" + "adp": "audio/adpcm", + "au": "audio/basic", + "snd": "audio/basic", + "mid": "audio/midi", + "midi": "audio/midi", + "kar": "audio/midi", + "rmi": "audio/midi", + "m4a": "audio/mp4", + "mp4a": "audio/mp4", + "mpga": "audio/mpeg", + "mp2": "audio/mpeg", + "mp2a": "audio/mpeg", + "mp3": "audio/mpeg", + "m2a": "audio/mpeg", + "m3a": "audio/mpeg", + "oga": "audio/ogg", + "ogg": "audio/ogg", + "spx": "audio/ogg", + "opus": "audio/ogg", + "s3m": "audio/s3m", + "sil": "audio/silk", + "uva": "audio/vnd.dece.audio", + "uvva": "audio/vnd.dece.audio", + "eol": "audio/vnd.digital-winds", + "dra": "audio/vnd.dra", + "dts": "audio/vnd.dts", + "dtshd": "audio/vnd.dts.hd", + "lvp": "audio/vnd.lucent.voice", + "pya": "audio/vnd.ms-playready.media.pya", + "ecelp4800": "audio/vnd.nuera.ecelp4800", + "ecelp7470": "audio/vnd.nuera.ecelp7470", + "ecelp9600": "audio/vnd.nuera.ecelp9600", + "rip": "audio/vnd.rip", + "weba": "audio/webm", + "aac": "audio/x-aac", + "aif": "audio/x-aiff", + "aiff": "audio/x-aiff", + "aifc": "audio/x-aiff", + "caf": "audio/x-caf", + "flac": "audio/x-flac", + "mka": "audio/x-matroska", + "m3u": "audio/x-mpegurl", + "wax": "audio/x-ms-wax", + "wma": "audio/x-ms-wma", + "ram": "audio/x-pn-realaudio", + "ra": "audio/x-pn-realaudio", + "rmp": "audio/x-pn-realaudio-plugin", + "wav": "audio/x-wav", + "xm": "audio/xm", + "cdx": "chemical/x-cdx", + "cif": "chemical/x-cif", + "cmdf": "chemical/x-cmdf", + "cml": "chemical/x-cml", + "csml": "chemical/x-csml", + "xyz": "chemical/x-xyz", + "ttc": "font/collection", + "otf": "font/otf", + "ttf": "font/ttf", + "woff": "font/woff", + "woff2": "font/woff2", + "bmp": "image/bmp", + "cgm": "image/cgm", + "g3": "image/g3fax", + "gif": "image/gif", + "ief": "image/ief", + "jpeg": "image/jpeg", + "jpg": "image/jpeg", + "jpe": "image/jpeg", + "ktx": "image/ktx", + "png": "image/png", + "btif": "image/prs.btif", + "sgi": "image/sgi", + "svg": "image/svg+xml", + "svgz": "image/svg+xml", + "tiff": "image/tiff", + "tif": "image/tiff", + "psd": "image/vnd.adobe.photoshop", + "uvi": "image/vnd.dece.graphic", + "uvvi": "image/vnd.dece.graphic", + "uvg": "image/vnd.dece.graphic", + "uvvg": "image/vnd.dece.graphic", + "djvu": "image/vnd.djvu", + "djv": "image/vnd.djvu", + "sub": "image/vnd.dvb.subtitle", + "dwg": "image/vnd.dwg", + "dxf": "image/vnd.dxf", + "fbs": "image/vnd.fastbidsheet", + "fpx": "image/vnd.fpx", + "fst": "image/vnd.fst", + "mmr": "image/vnd.fujixerox.edmics-mmr", + "rlc": "image/vnd.fujixerox.edmics-rlc", + "mdi": "image/vnd.ms-modi", + "wdp": "image/vnd.ms-photo", + "npx": "image/vnd.net-fpx", + "wbmp": "image/vnd.wap.wbmp", + "xif": "image/vnd.xiff", + "webp": "image/webp", + "3ds": "image/x-3ds", + "ras": "image/x-cmu-raster", + "cmx": "image/x-cmx", + "fh": "image/x-freehand", + "fhc": "image/x-freehand", + "fh4": "image/x-freehand", + "fh5": "image/x-freehand", + "fh7": "image/x-freehand", + "ico": "image/x-icon", + "sid": "image/x-mrsid-image", + "pcx": "image/x-pcx", + "pic": "image/x-pict", + "pct": "image/x-pict", + "pnm": "image/x-portable-anymap", + "pbm": "image/x-portable-bitmap", + "pgm": "image/x-portable-graymap", + "ppm": "image/x-portable-pixmap", + "rgb": "image/x-rgb", + "tga": "image/x-tga", + "xbm": "image/x-xbitmap", + "xpm": "image/x-xpixmap", + "xwd": "image/x-xwindowdump", + "eml": "message/rfc822", + "mime": "message/rfc822", + "igs": "model/iges", + "iges": "model/iges", + "msh": "model/mesh", + "mesh": "model/mesh", + "silo": "model/mesh", + "dae": "model/vnd.collada+xml", + "dwf": "model/vnd.dwf", + "gdl": "model/vnd.gdl", + "gtw": "model/vnd.gtw", + "mts": "model/vnd.mts", + "vtu": "model/vnd.vtu", + "wrl": "model/vrml", + "vrml": "model/vrml", + "x3db": "model/x3d+binary", + "x3dbz": "model/x3d+binary", + "x3dv": "model/x3d+vrml", + "x3dvz": "model/x3d+vrml", + "x3d": "model/x3d+xml", + "x3dz": "model/x3d+xml", + "appcache": "text/cache-manifest", + "ics": "text/calendar", + "ifb": "text/calendar", + "css": "text/css", + "csv": "text/csv", + "html": "text/html", + "htm": "text/html", + "js": "text/javascript", + "mjs": "text/javascript", + "n3": "text/n3", + "txt": "text/plain", + "text": "text/plain", + "conf": "text/plain", + "def": "text/plain", + "list": "text/plain", + "log": "text/plain", + "in": "text/plain", + "dsc": "text/prs.lines.tag", + "rtx": "text/richtext", + "sgml": "text/sgml", + "sgm": "text/sgml", + "tsv": "text/tab-separated-values", + "t": "text/troff", + "tr": "text/troff", + "roff": "text/troff", + "man": "text/troff", + "me": "text/troff", + "ms": "text/troff", + "ttl": "text/turtle", + "uri": "text/uri-list", + "uris": "text/uri-list", + "urls": "text/uri-list", + "vcard": "text/vcard", + "curl": "text/vnd.curl", + "dcurl": "text/vnd.curl.dcurl", + "mcurl": "text/vnd.curl.mcurl", + "scurl": "text/vnd.curl.scurl", + "sub": "text/vnd.dvb.subtitle", + "fly": "text/vnd.fly", + "flx": "text/vnd.fmi.flexstor", + "gv": "text/vnd.graphviz", + "3dml": "text/vnd.in3d.3dml", + "spot": "text/vnd.in3d.spot", + "jad": "text/vnd.sun.j2me.app-descriptor", + "wml": "text/vnd.wap.wml", + "wmls": "text/vnd.wap.wmlscript", + "s": "text/x-asm", + "asm": "text/x-asm", + "c": "text/x-c", + "cc": "text/x-c", + "cxx": "text/x-c", + "cpp": "text/x-c", + "h": "text/x-c", + "hh": "text/x-c", + "dic": "text/x-c", + "f": "text/x-fortran", + "for": "text/x-fortran", + "f77": "text/x-fortran", + "f90": "text/x-fortran", + "java": "text/x-java-source", + "nfo": "text/x-nfo", + "opml": "text/x-opml", + "p": "text/x-pascal", + "pas": "text/x-pascal", + "etx": "text/x-setext", + "sfv": "text/x-sfv", + "uu": "text/x-uuencode", + "vcs": "text/x-vcalendar", + "vcf": "text/x-vcard", + "3gp": "video/3gpp", + "3g2": "video/3gpp2", + "h261": "video/h261", + "h263": "video/h263", + "h264": "video/h264", + "jpgv": "video/jpeg", + "jpm": "video/jpm", + "jpgm": "video/jpm", + "mj2": "video/mj2", + "mjp2": "video/mj2", + "mp4": "video/mp4", + "mp4v": "video/mp4", + "mpg4": "video/mp4", + "mpeg": "video/mpeg", + "mpg": "video/mpeg", + "mpe": "video/mpeg", + "m1v": "video/mpeg", + "m2v": "video/mpeg", + "ogv": "video/ogg", + "qt": "video/quicktime", + "mov": "video/quicktime", + "uvh": "video/vnd.dece.hd", + "uvvh": "video/vnd.dece.hd", + "uvm": "video/vnd.dece.mobile", + "uvvm": "video/vnd.dece.mobile", + "uvp": "video/vnd.dece.pd", + "uvvp": "video/vnd.dece.pd", + "uvs": "video/vnd.dece.sd", + "uvvs": "video/vnd.dece.sd", + "uvv": "video/vnd.dece.video", + "uvvv": "video/vnd.dece.video", + "dvb": "video/vnd.dvb.file", + "fvt": "video/vnd.fvt", + "mxu": "video/vnd.mpegurl", + "m4u": "video/vnd.mpegurl", + "pyv": "video/vnd.ms-playready.media.pyv", + "uvu": "video/vnd.uvvu.mp4", + "uvvu": "video/vnd.uvvu.mp4", + "viv": "video/vnd.vivo", + "webm": "video/webm", + "f4v": "video/x-f4v", + "fli": "video/x-fli", + "flv": "video/x-flv", + "m4v": "video/x-m4v", + "mkv": "video/x-matroska", + "mk3d": "video/x-matroska", + "mks": "video/x-matroska", + "mng": "video/x-mng", + "asf": "video/x-ms-asf", + "asx": "video/x-ms-asf", + "vob": "video/x-ms-vob", + "wm": "video/x-ms-wm", + "wmv": "video/x-ms-wmv", + "wmx": "video/x-ms-wmx", + "wvx": "video/x-ms-wvx", + "avi": "video/x-msvideo", + "movie": "video/x-sgi-movie", + "smv": "video/x-smv", + "ice": "x-conference/x-cooltalk", } diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index b3465ef14..656c98a20 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -12,7 +12,7 @@ # TODO: Clean up the exports a bit and everything else in general. -import os, options +import std/[os, options] import std/private/since import std/strbasics @@ -27,12 +27,12 @@ const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr defined(nuttx) when useWinVersion: - import winlean + import std/winlean export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, WSANOTINITIALISED, WSAENOTSOCK, WSAEINPROGRESS, WSAEINTR, WSAEDISCON, ERROR_NETNAME_DELETED else: - import posix + import std/posix export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL, EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET, EBADF export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length @@ -67,7 +67,7 @@ type ## some procedures, such as getaddrinfo) AF_UNIX = 1, ## for local socket (using a file). Unsupported on Windows. AF_INET = 2, ## for network protocol IPv4 or - AF_INET6 = when defined(macosx): 30 else: 23 ## for network protocol IPv6. + AF_INET6 = when defined(macosx): 30 elif defined(windows): 23 else: 10 ## for network protocol IPv6. SockType* = enum ## second argument to `socket` proc SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets @@ -97,6 +97,8 @@ type length*: int addrList*: seq[string] +const IPPROTO_NONE* = IPPROTO_IP ## Use this if your socket type requires a protocol value of zero (e.g. Unix sockets). + when useWinVersion: let osInvalidSocket* = winlean.INVALID_SOCKET @@ -387,21 +389,37 @@ when not useNimNetLite: proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} = ## This function will lookup the hostname of an IP Address. - var myaddr: InAddr - myaddr.s_addr = inet_addr(ip) + var + addrInfo = getAddrInfo(ip, Port(0), AF_UNSPEC) + myAddr: pointer + addrLen = 0 + family = 0 + + defer: freeAddrInfo(addrInfo) + + if addrInfo.ai_addr.sa_family.cint == nativeAfInet: + family = nativeAfInet + myAddr = addr cast[ptr Sockaddr_in](addrInfo.ai_addr).sin_addr + addrLen = 4 + elif addrInfo.ai_addr.sa_family.cint == nativeAfInet6: + family = nativeAfInet6 + myAddr = addr cast[ptr Sockaddr_in6](addrInfo.ai_addr).sin6_addr + addrLen = 16 + else: + raise newException(IOError, "Unknown socket family in `getHostByAddr()`") when useWinVersion: - var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, - cint(AF_INET)) + var s = winlean.gethostbyaddr(cast[ptr InAddr](myAddr), addrLen.cuint, + cint(family)) if s == nil: raiseOSError(osLastError()) else: var s = when defined(android4): - posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint, - cint(posix.AF_INET)) + posix.gethostbyaddr(cast[cstring](myAddr), addrLen.cint, + cint(family)) else: - posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen, - cint(posix.AF_INET)) + posix.gethostbyaddr(myAddr, addrLen.SockLen, + cint(family)) if s == nil: raiseOSError(osLastError(), $hstrerror(h_errno)) @@ -424,7 +442,20 @@ when not useNimNetLite: result.addrList.add($inet_ntoa(inaddrPtr[])) inc(i) else: - result.addrList = cstringArrayToSeq(s.h_addr_list) + let strAddrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int + else: 46 + var i = 0 + while not isNil(s.h_addr_list[i]): + var ipStr = newString(strAddrLen) + if inet_ntop(nativeAfInet6, cast[pointer](s.h_addr_list[i]), + cstring(ipStr), len(ipStr).int32) == nil: + raiseOSError(osLastError()) + when not useWinVersion: + if posix.IN6_IS_ADDR_V4MAPPED(cast[ptr In6Addr](s.h_addr_list[i])) != 0: + ipStr.setSlice("::ffff:".len..<strAddrLen) + setLen(ipStr, len(cstring(ipStr))) + result.addrList.add(ipStr) + inc(i) result.length = int(s.h_length) proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 129c15fbf..24c94b651 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -93,11 +93,11 @@ import std/private/since when defined(nimPreviewSlimSystem): import std/assertions -import nativesockets -import os, strutils, times, sets, options, std/monotimes -import ssl_config +import std/nativesockets +import std/[os, strutils, times, sets, options, monotimes] +import std/ssl_config export nativesockets.Port, nativesockets.`$`, nativesockets.`==` -export Domain, SockType, Protocol +export Domain, SockType, Protocol, IPPROTO_NONE const useWinVersion = defined(windows) or defined(nimdoc) const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr) or @@ -105,12 +105,12 @@ const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr const defineSsl = defined(ssl) or defined(nimdoc) when useWinVersion: - from winlean import WSAESHUTDOWN + from std/winlean import WSAESHUTDOWN when defineSsl: - import openssl + import std/openssl when not defined(nimDisableCertificateValidation): - from ssl_certs import scanSSLCertificates + from std/ssl_certs import scanSSLCertificates # Note: The enumerations are mapped to Window's constants. @@ -209,7 +209,7 @@ when defined(nimHasStyleChecks): when defined(posix) and not defined(lwip): - from posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds + from std/posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int = var tpollfd: TPollfd @@ -1154,7 +1154,7 @@ proc accept*(server: Socket, client: var owned(Socket), acceptAddr(server, client, addrDummy, flags) when defined(posix) and not defined(lwip): - from posix import Sigset, sigwait, sigismember, sigemptyset, sigaddset, + from std/posix import Sigset, sigwait, sigismember, sigemptyset, sigaddset, sigprocmask, pthread_sigmask, SIGPIPE, SIG_BLOCK, SIG_UNBLOCK template blockSigpipe(body: untyped): untyped = @@ -1268,9 +1268,9 @@ proc close*(socket: Socket, flags = {SocketFlag.SafeDisconn}) = socket.fd = osInvalidSocket when defined(posix): - from posix import TCP_NODELAY + from std/posix import TCP_NODELAY else: - from winlean import TCP_NODELAY + from std/winlean import TCP_NODELAY proc toCInt*(opt: SOBool): cint = ## Converts a `SOBool` into its Socket Option cint representation. @@ -1321,7 +1321,7 @@ when defined(nimdoc) or (defined(posix) and not useNimNetLite): when not defined(nimdoc): var socketAddr = makeUnixAddr(path) if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), - (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32: + (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32: raiseOSError(osLastError()) proc bindUnix*(socket: Socket, path: string) = @@ -1330,7 +1330,7 @@ when defined(nimdoc) or (defined(posix) and not useNimNetLite): when not defined(nimdoc): var socketAddr = makeUnixAddr(path) if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), - (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32: + (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32: raiseOSError(osLastError()) when defineSsl: @@ -2040,8 +2040,10 @@ proc dial*(address: string, port: Port, if success: result = newSocket(lastFd, domain, sockType, protocol, buffered) elif lastError != 0.OSErrorCode: + lastFd.close() raiseOSError(lastError) else: + lastFd.close() raise newException(IOError, "Couldn't resolve address: " & address) proc connect*(socket: Socket, address: string, diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index 9849e42db..bf8367d1d 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -20,7 +20,7 @@ when not defined(profiler) and not defined(memProfiler): # We don't want to profile the profiling code ... {.push profiler: off.} -import hashes, algorithm, strutils, tables, sets +import std/[hashes, algorithm, strutils, tables, sets] when defined(nimPreviewSlimSystem): import std/[syncio, sysatomics] @@ -69,7 +69,7 @@ when not defined(memProfiler): else: interval = intervalInUs * 1000 - tickCountCorrection when withThreads: - import locks + import std/locks var profilingLock: Lock diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index ad8eeefd7..4d6ceefd7 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -14,7 +14,7 @@ ## This implementation calls `initRand()` for the first call of ## `genOid`. -import hashes, times, endians, random +import std/[hashes, times, endians, random] from std/private/decode_helpers import handleHexChar when defined(nimPreviewSlimSystem): diff --git a/lib/pure/options.nim b/lib/pure/options.nim index ec384ceb4..b34ff72c0 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -74,7 +74,7 @@ when defined(nimHasEffectsOf): else: {.pragma: effectsOf.} -import typetraits +import std/typetraits when defined(nimPreviewSlimSystem): import std/assertions @@ -82,7 +82,7 @@ when defined(nimPreviewSlimSystem): when (NimMajor, NimMinor) >= (1, 1): type - SomePointer = ref | ptr | pointer | proc + SomePointer = ref | ptr | pointer | proc | iterator {.closure.} else: type SomePointer = ref | ptr | pointer @@ -90,7 +90,7 @@ else: type Option*[T] = object ## An optional type that may or may not contain a value of type `T`. - ## When `T` is a a pointer type (`ptr`, `pointer`, `ref` or `proc`), + ## When `T` is a a pointer type (`ptr`, `pointer`, `ref`, `proc` or `iterator {.closure.}`), ## `none(T)` is represented as `nil`. when T is SomePointer: val: T @@ -117,9 +117,10 @@ proc option*[T](val: sink T): Option[T] {.inline.} = assert option[Foo](nil).isNone assert option(42).isSome - result.val = val - when T isnot SomePointer: - result.has = true + when T is SomePointer: + result = Option[T](val: val) + else: + result = Option[T](has: true, val: val) proc some*[T](val: sink T): Option[T] {.inline.} = ## Returns an `Option` that has the value `val`. @@ -136,10 +137,9 @@ proc some*[T](val: sink T): Option[T] {.inline.} = when T is SomePointer: assert not val.isNil - result.val = val + result = Option[T](val: val) else: - result.has = true - result.val = val + result = Option[T](has: true, val: val) proc none*(T: typedesc): Option[T] {.inline.} = ## Returns an `Option` for this type that has no value. @@ -152,7 +152,7 @@ proc none*(T: typedesc): Option[T] {.inline.} = assert none(int).isNone # the default is the none type - discard + result = Option[T]() proc none*[T]: Option[T] {.inline.} = ## Alias for `none(T) <#none,typedesc>`_. diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 7ba156c89..78ebb1c88 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -52,7 +52,7 @@ import std/private/since import std/cmdline export cmdline -import strutils, pathnorm +import std/[strutils, pathnorm] when defined(nimPreviewSlimSystem): import std/[syncio, assertions, widestrs] @@ -76,9 +76,9 @@ since (1, 1): when weirdTarget: discard elif defined(windows): - import winlean, times + import std/[winlean, times] elif defined(posix): - import posix, times + import std/[posix, times] proc toTime(ts: Timespec): times.Time {.inline.} = result = initTime(ts.tv_sec.int64, ts.tv_nsec.int) @@ -424,13 +424,13 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", when defined(windows): var bufsize = MAX_PATH.int32 var unused: WideCString = nil - var res = newWideCString("", bufsize) + var res = newWideCString(bufsize) while true: var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused) if L == 0'i32: raiseOSError(osLastError(), filename) elif L > bufsize: - res = newWideCString("", L) + res = newWideCString(L) bufsize = L else: result = res$L @@ -453,7 +453,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", c_free(cast[pointer](r)) proc getCurrentCompilerExe*(): string {.compileTime.} = discard - ## This is `getAppFilename()`_ at compile time. + ## Returns the path of the currently running Nim compiler or nimble executable. ## ## Can be used to retrieve the currently executing ## Nim compiler from a Nim or nimscript program, or the nimble binary @@ -692,7 +692,10 @@ proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noWeirdT proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [TimeEffect], noWeirdTarget.} = ## Sleeps `milsecs` milliseconds. + ## A negative `milsecs` causes sleep to return immediately. when defined(windows): + if milsecs < 0: + return # fixes #23732 winlean.sleep(int32(milsecs)) else: var a, b: Timespec @@ -754,14 +757,14 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped = ## 'rawInfo' is either a 'BY_HANDLE_FILE_INFORMATION' structure on Windows, ## or a 'Stat' structure on posix when defined(windows): - template merge(a, b): untyped = - int64( + template merge[T](a, b): untyped = + cast[T]( (uint64(cast[uint32](a))) or (uint64(cast[uint32](b)) shl 32) ) formalInfo.id.device = rawInfo.dwVolumeSerialNumber - formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh) - formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh) + formalInfo.id.file = merge[FileId](rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh) + formalInfo.size = merge[BiggestInt](rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh) formalInfo.linkCount = rawInfo.nNumberOfLinks formalInfo.lastAccessTime = fromWinTime(rdFileTime(rawInfo.ftLastAccessTime)) formalInfo.lastWriteTime = fromWinTime(rdFileTime(rawInfo.ftLastWriteTime)) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index b8dd153f2..c304ecca6 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -18,18 +18,18 @@ include "system/inclrtl" import - strutils, os, strtabs, streams, cpuinfo, streamwrapper, - std/private/since + std/[strutils, os, strtabs, streams, cpuinfo, streamwrapper, + private/since] export quoteShell, quoteShellWindows, quoteShellPosix when defined(windows): - import winlean + import std/winlean else: - import posix + import std/posix when defined(linux) and defined(useClone): - import linux + import std/linux when defined(nimPreviewSlimSystem): import std/[syncio, assertions] @@ -212,7 +212,7 @@ proc processID*(p: Process): int {.rtl, extern: "nosp$1".} = return p.id proc waitForExit*(p: Process, timeout: int = -1): int {.rtl, - extern: "nosp$1", raises: [OSError, ValueError], tags: [].} + extern: "nosp$1", raises: [OSError, ValueError], tags: [TimeEffect].} ## Waits for the process to finish and returns `p`'s error code. ## ## .. warning:: Be careful when using `waitForExit` for processes created without @@ -457,7 +457,7 @@ proc execProcesses*(cmds: openArray[string], if afterRunEvent != nil: afterRunEvent(i, p) close(p) -iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raises: [OSError, IOError, ValueError], tags: [ReadIOEffect].} = +iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect].} = ## Convenience iterator for working with `startProcess` to read data from a ## background process. ## @@ -487,7 +487,7 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raise discard waitForExit(p) proc readLines*(p: Process): (seq[string], int) {.since: (1, 3), - raises: [OSError, IOError, ValueError], tags: [ReadIOEffect].} = + raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect].} = ## Convenience function for working with `startProcess` to read data from a ## background process. ## @@ -1123,14 +1123,13 @@ elif not defined(useNimRtl): var error: cint let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error)) if sizeRead == sizeof(error): - raiseOSError(osLastError(), + raiseOSError(OSErrorCode(error), "Could not find command: '" & $data.sysCommand & "'. OS error: " & $strerror(error)) return pid {.push stacktrace: off, profiler: off.} - proc startProcessFail(data: ptr StartProcessData) = - var error: cint = errno + proc startProcessFail(data: ptr StartProcessData, error: cint = errno) = discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) exitnow(1) @@ -1167,7 +1166,11 @@ elif not defined(useNimRtl): if (poUsePath in data.options): when defined(uClibc) or defined(linux) or defined(haiku): # uClibc environment (OpenWrt included) doesn't have the full execvpe - let exe = findExe(data.sysCommand) + var exe: string + try: + exe = findExe(data.sysCommand) + except OSError as e: + startProcessFail(data, e.errorCode) discard execve(exe.cstring, data.sysArgs, data.sysEnv) else: # MacOSX doesn't have execvpe, so we need workaround. @@ -1231,7 +1234,7 @@ elif not defined(useNimRtl): when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(openbsd) or defined(dragonfly): - import kqueue + import std/kqueue proc waitForExit(p: Process, timeout: int = -1): int = if p.exitFlag: @@ -1353,114 +1356,63 @@ elif not defined(useNimRtl): result = exitStatusLikeShell(p.exitStatus) else: - import times - - const - hasThreadSupport = compileOption("threads") and not defined(nimscript) + import std/times except getTime + import std/monotimes proc waitForExit(p: Process, timeout: int = -1): int = - template adjustTimeout(t, s, e: Timespec) = - var diff: int - var b: Timespec - b.tv_sec = e.tv_sec - b.tv_nsec = e.tv_nsec - e.tv_sec = e.tv_sec - s.tv_sec - if e.tv_nsec >= s.tv_nsec: - e.tv_nsec -= s.tv_nsec - else: - if e.tv_sec == posix.Time(0): - raise newException(ValueError, "System time was modified") - else: - diff = s.tv_nsec - e.tv_nsec - e.tv_nsec = 1_000_000_000 - diff - t.tv_sec = t.tv_sec - e.tv_sec - if t.tv_nsec >= e.tv_nsec: - t.tv_nsec -= e.tv_nsec - else: - t.tv_sec = t.tv_sec - posix.Time(1) - diff = e.tv_nsec - t.tv_nsec - t.tv_nsec = 1_000_000_000 - diff - s.tv_sec = b.tv_sec - s.tv_nsec = b.tv_nsec - if p.exitFlag: return exitStatusLikeShell(p.exitStatus) - if timeout == -1: - var status: cint = 1 + if timeout < 0: + # Backwards compatibility with previous verison to + # handle cases where timeout == -1, but extend + # to handle cases where timeout < 0 + var status: cint if waitpid(p.id, status, 0) < 0: raiseOSError(osLastError()) p.exitFlag = true p.exitStatus = status else: - var nmask, omask: Sigset - var sinfo: SigInfo - var stspec, enspec, tmspec: Timespec - - discard sigemptyset(nmask) - discard sigemptyset(omask) - discard sigaddset(nmask, SIGCHLD) - - when hasThreadSupport: - if pthread_sigmask(SIG_BLOCK, nmask, omask) == -1: - raiseOSError(osLastError()) - else: - if sigprocmask(SIG_BLOCK, nmask, omask) == -1: - raiseOSError(osLastError()) - - if timeout >= 1000: - tmspec.tv_sec = posix.Time(timeout div 1_000) - tmspec.tv_nsec = (timeout %% 1_000) * 1_000_000 - else: - tmspec.tv_sec = posix.Time(0) - tmspec.tv_nsec = (timeout * 1_000_000) - - try: - if clock_gettime(CLOCK_REALTIME, stspec) == -1: - raiseOSError(osLastError()) - while true: - let res = sigtimedwait(nmask, sinfo, tmspec) - if res == SIGCHLD: - if sinfo.si_pid == p.id: - var status: cint = 1 - if waitpid(p.id, status, 0) < 0: - raiseOSError(osLastError()) - p.exitFlag = true - p.exitStatus = status - break - else: - # we have SIGCHLD, but not for process we are waiting, - # so we need to adjust timeout value and continue - if clock_gettime(CLOCK_REALTIME, enspec) == -1: - raiseOSError(osLastError()) - adjustTimeout(tmspec, stspec, enspec) - elif res < 0: - let err = osLastError() - if err.cint == EINTR: - # we have received another signal, so we need to - # adjust timeout and continue - if clock_gettime(CLOCK_REALTIME, enspec) == -1: - raiseOSError(osLastError()) - adjustTimeout(tmspec, stspec, enspec) - elif err.cint == EAGAIN: - # timeout expired, so we trying to kill process - if posix.kill(p.id, SIGKILL) == -1: - raiseOSError(osLastError()) - var status: cint = 1 - if waitpid(p.id, status, 0) < 0: - raiseOSError(osLastError()) - p.exitFlag = true - p.exitStatus = status - break - else: - raiseOSError(err) - finally: - when hasThreadSupport: - if pthread_sigmask(SIG_UNBLOCK, nmask, omask) == -1: - raiseOSError(osLastError()) + # Max 50ms delay + const maxWait = initDuration(milliseconds = 50) + let wait = initDuration(milliseconds = timeout) + let deadline = getMonoTime() + wait + # starting 50μs delay + var delay = initDuration(microseconds = 50) + + while true: + var status: cint + let pid = waitpid(p.id, status, WNOHANG) + if p.id == pid : + p.exitFlag = true + p.exitStatus = status + break + elif pid.int == -1: + raiseOsError(osLastError()) else: - if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1: - raiseOSError(osLastError()) + # Continue waiting if needed + if getMonoTime() >= deadline: + # Previous version of `waitForExit` + # foricibly killed the process. + # We keep this so we don't break programs + # that depend on this behavior + if posix.kill(p.id, SIGKILL) < 0: + raiseOSError(osLastError()) + else: + const max = 1_000_000_000 + let + newWait = getMonoTime() + delay + ticks = newWait.ticks() + ns = ticks mod max + secs = ticks div max + var + waitSpec: TimeSpec + unused: Timespec + waitSpec.tv_sec = posix.Time(secs) + waitSpec.tv_nsec = clong ns + discard posix.clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, waitSpec, unused) + let remaining = deadline - getMonoTime() + delay = min([delay * 2, remaining, maxWait]) result = exitStatusLikeShell(p.exitStatus) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index 3ba62ebd1..8a43daf54 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -170,7 +170,7 @@ runnableExamples: assert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False" assert dict.getSectionValue(section4, "purpose") == "formatting for readability" -import strutils, lexbase, streams, tables +import std/[strutils, lexbase, streams, tables] import std/private/decode_helpers import std/private/since @@ -452,7 +452,7 @@ proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = if c.tok.kind == tkSymbol: case kind of cfgOption, cfgKeyValuePair: - result = CfgEvent(kind: kind, key: c.tok.literal, value: "") + result = CfgEvent(kind: kind, key: c.tok.literal.move, value: "") else: discard rawGetTok(c, c.tok) if c.tok.kind in {tkEquals, tkColon}: @@ -481,7 +481,7 @@ proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = of tkBracketLe: rawGetTok(c, c.tok) if c.tok.kind == tkSymbol: - result = CfgEvent(kind: cfgSectionStart, section: c.tok.literal) + result = CfgEvent(kind: cfgSectionStart, section: c.tok.literal.move) else: result = CfgEvent(kind: cfgError, msg: errorStr(c, "symbol expected, but found: " & c.tok.literal)) diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index dcd486c08..c7bf0c9c1 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -67,7 +67,7 @@ ## * `parsesql module <parsesql.html>`_ for a SQL parser ## * `other parsers <lib.html#pure-libraries-parsers>`_ for other parsers -import lexbase, streams +import std/[lexbase, streams] when defined(nimPreviewSlimSystem): import std/syncio @@ -349,7 +349,7 @@ proc rowEntry*(self: var CsvParser, entry: string): var string = raise newException(KeyError, "Entry `" & entry & "` doesn't exist") when not defined(testing) and isMainModule: - import os + import std/os var s = newFileStream(paramStr(1), fmRead) if s == nil: quit("cannot open the file" & paramStr(1)) var x: CsvParser diff --git a/lib/pure/parsejson.nim b/lib/pure/parsejson.nim index fcbcf8e36..9292a8596 100644 --- a/lib/pure/parsejson.nim +++ b/lib/pure/parsejson.nim @@ -11,7 +11,7 @@ ## and exported by the `json` standard library ## module, but can also be used in its own right. -import strutils, lexbase, streams, unicode +import std/[strutils, lexbase, streams, unicode] import std/private/decode_helpers when defined(nimPreviewSlimSystem): diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 6674a7272..03f151b66 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -176,7 +176,8 @@ include "system/inclrtl" -import os +import std/strutils +import std/os type CmdLineKind* = enum ## The detected command line token. @@ -249,9 +250,20 @@ proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {}, result.cmds[i] = cmdline[i] else: when declared(paramCount): - result.cmds = newSeq[string](paramCount()) - for i in countup(1, paramCount()): - result.cmds[i-1] = paramStr(i) + when defined(nimscript): + var ctr = 0 + var firstNimsFound = false + for i in countup(0, paramCount()): + if firstNimsFound: + result.cmds[ctr] = paramStr(i) + inc ctr, 1 + if paramStr(i).endsWith(".nims") and not firstNimsFound: + firstNimsFound = true + result.cmds = newSeq[string](paramCount()-i) + else: + result.cmds = newSeq[string](paramCount()) + for i in countup(1, paramCount()): + result.cmds[i-1] = paramStr(i) else: # we cannot provide this for NimRtl creation on Posix, because we can't # access the command line arguments then! diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim index 074faf64c..a7c938d01 100644 --- a/lib/pure/parsesql.nim +++ b/lib/pure/parsesql.nim @@ -12,7 +12,7 @@ ## ## Unstable API. -import strutils, lexbase +import std/[strutils, lexbase] import std/private/decode_helpers when defined(nimPreviewSlimSystem): @@ -1491,7 +1491,7 @@ proc treeRepr*(s: SqlNode): string = result = newStringOfCap(128) treeReprAux(s, 0, result) -import streams +import std/streams proc open(L: var SqlLexer, input: Stream, filename: string) = lexbase.open(L, input) diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index ce642fcf7..2ca255fa0 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -460,6 +460,8 @@ proc parseBiggestInt*(s: openArray[char], number: var BiggestInt): int {. var res: BiggestInt doAssert parseBiggestInt("9223372036854775807", res) == 19 doAssert res == 9223372036854775807 + doAssert parseBiggestInt("-2024_05_09", res) == 11 + doAssert res == -20240509 var res = BiggestInt(0) # use 'res' for exception safety (don't write to 'number' in case of an # overflow exception): @@ -474,10 +476,8 @@ proc parseInt*(s: openArray[char], number: var int): int {. ## `ValueError` is raised if the parsed integer is out of the valid range. runnableExamples: var res: int - doAssert parseInt("2019", res, 0) == 4 - doAssert res == 2019 - doAssert parseInt("2019", res, 2) == 2 - doAssert res == 19 + doAssert parseInt("-2024_05_02", res) == 11 + doAssert res == -20240502 var res = BiggestInt(0) result = parseBiggestInt(s, res) when sizeof(int) <= 4: @@ -992,6 +992,10 @@ proc parseBiggestInt*(s: string, number: var BiggestInt, start = 0): int {.noSid var res: BiggestInt doAssert parseBiggestInt("9223372036854775807", res, 0) == 19 doAssert res == 9223372036854775807 + doAssert parseBiggestInt("-2024_05_09", res) == 11 + doAssert res == -20240509 + doAssert parseBiggestInt("-2024_05_02", res, 7) == 4 + doAssert res == 502 parseBiggestInt(s.toOpenArray(start, s.high), number) proc parseInt*(s: string, number: var int, start = 0): int {.noSideEffect, raises: [ValueError].} = @@ -1000,10 +1004,10 @@ proc parseInt*(s: string, number: var int, start = 0): int {.noSideEffect, raise ## `ValueError` is raised if the parsed integer is out of the valid range. runnableExamples: var res: int - doAssert parseInt("2019", res, 0) == 4 - doAssert res == 2019 - doAssert parseInt("2019", res, 2) == 2 - doAssert res == 19 + doAssert parseInt("-2024_05_02", res) == 11 + doAssert res == -20240502 + doAssert parseInt("-2024_05_02", res, 7) == 4 + doAssert res == 502 parseInt(s.toOpenArray(start, s.high), number) diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim index 88cb6d9c0..c760799a2 100644 --- a/lib/pure/parsexml.nim +++ b/lib/pure/parsexml.nim @@ -41,7 +41,7 @@ document. # This program reads an HTML file and writes its title to stdout. # Errors and whitespace are ignored. - import os, streams, parsexml, strutils + import std/[os, streams, parsexml, strutils] if paramCount() < 1: quit("Usage: htmltitle filename[.html]") @@ -90,7 +90,7 @@ an HTML document contains. # This program reads an HTML file and writes all its used links to stdout. # Errors and whitespace are ignored. - import os, streams, parsexml, strutils + import std/[os, streams, parsexml, strutils] proc `=?=` (a, b: string): bool = # little trick: define our own comparator that ignores case @@ -147,7 +147,7 @@ an HTML document contains. ]## import - strutils, lexbase, streams, unicode + std/[strutils, lexbase, streams, unicode] when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -792,7 +792,7 @@ proc next*(my: var XmlParser) = my.state = stateNormal when not defined(testing) and isMainModule: - import os + import std/os var s = newFileStream(paramStr(1), fmRead) if s == nil: quit("cannot open the file" & paramStr(1)) var x: XmlParser diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index 18e26027f..2969fd6d7 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -22,11 +22,11 @@ when defined(nimPreviewSlimSystem): const useUnicode = true ## change this to deactivate proper UTF-8 support -import strutils, macros +import std/[strutils, macros] import std/private/decode_helpers when useUnicode: - import unicode + import std/unicode export unicode.`==` const @@ -314,21 +314,21 @@ func capture*(a: Peg = Peg(kind: pkEmpty)): Peg {.rtl, extern: "npegsCapture".} func backref*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {. rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. `reverse` specifies wether indexing starts from the end of the + ## from 1. `reverse` specifies whether indexing starts from the end of the ## capture list. result = Peg(kind: pkBackRef, index: (if reverse: -index else: index - 1)) func backrefIgnoreCase*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {. rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. `reverse` specifies wether indexing starts from the end of the + ## from 1. `reverse` specifies whether indexing starts from the end of the ## capture list. Ignores case for matching. result = Peg(kind: pkBackRefIgnoreCase, index: (if reverse: -index else: index - 1)) func backrefIgnoreStyle*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {. rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. `reverse` specifies wether indexing starts from the end of the + ## from 1. `reverse` specifies whether indexing starts from the end of the ## capture list. Ignores style for matching. result = Peg(kind: pkBackRefIgnoreStyle, index: (if reverse: -index else: index - 1)) @@ -1047,7 +1047,7 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) = `enter hdPostf`(s, pegNode, start) else: discard - let hdPostf = ident(substr(strVal(pegKind), 2)) + let hdPostf = ident(substr($pegKind, 2)) getAst(mkDoEnter(hdPostf, s, pegNode, start)) macro leave(pegKind, s, pegNode, start, length: untyped): untyped = @@ -1058,7 +1058,7 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) = `leave hdPostf`(s, pegNode, start, length) else: discard - let hdPostf = ident(substr(strVal(pegKind), 2)) + let hdPostf = ident(substr($pegKind, 2)) getAst(mkDoLeave(hdPostf, s, pegNode, start, length)) matchOrParse(parseIt) @@ -1198,7 +1198,7 @@ template `=~`*(s: string, pattern: Peg): bool = ## ``` bind MaxSubpatterns when not declaredInScope(matches): - var matches {.inject.}: array[0..MaxSubpatterns-1, string] + var matches {.inject.} = default(array[0..MaxSubpatterns-1, string]) match(s, pattern, matches) # ------------------------- more string handling ------------------------------ diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 88616594b..3ec77d37e 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -71,7 +71,7 @@ runnableExamples: ## * `list of cryptographic and hashing modules <lib.html#pure-libraries-hashing>`_ ## in the standard library -import algorithm, math +import std/[algorithm, math] import std/private/[since, jsutils] when defined(nimPreviewSlimSystem): @@ -79,15 +79,28 @@ when defined(nimPreviewSlimSystem): include system/inclrtl {.push debugger: off.} +template whenHasBigInt64(yes64, no64): untyped = + when defined(js): + when compiles(compileOption("jsbigint64")): + when compileOption("jsbigint64"): + yes64 + else: + no64 + else: + no64 + else: + yes64 -when defined(js): - type Ui = uint32 - const randMax = 4_294_967_295u32 -else: +whenHasBigInt64: type Ui = uint64 const randMax = 18_446_744_073_709_551_615u64 +do: + type Ui = uint32 + + const randMax = 4_294_967_295u32 + type Rand* = object ## State of a random number generator. @@ -105,17 +118,17 @@ type ## generator are **not** thread-safe! a0, a1: Ui -when defined(js): - var state = Rand( - a0: 0x69B4C98Cu32, - a1: 0xFED1DD30u32) # global for backwards compatibility -else: +whenHasBigInt64: const DefaultRandSeed = Rand( a0: 0x69B4C98CB8530805u64, a1: 0xFED1DD3004688D67CAu64) # racy for multi-threading but good enough for now: var state = DefaultRandSeed # global for backwards compatibility +do: + var state = Rand( + a0: 0x69B4C98Cu32, + a1: 0xFED1DD30u32) # global for backwards compatibility func isValid(r: Rand): bool {.inline.} = ## Check whether state of `r` is valid. @@ -208,10 +221,10 @@ proc skipRandomNumbers*(s: var Rand) = doAssert vals == [501737, 497901, 500683, 500157] - when defined(js): - const helper = [0xbeac0467u32, 0xd86b048bu32] - else: + whenHasBigInt64: const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64] + do: + const helper = [0xbeac0467u32, 0xd86b048bu32] var s0 = Ui 0 s1 = Ui 0 @@ -294,7 +307,13 @@ proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} = let x = next(r) when defined(js): - result = (float(x) / float(high(uint32))) * max + when compiles(compileOption("jsbigint64")): + when compileOption("jsbigint64"): + result = (float(x) / float(high(uint64))) * max + else: + result = (float(x) / float(high(uint32))) * max + else: + result = (float(x) / float(high(uint32))) * max else: let u = (0x3FFu64 shl 52u64) or (x shr 12u64) result = (cast[float](u) - 1.0) * max @@ -670,7 +689,7 @@ when not defined(standalone): import std/[hashes, os, sysrand, monotimes] when compileOption("threads"): - import locks + import std/locks var baseSeedLock: Lock baseSeedLock.initLock diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index aba0f4ce4..5f806bd70 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -21,7 +21,7 @@ runnableExamples: doAssert r1 * r2 == -3 // 8 doAssert r1 / r2 == -2 // 3 -import math, hashes +import std/[math, hashes] when defined(nimPreviewSlimSystem): import std/assertions @@ -40,16 +40,16 @@ func reduce*[T: SomeInteger](x: var Rational[T]) = reduce(r) doAssert r.num == 1 doAssert r.den == 2 - + if x.den == 0: + raise newException(DivByZeroDefect, "division by zero") let common = gcd(x.num, x.den) if x.den > 0: x.num = x.num div common x.den = x.den div common - elif x.den < 0: - x.num = -x.num div common - x.den = -x.den div common - else: - raise newException(DivByZeroDefect, "division by zero") + when T isnot SomeUnsignedInt: + if x.den < 0: + x.num = -x.num div common + x.den = -x.den div common func initRational*[T: SomeInteger](num, den: T): Rational[T] = ## Creates a new rational number with numerator `num` and denominator `den`. @@ -318,3 +318,23 @@ func hash*[T](x: Rational[T]): Hash = h = h !& hash(copy.num) h = h !& hash(copy.den) result = !$h + +func `^`*[T: SomeInteger](x: Rational[T], y: T): Rational[T] = + ## Computes `x` to the power of `y`. + ## + ## The exponent `y` must be an integer. Negative exponents are supported + ## but floating point exponents are not. + runnableExamples: + doAssert (-3 // 5) ^ 0 == (1 // 1) + doAssert (-3 // 5) ^ 1 == (-3 // 5) + doAssert (-3 // 5) ^ 2 == (9 // 25) + doAssert (-3 // 5) ^ -2 == (25 // 9) + + if y >= 0: + result.num = x.num ^ y + result.den = x.den ^ y + else: + result.num = x.den ^ -y + result.den = x.num ^ -y + # Note that all powers of reduced rationals are already reduced, + # so we don't need to call reduce() here diff --git a/lib/pure/reservedmem.nim b/lib/pure/reservedmem.nim index 528b0095c..ffa0128dc 100644 --- a/lib/pure/reservedmem.nim +++ b/lib/pure/reservedmem.nim @@ -44,7 +44,7 @@ type mem: ReservedMem when defined(windows): - import winlean + import std/winlean import std/private/win_getsysteminfo proc getAllocationGranularity: uint = @@ -68,7 +68,7 @@ when defined(windows): raiseOSError(osLastError()) else: - import posix + import std/posix let allocationGranularity = sysconf(SC_PAGESIZE) diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index b973fd222..8750aca87 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -17,7 +17,7 @@ ## runtime efficiency. include system/inclrtl -import streams +import std/streams when defined(nimPreviewSlimSystem): import std/[syncio, formatfloat, assertions] diff --git a/lib/pure/segfaults.nim b/lib/pure/segfaults.nim index b0eac2299..65b059e86 100644 --- a/lib/pure/segfaults.nim +++ b/lib/pure/segfaults.nim @@ -26,7 +26,7 @@ se.msg = "Could not access value because it is nil." when defined(windows): include "../system/ansi_c" - import winlean + import std/winlean const EXCEPTION_ACCESS_VIOLATION = DWORD(0xc0000005'i32) @@ -65,7 +65,7 @@ when defined(windows): c_signal(SIGSEGV, segfaultHandler) else: - import posix + import std/posix var sa: Sigaction diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 1b4ae992d..ac180e2bd 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -27,7 +27,7 @@ ## ## TODO: `/dev/poll`, `event ports` and filesystem events. -import nativesockets +import std/nativesockets import std/oserrors when defined(nimPreviewSlimSystem): @@ -235,9 +235,9 @@ when defined(nimdoc): ## For *poll* and *select* selectors `-1` is returned. else: - import strutils + import std/strutils when hasThreadSupport: - import locks + import std/locks type SharedArray[T] = UncheckedArray[T] @@ -288,7 +288,7 @@ else: setBlocking(fd.SocketHandle, false) when not defined(windows): - import posix + import std/posix template setKey(s, pident, pevents, pparam, pdata: untyped) = var skey = addr(s.fds[pident]) diff --git a/lib/pure/ssl_certs.nim b/lib/pure/ssl_certs.nim index dd09848be..d60cd22eb 100644 --- a/lib/pure/ssl_certs.nim +++ b/lib/pure/ssl_certs.nim @@ -10,7 +10,7 @@ ## The default locations can be overridden using the SSL_CERT_FILE and ## SSL_CERT_DIR environment variables. -import os, strutils +import std/[os, strutils] # FWIW look for files before scanning entire dirs. @@ -150,7 +150,7 @@ iterator scanSSLCertificates*(useEnvVars = false): string = # Certificates management on windows # when defined(windows) or defined(nimdoc): # -# import openssl +# import std/openssl # # type # PCCertContext {.final, pure.} = pointer diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index 7f797529d..6a4fd8f01 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -53,7 +53,7 @@ runnableExamples: doAssert statistics.kurtosis() ~= -1.0 doAssert statistics.kurtosisS() ~= -0.7000000000000008 -from math import FloatClass, sqrt, pow, round +from std/math import FloatClass, sqrt, pow, round when defined(nimPreviewSlimSystem): import std/[assertions, formatfloat] diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index d3aeacee5..56f49d7b1 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -15,6 +15,11 @@ ## Other modules may provide other implementations for this standard ## stream interface. ## +## .. warning:: Due to the use of `pointer`, the `readData`, `peekData` and +## `writeData` interfaces are not available on the compile-time VM, and must +## be cast from a `ptr string` on the JS backend. However, `readDataStr` is +## available generally in place of `readData`. +## ## Basic usage ## =========== ## @@ -938,10 +943,14 @@ proc peekFloat64*(s: Stream): float64 = proc readStrPrivate(s: Stream, length: int, str: var string) = if length > len(str): setLen(str, length) - when defined(js): - let L = readData(s, addr(str), length) + var L: int + when nimvm: + L = readDataStr(s, str, 0..length-1) else: - let L = readData(s, cstring(str), length) + when defined(js): + L = readData(s, addr(str), length) + else: + L = readData(s, cstring(str), length) if L != len(str): setLen(str, L) proc readStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} = @@ -1482,7 +1491,7 @@ when false: # do not import windows as this increases compile times: discard else: - import posix + import std/posix proc hsSetPosition(s: FileHandleStream, pos: int) = discard lseek(s.handle, pos, SEEK_SET) diff --git a/lib/pure/streamwrapper.nim b/lib/pure/streamwrapper.nim index 9f5c0f28a..99752a9ab 100644 --- a/lib/pure/streamwrapper.nim +++ b/lib/pure/streamwrapper.nim @@ -11,7 +11,7 @@ ## ## **Since** version 1.2. -import deques, streams +import std/[deques, streams] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim index 2668ad66c..7d093ebb3 100644 --- a/lib/pure/strformat.nim +++ b/lib/pure/strformat.nim @@ -264,6 +264,12 @@ The available floating point presentation types are: exponent notation. `G` General format. Same as `g` except it switches to `E` if the number gets to large. +`i` Complex General format. This is only supported for + complex numbers, which it prints using the mathematical + (RE+IMj) format. The real and imaginary parts are printed + using the general format `g` by default, but it is + possible to combine this format with one of the other + formats (e.g `jf`). (None) Similar to `g`, except that it prints at least one digit after the decimal point. ================= ==================================================== @@ -316,8 +322,8 @@ help with readability, since there is only so much you can cram into single letter DSLs. ]## -import macros, parseutils, unicode -import strutils except format +import std/[macros, parseutils, unicode] +import std/strutils except format when defined(nimPreviewSlimSystem): import std/assertions @@ -475,50 +481,48 @@ proc parseStandardFormatSpecifier*(s: string; start = 0; raise newException(ValueError, "invalid format string, cannot parse: " & s[i..^1]) +proc toRadix(typ: char): int = + case typ + of 'x', 'X': 16 + of 'd', '\0': 10 + of 'o': 8 + of 'b': 2 + else: + raise newException(ValueError, + "invalid type in format string for number, expected one " & + " of 'x', 'X', 'b', 'd', 'o' but got: " & typ) + proc formatValue*[T: SomeInteger](result: var string; value: T; - specifier: string) = + specifier: static string) = ## Standard format implementation for `SomeInteger`. It makes little ## sense to call this directly, but it is required to exist ## by the `&` macro. - if specifier.len == 0: + when specifier.len == 0: result.add $value - return - let spec = parseStandardFormatSpecifier(specifier) - var radix = 10 - case spec.typ - of 'x', 'X': radix = 16 - of 'd', '\0': discard - of 'b': radix = 2 - of 'o': radix = 8 else: - raise newException(ValueError, - "invalid type in format string for number, expected one " & - " of 'x', 'X', 'b', 'd', 'o' but got: " & spec.typ) - result.add formatInt(value, radix, spec) + const + spec = parseStandardFormatSpecifier(specifier) + radix = toRadix(spec.typ) -proc formatValue*(result: var string; value: SomeFloat; specifier: string) = - ## Standard format implementation for `SomeFloat`. It makes little + result.add formatInt(value, radix, spec) + +proc formatValue*[T: SomeInteger](result: var string; value: T; + specifier: string) = + ## Standard format implementation for `SomeInteger`. It makes little ## sense to call this directly, but it is required to exist ## by the `&` macro. if specifier.len == 0: result.add $value - return - let spec = parseStandardFormatSpecifier(specifier) - - var fmode = ffDefault - case spec.typ - of 'e', 'E': - fmode = ffScientific - of 'f', 'F': - fmode = ffDecimal - of 'g', 'G': - fmode = ffDefault - of '\0': discard else: - raise newException(ValueError, - "invalid type in format string for number, expected one " & - " of 'e', 'E', 'f', 'F', 'g', 'G' but got: " & spec.typ) + let + spec = parseStandardFormatSpecifier(specifier) + radix = toRadix(spec.typ) + + result.add formatInt(value, radix, spec) +proc formatFloat( + result: var string, value: SomeFloat, fmode: FloatFormatMode, + spec: StandardFormatSpecifier) = var f = formatBiggestFloat(value, fmode, spec.precision) var sign = false if value >= 0.0: @@ -553,23 +557,83 @@ proc formatValue*(result: var string; value: SomeFloat; specifier: string) = else: result.add res +proc toFloatFormatMode(typ: char): FloatFormatMode = + case typ + of 'e', 'E': ffScientific + of 'f', 'F': ffDecimal + of 'g', 'G': ffDefault + of '\0': ffDefault + else: + raise newException(ValueError, + "invalid type in format string for number, expected one " & + " of 'e', 'E', 'f', 'F', 'g', 'G' but got: " & typ) + +proc formatValue*(result: var string; value: SomeFloat; specifier: static string) = + ## Standard format implementation for `SomeFloat`. It makes little + ## sense to call this directly, but it is required to exist + ## by the `&` macro. + when specifier.len == 0: + result.add $value + else: + const + spec = parseStandardFormatSpecifier(specifier) + fmode = toFloatFormatMode(spec.typ) + + formatFloat(result, value, fmode, spec) + +proc formatValue*(result: var string; value: SomeFloat; specifier: string) = + ## Standard format implementation for `SomeFloat`. It makes little + ## sense to call this directly, but it is required to exist + ## by the `&` macro. + if specifier.len == 0: + result.add $value + else: + let + spec = parseStandardFormatSpecifier(specifier) + fmode = toFloatFormatMode(spec.typ) + + formatFloat(result, value, fmode, spec) + +proc formatValue*(result: var string; value: string; specifier: static string) = + ## Standard format implementation for `string`. It makes little + ## sense to call this directly, but it is required to exist + ## by the `&` macro. + const spec = parseStandardFormatSpecifier(specifier) + var value = + when spec.typ in {'s', '\0'}: value + else: static: + raise newException(ValueError, + "invalid type in format string for string, expected 's', but got " & + spec.typ) + when spec.precision != -1: + if spec.precision < runeLen(value): + const precision = cast[Natural](spec.precision) + setLen(value, Natural(runeOffset(value, precision))) + + result.add alignString(value, spec.minimumWidth, spec.align, spec.fill) + proc formatValue*(result: var string; value: string; specifier: string) = ## Standard format implementation for `string`. It makes little ## sense to call this directly, but it is required to exist ## by the `&` macro. let spec = parseStandardFormatSpecifier(specifier) - var value = value - case spec.typ - of 's', '\0': discard - else: - raise newException(ValueError, - "invalid type in format string for string, expected 's', but got " & - spec.typ) + var value = + if spec.typ in {'s', '\0'}: value + else: + raise newException(ValueError, + "invalid type in format string for string, expected 's', but got " & + spec.typ) if spec.precision != -1: if spec.precision < runeLen(value): - setLen(value, runeOffset(value, spec.precision)) + let precision = cast[Natural](spec.precision) + setLen(value, Natural(runeOffset(value, precision))) + result.add alignString(value, spec.minimumWidth, spec.align, spec.fill) +proc formatValue[T: not SomeInteger](result: var string; value: T; specifier: static string) = + mixin `$` + formatValue(result, $value, specifier) + proc formatValue[T: not SomeInteger](result: var string; value: T; specifier: string) = mixin `$` formatValue(result, $value, specifier) @@ -667,7 +731,6 @@ proc strformatImpl(f: string; openChar, closeChar: char, inc i, 2 else: raiseAssert "invalid format string: '$1' instead of '$1$1'" % $closeChar - inc i else: strlit.add f[i] inc i diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim index c8cd839be..a3e539e7e 100644 --- a/lib/pure/strmisc.nim +++ b/lib/pure/strmisc.nim @@ -27,20 +27,17 @@ func expandTabs*(s: string, tabSize: int = 8): string = doAssert expandTabs("a\tb\n\txy\t", 3) == "a b\n xy " result = newStringOfCap(s.len + s.len shr 2) - var pos = 0 template addSpaces(n) = - for j in 0 ..< n: + for _ in 1..n: result.add(' ') - pos += 1 + pos += n - for i in 0 ..< len(s): - let c = s[i] + var pos = 0 + let denominator = if tabSize > 0: tabSize else: 1 + for c in s: if c == '\t': - let - denominator = if tabSize > 0: tabSize else: 1 - numSpaces = tabSize - pos mod denominator - + let numSpaces = tabSize - pos mod denominator addSpaces(numSpaces) else: result.add(c) diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim index 0b23abc28..16ef9e642 100644 --- a/lib/pure/strscans.nim +++ b/lib/pure/strscans.nim @@ -94,7 +94,7 @@ which we then use in our scanf pattern to help us in the matching process: ... ``` -It also possible to pass arguments to a user definable matcher: +It is also possible to pass arguments to a user definable matcher: ```nim proc ndigits(input: string; intVal: var int; start: int; n: int): int = @@ -283,7 +283,7 @@ efficiency and perform different checks. ]## -import macros, parseutils +import std/[macros, parseutils] import std/private/since when defined(nimPreviewSlimSystem): diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 11d5015cb..4b07aca5a 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -51,7 +51,7 @@ runnableExamples: import std/private/since import - hashes, strutils + std/[hashes, strutils] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 7ab3d37c8..81be7db17 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -70,12 +70,12 @@ runnableExamples: ## easier substring extraction than regular expressions -import parseutils -from math import pow, floor, log10 -from algorithm import fill, reverse +import std/parseutils +from std/math import pow, floor, log10 +from std/algorithm import fill, reverse import std/enumutils -from unicode import toLower, toUpper +from std/unicode import toLower, toUpper export toLower, toUpper include "system/inclrtl" @@ -334,9 +334,9 @@ func normalize*(s: string): string {.rtl, extern: "nsuNormalize".} = func cmpIgnoreCase*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreCase".} = ## Compares two strings in a case insensitive manner. Returns: ## - ## | 0 if a == b - ## | < 0 if a < b - ## | > 0 if a > b + ## | `0` if a == b + ## | `< 0` if a < b + ## | `> 0` if a > b runnableExamples: doAssert cmpIgnoreCase("FooBar", "foobar") == 0 doAssert cmpIgnoreCase("bar", "Foo") < 0 @@ -354,9 +354,9 @@ func cmpIgnoreStyle*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreStyle".} = ## ## Returns: ## - ## | 0 if a == b - ## | < 0 if a < b - ## | > 0 if a > b + ## | `0` if a == b + ## | `< 0` if a < b + ## | `> 0` if a > b runnableExamples: doAssert cmpIgnoreStyle("foo_bar", "FooBar") == 0 doAssert cmpIgnoreStyle("foo_bar_5", "FooBar4") > 0 @@ -565,7 +565,7 @@ iterator rsplit*(s: string, sep: char, maxsplit: int = -1): string = ## Splits the string `s` into substrings from the right using a ## string separator. Works exactly the same as `split iterator - ## <#split.i,string,char,int>`_ except in reverse order. + ## <#split.i,string,char,int>`_ except in **reverse** order. ## ## ```nim ## for piece in "foo:bar".rsplit(':'): @@ -592,7 +592,7 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): string = ## Splits the string `s` into substrings from the right using a ## string separator. Works exactly the same as `split iterator - ## <#split.i,string,char,int>`_ except in reverse order. + ## <#split.i,string,char,int>`_ except in **reverse** order. ## ## ```nim ## for piece in "foo bar".rsplit(WhiteSpace): @@ -622,7 +622,7 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1, keepSeparators: bool = false): string = ## Splits the string `s` into substrings from the right using a ## string separator. Works exactly the same as `split iterator - ## <#split.i,string,string,int>`_ except in reverse order. + ## <#split.i,string,string,int>`_ except in **reverse** order. ## ## ```nim ## for piece in "foothebar".rsplit("the"): @@ -805,7 +805,7 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl, func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl, extern: "nsuRSplitChar".} = ## The same as the `rsplit iterator <#rsplit.i,string,char,int>`_, but is a func - ## that returns a sequence of substrings. + ## that returns a sequence of substrings in original order. ## ## A possible common use case for `rsplit` is path manipulation, ## particularly on systems that don't use a common delimiter. @@ -835,7 +835,7 @@ func rsplit*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[string] {.rtl, extern: "nsuRSplitCharSet".} = ## The same as the `rsplit iterator <#rsplit.i,string,set[char],int>`_, but is a - ## func that returns a sequence of substrings. + ## func that returns a sequence of substrings in original order. ## ## A possible common use case for `rsplit` is path manipulation, ## particularly on systems that don't use a common delimiter. @@ -867,7 +867,7 @@ func rsplit*(s: string, seps: set[char] = Whitespace, func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl, extern: "nsuRSplitString".} = ## The same as the `rsplit iterator <#rsplit.i,string,string,int,bool>`_, but is a func - ## that returns a sequence of substrings. + ## that returns a sequence of substrings in original order. ## ## A possible common use case for `rsplit` is path manipulation, ## particularly on systems that don't use a common delimiter. @@ -1307,7 +1307,7 @@ func parseEnum*[T: enum](s: string): T = ## type contains multiple fields with the same string value. ## ## Raises `ValueError` for an invalid value in `s`. The comparison is - ## done in a style insensitive way. + ## done in a style insensitive way (first letter is still case-sensitive). runnableExamples: type MyEnum = enum @@ -1327,7 +1327,7 @@ func parseEnum*[T: enum](s: string, default: T): T = ## type contains multiple fields with the same string value. ## ## Uses `default` for an invalid value in `s`. The comparison is done in a - ## style insensitive way. + ## style insensitive way (first letter is still case-sensitive). runnableExamples: type MyEnum = enum @@ -1875,7 +1875,7 @@ func join*(a: openArray[string], sep: string = ""): string {.rtl, else: result = "" -func join*[T: not string](a: openArray[T], sep: string = ""): string = +proc join*[T: not string](a: openArray[T], sep: string = ""): string = ## Converts all elements in the container `a` to strings using `$`, ## and concatenates them with `sep`. runnableExamples: @@ -2281,17 +2281,31 @@ func replaceWord*(s, sub: string, by = ""): string {.rtl, add result, substr(s, i) func multiReplace*(s: string, replacements: varargs[(string, string)]): string = - ## Same as replace, but specialized for doing multiple replacements in a single - ## pass through the input string. + ## Same as `replace<#replace,string,string,string>`_, but specialized for + ## doing multiple replacements in a single pass through the input string. ## - ## `multiReplace` performs all replacements in a single pass, this means it - ## can be used to swap the occurrences of "a" and "b", for instance. + ## `multiReplace` scans the input string from left to right and replaces the + ## matching substrings in the same order as passed in the argument list. + ## + ## The implications of the order of scanning the string and matching the + ## replacements: + ## - In case of multiple matches at a given position, the earliest + ## replacement is applied. + ## - Overlaps are not handled. After performing a replacement, the scan + ## continues from the character after the matched substring. If the + ## resulting string then contains a possible match starting in a newly + ## placed substring, the additional replacement is not performed. ## ## If the resulting string is not longer than the original input string, ## only a single memory allocation is required. ## - ## The order of the replacements does matter. Earlier replacements are - ## preferred over later replacements in the argument list. + runnableExamples: + # Swapping occurrences of 'a' and 'b': + doAssert multireplace("abba", [("a", "b"), ("b", "a")]) == "baab" + + # The second replacement ("ab") is matched and performed first, the scan then + # continues from 'c', so the "bc" replacement is never matched and thus skipped. + doAssert multireplace("abc", [("bc", "x"), ("ab", "_b")]) == "_bc" result = newStringOfCap(s.len) var i = 0 var fastChk: set[char] = {} @@ -2440,8 +2454,8 @@ func validIdentifier*(s: string): bool {.rtl, extern: "nsuValidIdentifier".} = # floating point formatting: when not defined(js): - func c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", - importc: "sprintf", varargs.} + func c_snprintf(buf: cstring, n: csize_t, frmt: cstring): cint {.header: "<stdio.h>", + importc: "snprintf", varargs.} type FloatFormatMode* = enum @@ -2474,7 +2488,7 @@ func formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault, when defined(js): var precision = precision if precision == -1: - # use the same default precision as c_sprintf + # use the same default precision as c_snprintf precision = 6 var res: cstring case format @@ -2505,11 +2519,11 @@ func formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault, frmtstr[3] = '*' frmtstr[4] = floatFormatToChar[format] frmtstr[5] = '\0' - L = c_sprintf(cast[cstring](addr buf), cast[cstring](addr frmtstr), precision, f) + L = c_snprintf(cast[cstring](addr buf), csize_t(2501), cast[cstring](addr frmtstr), precision, f) else: frmtstr[1] = floatFormatToChar[format] frmtstr[2] = '\0' - L = c_sprintf(cast[cstring](addr buf), cast[cstring](addr frmtstr), f) + L = c_snprintf(cast[cstring](addr buf), csize_t(2501), cast[cstring](addr frmtstr), f) result = newString(L) for i in 0 ..< L: # Depending on the locale either dot or comma is produced, diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim index d8e00d1f8..90ba20c13 100644 --- a/lib/pure/sugar.nim +++ b/lib/pure/sugar.nim @@ -11,7 +11,7 @@ ## macro system. import std/private/since -import macros +import std/macros proc checkPragma(ex, prag: var NimNode) = since (1, 3): @@ -203,7 +203,7 @@ proc freshIdentNodes(ast: NimNode): NimNode = # see also https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458 proc inspect(node: NimNode): NimNode = case node.kind: - of nnkIdent, nnkSym: + of nnkIdent, nnkSym, nnkOpenSymChoice, nnkClosedSymChoice, nnkOpenSym: result = ident($node) of nnkEmpty, nnkLiterals: result = node @@ -345,9 +345,10 @@ proc collectImpl(init, body: NimNode): NimNode {.since: (1, 1).} = let res = genSym(nskVar, "collectResult") var bracketExpr: NimNode if init != nil: - expectKind init, {nnkCall, nnkIdent, nnkSym} + expectKind init, {nnkCall, nnkIdent, nnkSym, nnkClosedSymChoice, nnkOpenSymChoice, nnkOpenSym} bracketExpr = newTree(nnkBracketExpr, - if init.kind == nnkCall: freshIdentNodes(init[0]) else: freshIdentNodes(init)) + if init.kind in {nnkCall, nnkClosedSymChoice, nnkOpenSymChoice, nnkOpenSym}: + freshIdentNodes(init[0]) else: freshIdentNodes(init)) else: bracketExpr = newTree(nnkBracketExpr) let (resBody, keyType, valueType) = trans(body, res, bracketExpr) diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 4177eb002..53b3d61da 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -58,13 +58,13 @@ runnableExamples("-r:off"): stdout.styledWriteLine(fgRed, "red text ", styleBright, "bold red", fgDefault, " bold text") -import macros -import strformat -from strutils import toLowerAscii, `%` -import colors +import std/macros +import std/strformat +from std/strutils import toLowerAscii, `%`, parseInt +import std/colors when defined(windows): - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/[syncio, assertions] @@ -96,10 +96,11 @@ const fgPrefix = "\e[38;2;" bgPrefix = "\e[48;2;" ansiResetCode* = "\e[0m" + getPos = "\e[6n" stylePrefix = "\e[" when defined(windows): - import winlean, os + import std/[winlean, os] const DUPLICATE_SAME_ACCESS = 2 @@ -220,6 +221,9 @@ when defined(windows): raiseOSError(osLastError()) return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y)) + proc getCursorPos*(): tuple [x, y: int] {.raises: [ValueError, IOError, OSError].} = + return getCursorPos(getStdHandle(STD_OUTPUT_HANDLE)) + proc setCursorPos(h: Handle, x, y: int) = var c: COORD c.x = int16(x) @@ -253,7 +257,7 @@ when defined(windows): if f == stderr: term.hStderr else: term.hStdout else: - import termios, posix, os, parseutils + import std/[termios, posix, os, parseutils] proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) = var mode: Termios @@ -267,6 +271,48 @@ else: mode.c_cc[VTIME] = 0.cuchar discard fd.tcSetAttr(time, addr mode) + proc getCursorPos*(): tuple [x, y: int] {.raises: [ValueError, IOError].} = + ## Returns cursor position (x, y) + ## writes to stdout and expects the terminal to respond via stdin + var + xStr = "" + yStr = "" + ch: char + ct: int + readX = false + + # use raw mode to ask terminal for cursor position + let fd = getFileHandle(stdin) + var oldMode: Termios + discard fd.tcGetAttr(addr oldMode) + fd.setRaw() + stdout.write(getPos) + flushFile(stdout) + + try: + # parse response format: [yyy;xxxR + while true: + let n = readBuffer(stdin, addr ch, 1) + if n == 0 or ch == 'R': + if xStr == "" or yStr == "": + raise newException(ValueError, "Got character position message that was missing data") + break + ct += 1 + if ct > 16: + raise newException(ValueError, "Got unterminated character position message from terminal") + if ch == ';': + readX = true + elif ch in {'0'..'9'}: + if readX: + xStr.add(ch) + else: + yStr.add(ch) + finally: + # restore previous terminal mode + discard fd.tcSetAttr(TCSADRAIN, addr oldMode) + + return (parseInt(xStr), parseInt(yStr)) + proc terminalWidthIoctl*(fds: openArray[int]): int = ## Returns terminal width from first fd that supports the ioctl. @@ -876,7 +922,7 @@ when defined(windows): stdout.write "\n" else: - import termios + import std/termios proc readPasswordFromStdin*(prompt: string, password: var string): bool {.tags: [ReadIOEffect, WriteIOEffect].} = @@ -932,7 +978,7 @@ proc isTrueColorSupported*(): bool = return getTerminal().trueColorIsSupported when defined(windows): - import os + import std/os proc enableTrueColors*() = ## Enables true color. diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 9c32c7b21..e59153455 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -131,9 +131,10 @@ =========== ================================================================================= ============================================== Other strings can be inserted by putting them in `''`. For example - `hh'->'mm` will give `01->56`. The following characters can be - inserted without quoting them: `:` `-` `(` `)` `/` `[` `]` - `,`. A literal `'` can be specified with `''`. + `hh'->'mm` will give `01->56`. In addition to spaces, + the following characters can be inserted without quoting them: + `:` `-` `,` `.` `(` `)` `/` `[` `]`. + A literal `'` can be specified with `''`. However you don't need to necessarily separate format patterns, as an unambiguous format string like `yyyyMMddhhmmss` is also valid (although @@ -203,7 +204,7 @@ * `monotimes module <monotimes.html>`_ ]## -import strutils, math, options +import std/[strutils, math, options] import std/private/since include "system/inclrtl" @@ -213,7 +214,7 @@ when defined(nimPreviewSlimSystem): when defined(js): - import jscore + import std/jscore # This is really bad, but overflow checks are broken badly for # ints on the JS backend. See #6752. @@ -237,7 +238,7 @@ when defined(js): {.pop.} elif defined(posix): - import posix + import std/posix type CTime = posix.Time @@ -246,7 +247,7 @@ elif defined(posix): {.importc: "gettimeofday", header: "<sys/time.h>", sideEffect.} elif defined(windows): - import winlean, std/time_t + import std/winlean, std/time_t type CTime = time_t.Time @@ -1498,11 +1499,11 @@ proc `-=`*(a: var DateTime, b: Duration) = a = a - b proc getDateStr*(dt = now()): string {.rtl, extern: "nt$1", tags: [TimeEffect].} = - ## Gets the current local date as a string of the format `YYYY-MM-DD`. + ## Gets the current local date as a string of the format `YYYY-MM-dd`. runnableExamples: echo getDateStr(now() - 1.months) assertDateTimeInitialized dt - result = newStringOfCap(10) # len("YYYY-MM-DD") == 10 + result = newStringOfCap(10) # len("YYYY-MM-dd") == 10 result.addInt dt.year result.add '-' result.add intToStr(dt.monthZero, 2) @@ -1631,7 +1632,7 @@ const "Sunday"], ) - FormatLiterals = {' ', '-', '/', ':', '(', ')', '[', ']', ','} + FormatLiterals = {' ', '-', '/', ':', '(', ')', '[', ']', ',', '.'} proc `$`*(f: TimeFormat): string = ## Returns the format string that was used to construct `f`. @@ -2787,7 +2788,9 @@ proc epochTime*(): float {.tags: [TimeEffect].} = ## ## .. warning:: Unsuitable for benchmarking (but still better than `now`), ## use `monotimes.getMonoTime` or `cpuTime` instead, depending on the use case. - when defined(macosx): + when defined(js): + result = newDate().getTime() / 1000 + elif defined(macosx): var a {.noinit.}: Timeval gettimeofday(a) result = toBiggestFloat(a.tv_sec.int64) + toBiggestFloat( @@ -2804,8 +2807,6 @@ proc epochTime*(): float {.tags: [TimeEffect].} = var secs = i64 div rateDiff var subsecs = i64 mod rateDiff result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001 - elif defined(js): - result = newDate().getTime() / 1000 else: {.error: "unknown OS".} diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 384c2dbac..78af84fdd 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -130,6 +130,40 @@ template pointerBase*[T](_: typedesc[ptr T | ref T]): typedesc = assert (var s = "abc"; s[0].addr).typeof.pointerBase is char T +proc rangeBase*(T: typedesc[range]): typedesc {.magic: "TypeTrait".} = + ## Returns the base type for range types, or the type itself otherwise. + ## + ## **See also:** + ## * `rangeBase template <#rangeBase.t,T>`_ + runnableExamples: + type MyRange = range[0..5] + type MyEnum = enum a, b, c + type MyEnumRange = range[b..c] + doAssert rangeBase(MyRange) is int + doAssert rangeBase(MyEnumRange) is MyEnum + doAssert rangeBase(range['a'..'z']) is char + +template rangeBase*[T: range](a: T): untyped = + ## Overload of `rangeBase <#rangeBase,typedesc,static[bool]>`_ for values. + runnableExamples: + type MyRange = range[0..5] + type MyEnum = enum a, b, c + type MyEnumRange = range[b..c] + let x = MyRange(3) + doAssert rangeBase(x) is int + doAssert $typeof(rangeBase(x)) == "int" + doAssert rangeBase(x) == 3 + let y: set[MyEnumRange] = {c} + for e in y: + doAssert rangeBase(e) is MyEnum + doAssert $typeof(rangeBase(e)) == "MyEnum" + doAssert rangeBase(e) == c + let z: seq[range['a'..'z']] = @['c'] + doAssert rangeBase(z[0]) is char + doAssert $typeof(rangeBase(z[0])) == "char" + doAssert rangeBase(z[0]) == 'c' + rangeBase(typeof(T))(a) + proc distinctBase*(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".} = ## Returns the base type for distinct types, or the type itself otherwise. ## If `recursive` is false, only the immediate distinct base will be returned. @@ -204,7 +238,7 @@ since (1, 3, 5): typeof(block: (for ai in a: ai)) -import macros +import std/macros macro enumLen*(T: typedesc[enum]): int = ## Returns the number of items in the enum `T`. diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index c8d18831a..8cbe117bb 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -464,7 +464,7 @@ proc `==`*(a, b: Rune): bool = include "includes/unicode_ranges" -proc binarySearch(c: RuneImpl, tab: openArray[int], len, stride: int): int = +proc binarySearch(c: RuneImpl, tab: openArray[int32], len, stride: int): int = var n = len var t = 0 while n > 1: @@ -836,9 +836,9 @@ proc toRunes*(s: openArray[char]): seq[Rune] = proc cmpRunesIgnoreCase*(a, b: openArray[char]): int {.rtl, extern: "nuc$1".} = ## Compares two UTF-8 strings and ignores the case. Returns: ## - ## | 0 if a == b - ## | < 0 if a < b - ## | > 0 if a > b + ## | `0` if a == b + ## | `< 0` if a < b + ## | `> 0` if a > b var i = 0 var j = 0 var ar, br: Rune @@ -846,7 +846,12 @@ proc cmpRunesIgnoreCase*(a, b: openArray[char]): int {.rtl, extern: "nuc$1".} = # slow path: fastRuneAt(a, i, ar) fastRuneAt(b, j, br) - result = RuneImpl(toLower(ar)) - RuneImpl(toLower(br)) + when sizeof(int) < 4: + const lo = low(int).int32 + const hi = high(int).int32 + result = clamp(RuneImpl(toLower(ar)) - RuneImpl(toLower(br)), lo, hi).int + else: + result = RuneImpl(toLower(ar)) - RuneImpl(toLower(br)) if result != 0: return result = a.len - b.len @@ -1370,9 +1375,9 @@ proc toRunes*(s: string): seq[Rune] {.inline.} = proc cmpRunesIgnoreCase*(a, b: string): int {.inline.} = ## Compares two UTF-8 strings and ignores the case. Returns: ## - ## | 0 if a == b - ## | < 0 if a < b - ## | > 0 if a > b + ## | `0` if a == b + ## | `< 0` if a < b + ## | `> 0` if a > b cmpRunesIgnoreCase(a.toOa(), b.toOa()) proc reversed*(s: string): string {.inline.} = diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index a6b01d644..cfb762258 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -111,15 +111,15 @@ import std/exitprocs when defined(nimPreviewSlimSystem): import std/assertions -import macros, strutils, streams, times, sets, sequtils +import std/[macros, strutils, streams, times, sets, sequtils] when declared(stdout): - import os + import std/os const useTerminal = not defined(js) when useTerminal: - import terminal + import std/terminal type TestStatus* = enum ## The status of a test when it is done. @@ -773,7 +773,8 @@ macro expect*(exceptions: varargs[typed], body: untyped): untyped = except errorTypes: discard except: - checkpoint(lineInfoLit & ": Expect Failed, unexpected exception was thrown.") + let err = getCurrentException() + checkpoint(lineInfoLit & ": Expect Failed, " & $err.name & " was thrown.") fail() {.pop.} diff --git a/lib/pure/volatile.nim b/lib/pure/volatile.nim index f30d899df..a38247c7d 100644 --- a/lib/pure/volatile.nim +++ b/lib/pure/volatile.nim @@ -10,20 +10,18 @@ ## This module contains code for generating volatile loads and stores, ## which are useful in embedded and systems programming. -template volatileLoad*[T](src: ptr T): T = +proc volatileLoad*[T](src: ptr T): T {.inline, noinit.} = ## Generates a volatile load of the value stored in the container `src`. ## Note that this only effects code generation on `C` like backends. when nimvm: - src[] + result = src[] else: when defined(js): - src[] + result = src[] else: - var res: T - {.emit: [res, " = (*(", typeof(src[]), " volatile*)", src, ");"].} - res + {.emit: [result, " = (*(", typeof(src[]), " volatile*)", src, ");"].} -template volatileStore*[T](dest: ptr T, val: T) = +proc volatileStore*[T](dest: ptr T, val: T) {.inline.} = ## Generates a volatile store into the container `dest` of the value ## `val`. Note that this only effects code generation on `C` like ## backends. diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index 6785fa66e..2c1e4e37c 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -9,7 +9,7 @@ ## This module parses an XML document and creates its XML tree representation. -import streams, parsexml, strtabs, xmltree +import std/[streams, parsexml, strtabs, xmltree] when defined(nimPreviewSlimSystem): import std/syncio @@ -151,7 +151,7 @@ proc loadXml*(path: string, options: set[XmlParseOption] = {reportComments}): Xm when isMainModule: when not defined(testing): - import os + import std/os var errors: seq[string] = @[] var x = loadXml(paramStr(1), errors) diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index e4cd407e2..5c0cbc5e4 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -31,7 +31,7 @@ runnableExamples: ## * `htmlgen module <htmlgen.html>`_ for html code generator import std/private/since -import macros, strtabs, strutils, sequtils +import std/[macros, strtabs, strutils, sequtils] when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/std/cmdline.nim b/lib/std/cmdline.nim index e545ac599..0ba4619e5 100644 --- a/lib/std/cmdline.nim +++ b/lib/std/cmdline.nim @@ -30,9 +30,9 @@ const weirdTarget = defined(nimscript) or defined(js) when weirdTarget: discard elif defined(windows): - import winlean + import std/winlean elif defined(posix): - import posix + import std/posix else: {.error: "The cmdline module has not been implemented for the target platform.".} @@ -138,7 +138,7 @@ proc parseCmdLine*(c: string): seq[string] {. while i < c.len and c[i] > ' ': add(a, c[i]) inc(i) - add(result, a) + add(result, move a) when defined(nimdoc): # Common forward declaration docstring block for parameter retrieval procs. @@ -181,7 +181,7 @@ when defined(nimdoc): ## Similarly to `argv`:idx: in C, ## it is possible to call `paramStr(0)` but this will return OS specific ## contents (usually the name of the invoked executable). You should avoid - ## this and call `getAppFilename()`_ instead. + ## this and call `getAppFilename() <os.html#getAppFilename>`_ instead. ## ## **Availability**: When generating a dynamic library (see `--app:lib`) on ## Posix this proc is not defined. @@ -192,7 +192,7 @@ when defined(nimdoc): ## * `parseCmdLine proc`_ ## * `paramCount proc`_ ## * `commandLineParams proc`_ - ## * `getAppFilename proc`_ + ## * `getAppFilename proc <os.html#getAppFilename>`_ ## ## **Examples:** ## @@ -282,7 +282,7 @@ when declared(paramCount) or defined(nimdoc): ## Convenience proc which returns the command line parameters. ## ## This returns **only** the parameters. If you want to get the application - ## executable filename, call `getAppFilename()`_. + ## executable filename, call `getAppFilename() <os.html#getAppFilename>`_. ## ## **Availability**: On Posix there is no portable way to get the command ## line from a DLL and thus the proc isn't defined in this environment. You @@ -294,7 +294,7 @@ when declared(paramCount) or defined(nimdoc): ## * `parseCmdLine proc`_ ## * `paramCount proc`_ ## * `paramStr proc`_ - ## * `getAppFilename proc`_ + ## * `getAppFilename proc <os.html#getAppFilename>`_ ## ## **Examples:** ## diff --git a/lib/std/decls.nim b/lib/std/decls.nim index 3f774cd08..bb7ec3593 100644 --- a/lib/std/decls.nim +++ b/lib/std/decls.nim @@ -1,6 +1,6 @@ ## This module implements syntax sugar for some declarations. -import macros +import std/macros macro byaddr*(sect) = ## Allows a syntax for l-value references, being an exact analog to diff --git a/lib/std/dirs.nim b/lib/std/dirs.nim index 0b0366d44..380d6d08f 100644 --- a/lib/std/dirs.nim +++ b/lib/std/dirs.nim @@ -1,6 +1,6 @@ ## This module implements directory handling. -from paths import Path, ReadDirEffect, WriteDirEffect +from std/paths import Path, ReadDirEffect, WriteDirEffect from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir, moveDir, walkDir, setCurrentDir, diff --git a/lib/std/editdistance.nim b/lib/std/editdistance.nim index 9f29c5c05..40c0017ae 100644 --- a/lib/std/editdistance.nim +++ b/lib/std/editdistance.nim @@ -10,7 +10,7 @@ ## This module implements an algorithm to compute the ## `edit distance`:idx: between two Unicode strings. -import unicode +import std/unicode proc editDistance*(a, b: string): int {.noSideEffect.} = ## Returns the **unicode-rune** edit distance between `a` and `b`. @@ -18,7 +18,7 @@ proc editDistance*(a, b: string): int {.noSideEffect.} = ## This uses the `Levenshtein`:idx: distance algorithm with only a linear ## memory overhead. runnableExamples: static: doAssert editdistance("Kitten", "Bitten") == 1 - if len(a) > len(b): + if runeLen(a) > runeLen(b): # make `b` the longer string return editDistance(b, a) # strip common prefix diff --git a/lib/std/effecttraits.nim b/lib/std/effecttraits.nim index fb057a669..3d1b4ffd3 100644 --- a/lib/std/effecttraits.nim +++ b/lib/std/effecttraits.nim @@ -14,7 +14,7 @@ ## One can test for the existence of this standard module ## via `defined(nimHasEffectTraitsModule)`. -import macros +import std/macros proc getRaisesListImpl(n: NimNode): NimNode = discard "see compiler/vmops.nim" proc getTagsListImpl(n: NimNode): NimNode = discard "see compiler/vmops.nim" diff --git a/lib/std/enumerate.nim b/lib/std/enumerate.nim index 4f0161b7c..beb65ed30 100644 --- a/lib/std/enumerate.nim +++ b/lib/std/enumerate.nim @@ -11,7 +11,7 @@ ## macro system. import std/private/since -import macros +import std/macros macro enumerate*(x: ForLoopStmt): untyped {.since: (1, 3).} = diff --git a/lib/std/enumutils.nim b/lib/std/enumutils.nim index 0386c2589..9c338817d 100644 --- a/lib/std/enumutils.nim +++ b/lib/std/enumutils.nim @@ -7,8 +7,8 @@ # distribution, for details about the copyright. # -import macros -from typetraits import OrdinalEnum, HoleyEnum +import std/macros +from std/typetraits import OrdinalEnum, HoleyEnum when defined(nimPreviewSlimSystem): import std/assertions @@ -22,7 +22,8 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed, # a normalized string comparison to the `argSym` input. # string normalization is done using passed normalizer. let typ = typ.getTypeInst[1] - let impl = typ.getImpl[2] + let typSym = typ.getTypeImpl.getTypeInst # skip aliases etc to get type sym + let impl = typSym.getImpl[2] expectKind impl, nnkEnumTy let normalizerNode = quote: `normalizer` expectKind normalizerNode, nnkSym @@ -81,7 +82,7 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed, result.add nnkElse.newTree(default) macro enumFullRange(a: typed): untyped = - newNimNode(nnkCurly).add(a.getType[1][1..^1]) + newNimNode(nnkBracket).add(a.getType[1][1..^1]) macro enumNames(a: typed): untyped = # this could be exported too; in particular this could be useful for enum with holes. @@ -173,6 +174,9 @@ template symbolRank*[T: enum](a: T): int = when T is Ordinal: ord(a) - T.low.ord.static else: symbolRankImpl(a) +proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".} + # skip one level of range; return the base type of a range type + func symbolName*[T: enum](a: T): string = ## Returns the symbol name of an enum. ## @@ -191,5 +195,8 @@ func symbolName*[T: enum](a: T): string = c1 = 4 c2 = 20 assert c1.symbolName == "c1" - const names = enumNames(T) + when T is range: + const names = enumNames(rangeBase T) + else: + const names = enumNames(T) names[a.symbolRank] diff --git a/lib/std/envvars.nim b/lib/std/envvars.nim index ab5c9f06e..a955077ea 100644 --- a/lib/std/envvars.nim +++ b/lib/std/envvars.nim @@ -60,7 +60,7 @@ when not defined(nimscript): when defined(windows): proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".} from std/private/win_setenv import setEnvImpl - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/widestrs diff --git a/lib/std/exitprocs.nim b/lib/std/exitprocs.nim index e42397c4c..f26368f42 100644 --- a/lib/std/exitprocs.nim +++ b/lib/std/exitprocs.nim @@ -9,7 +9,7 @@ ## This module allows adding hooks to program exit. -import locks +import std/locks when defined(js) and not defined(nodejs): import std/assertions @@ -29,13 +29,13 @@ initLock(gFunsLock) when defined(js): proc addAtExit(quitProc: proc() {.noconv.}) = when defined(nodejs): - asm """ + {.emit: """ process.on('exit', `quitProc`); - """ + """.} elif defined(js): - asm """ + {.emit: """ window.onbeforeunload = `quitProc`; - """ + """.} else: proc addAtExit(quitProc: proc() {.noconv.}) {. importc: "atexit", header: "<stdlib.h>".} @@ -72,16 +72,16 @@ proc addExitProc*(cl: proc() {.noconv.}) = when not defined(nimscript) and (not defined(js) or defined(nodejs)): proc getProgramResult*(): int = when defined(js) and defined(nodejs): - asm """ + {.emit: """ `result` = process.exitCode; -""" +""".} else: result = programResult proc setProgramResult*(a: int) = when defined(js) and defined(nodejs): - asm """ + {.emit: """ process.exitCode = `a`; -""" +""".} else: programResult = a diff --git a/lib/std/files.nim b/lib/std/files.nim index b61b7dafd..c4e0491c9 100644 --- a/lib/std/files.nim +++ b/lib/std/files.nim @@ -3,7 +3,7 @@ ## **See also:** ## * `paths module <paths.html>`_ for path manipulation -from paths import Path, ReadDirEffect, WriteDirEffect +from std/paths import Path, ReadDirEffect, WriteDirEffect from std/private/osfiles import fileExists, removeFile, moveFile diff --git a/lib/std/formatfloat.nim b/lib/std/formatfloat.nim index 48973aa55..9258245f6 100644 --- a/lib/std/formatfloat.nim +++ b/lib/std/formatfloat.nim @@ -35,8 +35,8 @@ proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int result = float32ToChars(buf, value, forceTrailingDotZero=true).int buf[result] = '\0' -proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", - importc: "sprintf", varargs, noSideEffect.} +proc c_snprintf(buf: cstring, n: csize_t, frmt: cstring): cint {.header: "<stdio.h>", + importc: "snprintf", varargs, noSideEffect.} proc writeToBuffer(buf: var array[65, char]; value: cstring) = var i = 0 @@ -49,7 +49,7 @@ proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): ## ## returns the amount of bytes written to `buf` not counting the ## terminating '\0' character. - var n = c_sprintf(cast[cstring](addr buf), "%.16g", value).int + var n = c_snprintf(cast[cstring](addr buf), 65, "%.16g", value).int var hasDot = false for i in 0..n-1: if buf[i] == ',': @@ -100,22 +100,23 @@ proc addFloatSprintf*(result: var string; x: float) = let n = writeFloatToBufferSprintf(buffer, x) result.addCstringN(cast[cstring](buffer[0].addr), n) -proc nimFloatToString(a: float): cstring = - ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2 - # print `-0.0` properly - asm """ - function nimOnlyDigitsOrMinus(n) { - return n.toString().match(/^-?\d+$/); - } - if (Number.isSafeInteger(`a`)) - `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0" - else { - `result` = `a`+"" - if(nimOnlyDigitsOrMinus(`result`)){ - `result` = `a`+".0" +when defined(js): + proc nimFloatToString(a: float): cstring = + ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2 + # print `-0.0` properly + {.emit: """ + function nimOnlyDigitsOrMinus(n) { + return n.toString().match(/^-?\d+$/); } - } - """ + if (Number.isSafeInteger(`a`)) + `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0"; + else { + `result` = `a`+""; + if(nimOnlyDigitsOrMinus(`result`)){ + `result` = `a`+".0"; + } + } + """.} proc addFloat*(result: var string; x: float | float32) {.inline.} = ## Converts float to its string representation and appends it to `result`. diff --git a/lib/std/genasts.nim b/lib/std/genasts.nim index 04257533d..d0f07c527 100644 --- a/lib/std/genasts.nim +++ b/lib/std/genasts.nim @@ -1,6 +1,6 @@ ## This module implements AST generation using captured variables for macros. -import macros +import std/macros type GenAstOpt* = enum kDirtyTemplate, diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim index b1025d24b..2d28748ce 100644 --- a/lib/std/jsonutils.nim +++ b/lib/std/jsonutils.nim @@ -16,7 +16,7 @@ runnableExamples: assert 0.0.toJson.kind == JFloat assert Inf.toJson.kind == JString -import json, strutils, tables, sets, strtabs, options, strformat +import std/[json, strutils, tables, sets, strtabs, options, strformat] #[ Future directions: @@ -30,9 +30,9 @@ add a way to customize serialization, for e.g.: objects. ]# -import macros -from enumutils import symbolName -from typetraits import OrdinalEnum, tupleLen +import std/macros +from std/enumutils import symbolName +from std/typetraits import OrdinalEnum, tupleLen when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/std/monotimes.nim b/lib/std/monotimes.nim index 5c67a5d4c..bf6dc776b 100644 --- a/lib/std/monotimes.nim +++ b/lib/std/monotimes.nim @@ -36,7 +36,7 @@ See also * `times module <times.html>`_ ]## -import times +import std/times type MonoTime* = object ## Represents a monotonic timestamp. @@ -74,7 +74,7 @@ when defined(js): {.pop.} elif defined(posix) and not defined(osx): - import posix + import std/posix when defined(zephyr): proc k_uptime_ticks(): int64 {.importc: "k_uptime_ticks", header: "<kernel.h>".} diff --git a/lib/std/oserrors.nim b/lib/std/oserrors.nim index a641a7f47..7b11c5e8e 100644 --- a/lib/std/oserrors.nim +++ b/lib/std/oserrors.nim @@ -15,7 +15,7 @@ type when not defined(nimscript): when defined(windows): - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/widestrs else: diff --git a/lib/std/outparams.nim b/lib/std/outparams.nim index 8a0e5ae67..a471fbaa7 100644 --- a/lib/std/outparams.nim +++ b/lib/std/outparams.nim @@ -9,7 +9,7 @@ ## `outParamsAt` macro for easy writing code that works with both 2.0 and 1.x. -import macros +import std/macros macro outParamsAt*(positions: static openArray[int]; n: untyped): untyped = ## Use this macro to annotate `out` parameters in a portable way. diff --git a/lib/std/packedsets.nim b/lib/std/packedsets.nim index c6d007c26..3320558f2 100644 --- a/lib/std/packedsets.nim +++ b/lib/std/packedsets.nim @@ -17,7 +17,7 @@ ## * `sets module <sets.html>`_ for more general hash sets import std/private/since -import hashes +import std/hashes when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/std/paths.nim b/lib/std/paths.nim index f675e7445..664dedd31 100644 --- a/lib/std/paths.nim +++ b/lib/std/paths.nim @@ -9,7 +9,7 @@ export osseps import std/envvars import std/private/osappdirs -import pathnorm +import std/[pathnorm, hashes, sugar, strutils] from std/private/ospaths2 import joinPath, splitPath, ReadDirEffect, WriteDirEffect, @@ -25,6 +25,16 @@ export ReadDirEffect, WriteDirEffect type Path* = distinct string +func hash*(x: Path): Hash = + let x = x.string.dup(normalizePath) + if FileSystemCaseSensitive: + result = x.hash + else: + result = x.toLowerAscii.hash + +template `$`*(x: Path): string = + string(x) + func `==`*(x, y: Path): bool {.inline.} = ## Compares two paths. ## diff --git a/lib/std/private/gitutils.nim b/lib/std/private/gitutils.nim index db323bee1..6dc9c8f3b 100644 --- a/lib/std/private/gitutils.nim +++ b/lib/std/private/gitutils.nim @@ -4,7 +4,7 @@ internal API for now, API subject to change # xxx move other git utilities here; candidate for stdlib. -import std/[os, osproc, strutils, tempfiles] +import std/[os, paths, osproc, strutils, tempfiles] when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -32,15 +32,8 @@ template retryCall*(maxRetry = 3, backoffDuration = 1.0, call: untyped): bool = result proc isGitRepo*(dir: string): bool = - ## This command is used to get the relative path to the root of the repository. - ## Using this, we can verify whether a folder is a git repository by checking - ## whether the command success and if the output is empty. - let (output, status) = execCmdEx("git rev-parse --show-cdup", workingDir = dir) - # On Windows there will be a trailing newline on success, remove it. - # The value of a successful call typically won't have a whitespace (it's - # usually a series of ../), so we know that it's safe to unconditionally - # remove trailing whitespaces from the result. - result = status == 0 and output.strip() == "" + ## Avoid calling git since it depends on /bin/sh existing and fails in Nix. + return fileExists(dir/".git/HEAD") proc diffFiles*(path1, path2: string): tuple[output: string, same: bool] = ## Returns a human readable diff of files `path1`, `path2`, the exact form of diff --git a/lib/std/private/globs.nim b/lib/std/private/globs.nim index 64065aac8..a6d088558 100644 --- a/lib/std/private/globs.nim +++ b/lib/std/private/globs.nim @@ -4,9 +4,9 @@ this can eventually be moved to std/os and `walkDirRec` can be implemented in te to avoid duplication ]## -import os +import std/os when defined(windows): - from strutils import replace + from std/strutils import replace when defined(nimPreviewSlimSystem): import std/[assertions, objectdollar] @@ -65,6 +65,6 @@ proc nativeToUnixPath*(path: string): string = result = replace(result, '\\', '/') when isMainModule: - import sugar + import std/sugar for a in walkDirRecFilter(".", follow = a=>a.path.lastPathPart notin ["nimcache", ".git", "csources_v1", "csources", "bin"]): echo a diff --git a/lib/std/private/jsutils.nim b/lib/std/private/jsutils.nim index fd1f395f3..5f79eab27 100644 --- a/lib/std/private/jsutils.nim +++ b/lib/std/private/jsutils.nim @@ -37,13 +37,13 @@ when defined(js): let a = array[2, float64].default assert jsConstructorName(a) == "Float64Array" assert jsConstructorName(a.toJs) == "Float64Array" - asm """`result` = `a`.constructor.name""" + {.emit: """`result` = `a`.constructor.name;""".} proc hasJsBigInt*(): bool = - asm """`result` = typeof BigInt != 'undefined'""" + {.emit: """`result` = typeof BigInt != 'undefined';""".} proc hasBigUint64Array*(): bool = - asm """`result` = typeof BigUint64Array != 'undefined'""" + {.emit: """`result` = typeof BigUint64Array != 'undefined';""".} proc getProtoName*[T](a: T): cstring {.importjs: "Object.prototype.toString.call(#)".} = runnableExamples: diff --git a/lib/std/private/oscommon.nim b/lib/std/private/oscommon.nim index c24db3f67..c49d52ef2 100644 --- a/lib/std/private/oscommon.nim +++ b/lib/std/private/oscommon.nim @@ -22,9 +22,9 @@ type when weirdTarget: discard elif defined(windows): - import winlean, times + import std/[winlean, times] elif defined(posix): - import posix + import std/posix proc c_rename(oldname, newname: cstring): cint {. importc: "rename", header: "<stdio.h>".} else: diff --git a/lib/std/private/osdirs.nim b/lib/std/private/osdirs.nim index a4318367d..a44cad7d9 100644 --- a/lib/std/private/osdirs.nim +++ b/lib/std/private/osdirs.nim @@ -16,9 +16,9 @@ when defined(nimPreviewSlimSystem): when weirdTarget: discard elif defined(windows): - import winlean, times + import std/[winlean, times] elif defined(posix): - import posix, times + import std/[posix, times] else: {.error: "OS module not ported to your operating system!".} @@ -446,13 +446,17 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", else: discard existsOrCreateDir(p) -proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", +proc copyDir*(source, dest: string, skipSpecial = false) {.rtl, extern: "nos$1", tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], benign, noWeirdTarget.} = ## Copies a directory from `source` to `dest`. ## ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks ## are skipped. ## + ## If `skipSpecial` is true, then (besides all directories) only *regular* + ## files (**without** special "file" objects like FIFOs, device files, + ## etc) will be copied on Unix. + ## ## If this fails, `OSError` is raised. ## ## On the Windows platform this proc will copy the attributes from @@ -472,16 +476,17 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", ## * `createDir proc`_ ## * `moveDir proc`_ createDir(dest) - for kind, path in walkDir(source): + for kind, path in walkDir(source, skipSpecial = skipSpecial): var noSource = splitPath(path).tail if kind == pcDir: - copyDir(path, dest / noSource) + copyDir(path, dest / noSource, skipSpecial = skipSpecial) else: copyFile(path, dest / noSource, {cfSymlinkAsIs}) proc copyDirWithPermissions*(source, dest: string, - ignorePermissionErrors = true) + ignorePermissionErrors = true, + skipSpecial = false) {.rtl, extern: "nos$1", tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], benign, noWeirdTarget.} = ## Copies a directory from `source` to `dest` preserving file permissions. @@ -489,6 +494,10 @@ proc copyDirWithPermissions*(source, dest: string, ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks ## are skipped. ## + ## If `skipSpecial` is true, then (besides all directories) only *regular* + ## files (**without** special "file" objects like FIFOs, device files, + ## etc) will be copied on Unix. + ## ## If this fails, `OSError` is raised. This is a wrapper proc around ## `copyDir`_ and `copyFileWithPermissions`_ procs ## on non-Windows platforms. @@ -518,10 +527,10 @@ proc copyDirWithPermissions*(source, dest: string, except: if not ignorePermissionErrors: raise - for kind, path in walkDir(source): + for kind, path in walkDir(source, skipSpecial = skipSpecial): var noSource = splitPath(path).tail if kind == pcDir: - copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors) + copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors, skipSpecial = skipSpecial) else: copyFileWithPermissions(path, dest / noSource, ignorePermissionErrors, {cfSymlinkAsIs}) diff --git a/lib/std/private/osfiles.nim b/lib/std/private/osfiles.nim index f2e7bf11d..37d8eabca 100644 --- a/lib/std/private/osfiles.nim +++ b/lib/std/private/osfiles.nim @@ -15,9 +15,9 @@ when defined(nimPreviewSlimSystem): when weirdTarget: discard elif defined(windows): - import winlean + import std/winlean elif defined(posix): - import posix, times + import std/[posix, times] proc toTime(ts: Timespec): times.Time {.inline.} = result = initTime(ts.tv_sec.int64, ts.tv_nsec.int) @@ -173,7 +173,7 @@ type const copyFlagSymlink = {cfSymlinkAsIs, cfSymlinkFollow, cfSymlinkIgnore} -proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl, +proc copyFile*(source, dest: string, options = {cfSymlinkFollow}; bufferSize = 16_384) {.rtl, extern: "nos$1", tags: [ReadDirEffect, ReadIOEffect, WriteIOEffect], noWeirdTarget.} = ## Copies a file from `source` to `dest`, where `dest.parentDir` must exist. @@ -202,6 +202,8 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl, ## On OSX, `copyfile` C api will be used (available since OSX 10.5) unless ## `-d:nimLegacyCopyFile` is used. ## + ## `copyFile` allows to specify `bufferSize` to improve I/O performance. + ## ## See also: ## * `CopyFlag enum`_ ## * `copyDir proc`_ @@ -210,8 +212,7 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl, ## * `removeFile proc`_ ## * `moveFile proc`_ - doAssert card(copyFlagSymlink * options) == 1, "There should be exactly " & - "one cfSymlink* in options" + doAssert card(copyFlagSymlink * options) == 1, "There should be exactly one cfSymlink* in options" let isSymlink = source.symlinkExists if isSymlink and (cfSymlinkIgnore in options or defined(windows)): return @@ -238,15 +239,21 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl, if status2 != 0: raiseOSError(osLastError(), $(source, dest)) else: # generic version of copyFile which works for any platform: - const bufSize = 8000 # better for memory manager var d, s: File - if not open(s, source):raiseOSError(osLastError(), source) + if not open(s, source): raiseOSError(osLastError(), source) if not open(d, dest, fmWrite): close(s) raiseOSError(osLastError(), dest) - var buf = alloc(bufSize) + + # Hints for kernel-level aggressive sequential low-fragmentation read-aheads: + # https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html + when defined(linux) or defined(osx): + discard posix_fadvise(getFileHandle(d), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL) + discard posix_fadvise(getFileHandle(s), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL) + + var buf = alloc(bufferSize) while true: - var bytesread = readBuffer(s, buf, bufSize) + var bytesread = readBuffer(s, buf, bufferSize) if bytesread > 0: var byteswritten = writeBuffer(d, buf, bytesread) if bytesread != byteswritten: @@ -254,13 +261,13 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl, close(s) close(d) raiseOSError(osLastError(), dest) - if bytesread != bufSize: break + if bytesread != bufferSize: break dealloc(buf) close(s) flushFile(d) close(d) -proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow}) +proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow}; bufferSize = 16_384) {.noWeirdTarget, since: (1,3,7).} = ## Copies a file `source` into directory `dir`, which must exist. ## @@ -268,12 +275,14 @@ proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow}) ## if `source` is a symlink, copies the file symlink points to. `options` is ## ignored on Windows: symlinks are skipped. ## + ## `copyFileToDir` allows to specify `bufferSize` to improve I/O performance. + ## ## See also: ## * `CopyFlag enum`_ ## * `copyFile proc`_ if dir.len == 0: # treating "" as "." is error prone raise newException(ValueError, "dest is empty") - copyFile(source, dir / source.lastPathPart, options) + copyFile(source, dir / source.lastPathPart, options, bufferSize) proc copyFileWithPermissions*(source, dest: string, @@ -399,7 +408,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", raiseAssert "unreachable" else: # Fallback to copy & del - copyFile(source, dest, {cfSymlinkAsIs}) + copyFileWithPermissions(source, dest, options={cfSymlinkAsIs}) try: removeFile(source) except: diff --git a/lib/std/private/ospaths2.nim b/lib/std/private/ospaths2.nim index 421def62b..bc69ff725 100644 --- a/lib/std/private/ospaths2.nim +++ b/lib/std/private/ospaths2.nim @@ -1,7 +1,7 @@ include system/inclrtl import std/private/since -import strutils, pathnorm +import std/[strutils, pathnorm] import std/oserrors import oscommon @@ -17,9 +17,9 @@ const weirdTarget = defined(nimscript) or defined(js) when weirdTarget: discard elif defined(windows): - import winlean + import std/winlean elif defined(posix): - import posix, system/ansi_c + import std/posix, system/ansi_c else: {.error: "OS module not ported to your operating system!".} @@ -254,10 +254,10 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1", raise result = path[0] != ':' elif defined(RISCOS): result = path[0] == '$' - elif defined(posix) or defined(js): - # `or defined(js)` wouldn't be needed pending https://github.com/nim-lang/Nim/issues/13469 - # This works around the problem for posix, but Windows is still broken with nim js -d:nodejs + elif defined(posix): result = path[0] == '/' + elif defined(nodejs): + {.emit: [result," = require(\"path\").isAbsolute(",path.cstring,");"].} else: raiseAssert "unreachable" # if ever hits here, adapt as needed @@ -763,9 +763,9 @@ proc cmpPaths*(pathA, pathB: string): int {. ## On a case-sensitive filesystem this is done ## case-sensitively otherwise case-insensitively. Returns: ## - ## | 0 if pathA == pathB - ## | < 0 if pathA < pathB - ## | > 0 if pathA > pathB + ## | `0` if pathA == pathB + ## | `< 0` if pathA < pathB + ## | `> 0` if pathA > pathB runnableExamples: when defined(macosx): assert cmpPaths("foo", "Foo") == 0 @@ -862,13 +862,13 @@ when not defined(nimscript): raiseAssert "use -d:nodejs to have `getCurrentDir` defined" elif defined(windows): var bufsize = MAX_PATH.int32 - var res = newWideCString("", bufsize) + var res = newWideCString(bufsize) while true: var L = getCurrentDirectoryW(bufsize, res) if L == 0'i32: raiseOSError(osLastError()) elif L > bufsize: - res = newWideCString("", L) + res = newWideCString(L) bufsize = L else: result = res$L diff --git a/lib/std/private/ossymlinks.nim b/lib/std/private/ossymlinks.nim index 18737b8b5..c1760c42e 100644 --- a/lib/std/private/ossymlinks.nim +++ b/lib/std/private/ossymlinks.nim @@ -10,9 +10,9 @@ when defined(nimPreviewSlimSystem): when weirdTarget: discard elif defined(windows): - import winlean, times + import std/[winlean, times] elif defined(posix): - import posix + import std/posix else: {.error: "OS module not ported to your operating system!".} @@ -66,11 +66,13 @@ proc expandSymlink*(symlinkPath: string): string {.noWeirdTarget.} = when defined(windows) or defined(nintendoswitch): result = symlinkPath else: - result = newString(maxSymlinkLen) - var len = readlink(symlinkPath, result.cstring, maxSymlinkLen) - if len < 0: - raiseOSError(osLastError(), symlinkPath) - if len > maxSymlinkLen: - result = newString(len+1) - len = readlink(symlinkPath, result.cstring, len) - setLen(result, len) + var bufLen = 1024 + while true: + result = newString(bufLen) + let len = readlink(symlinkPath.cstring, result.cstring, bufLen) + if len < 0: + raiseOSError(osLastError(), symlinkPath) + if len < bufLen: + result.setLen(len) + break + bufLen = bufLen shl 1 diff --git a/lib/std/private/syslocks.nim b/lib/std/private/syslocks.nim index ca8897dc2..e19ec2c04 100644 --- a/lib/std/private/syslocks.nim +++ b/lib/std/private/syslocks.nim @@ -16,7 +16,7 @@ when defined(windows): Handle = int SysLock* {.importc: "CRITICAL_SECTION", - header: "<windows.h>", final, pure.} = object # CRITICAL_SECTION in WinApi + header: "<windows.h>", final, pure, byref.} = object # CRITICAL_SECTION in WinApi DebugInfo: pointer LockCount: int32 RecursionCount: int32 @@ -24,7 +24,7 @@ when defined(windows): LockSemaphore: int SpinCount: int - SysCond* {.importc: "RTL_CONDITION_VARIABLE", header: "<windows.h>".} = object + SysCond* {.importc: "RTL_CONDITION_VARIABLE", header: "<windows.h>", byref.} = object thePtr {.importc: "Ptr".} : Handle proc initSysLock*(L: var SysLock) {.importc: "InitializeCriticalSection", @@ -46,7 +46,7 @@ when defined(windows): header: "<windows.h>".} ## Releases the lock `L`. - proc deinitSys*(L: var SysLock) {.importc: "DeleteCriticalSection", + proc deinitSys*(L: SysLock) {.importc: "DeleteCriticalSection", header: "<windows.h>".} proc initializeConditionVariable( @@ -68,7 +68,7 @@ when defined(windows): proc initSysCond*(cond: var SysCond) {.inline.} = initializeConditionVariable(cond) - proc deinitSysCond*(cond: var SysCond) {.inline.} = + proc deinitSysCond*(cond: SysCond) {.inline.} = discard proc waitSysCond*(cond: var SysCond, lock: var SysLock) = discard sleepConditionVariableCS(cond, lock, -1'i32) @@ -83,13 +83,13 @@ elif defined(genode): header: Header.} = object proc initSysLock*(L: var SysLock) = discard - proc deinitSys*(L: var SysLock) = discard + proc deinitSys*(L: SysLock) = discard proc acquireSys*(L: var SysLock) {.noSideEffect, importcpp.} proc tryAcquireSys*(L: var SysLock): bool {.noSideEffect, importcpp.} proc releaseSys*(L: var SysLock) {.noSideEffect, importcpp.} proc initSysCond*(L: var SysCond) = discard - proc deinitSysCond*(L: var SysCond) = discard + proc deinitSysCond*(L: SysCond) = discard proc waitSysCond*(cond: var SysCond, lock: var SysLock) {. noSideEffect, importcpp.} proc signalSysCond*(cond: var SysCond) {. @@ -101,7 +101,7 @@ else: type SysLockObj {.importc: "pthread_mutex_t", pure, final, header: """#include <sys/types.h> - #include <pthread.h>""".} = object + #include <pthread.h>""", byref.} = object when defined(linux) and defined(amd64): abi: array[40 div sizeof(clong), clong] @@ -113,7 +113,7 @@ else: SysCondObj {.importc: "pthread_cond_t", pure, final, header: """#include <sys/types.h> - #include <pthread.h>""".} = object + #include <pthread.h>""", byref.} = object when defined(linux) and defined(amd64): abi: array[48 div sizeof(clonglong), clonglong] @@ -127,7 +127,7 @@ else: proc initSysLockAux(L: var SysLockObj, attr: ptr SysLockAttr) {. importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.} - proc deinitSysAux(L: var SysLockObj) {.noSideEffect, + proc deinitSysAux(L: SysLockObj) {.noSideEffect, importc: "pthread_mutex_destroy", header: "<pthread.h>".} proc acquireSysAux(L: var SysLockObj) {.noSideEffect, @@ -156,7 +156,7 @@ else: L = cast[SysLock](c_malloc(csize_t(sizeof(SysLockObj)))) initSysLockAux(L[], attr) - proc deinitSys*(L: var SysLock) = + proc deinitSys*(L: SysLock) = deinitSysAux(L[]) c_free(L) @@ -173,7 +173,7 @@ else: template initSysLock*(L: var SysLock, attr: ptr SysLockAttr = nil) = initSysLockAux(L, attr) - template deinitSys*(L: var SysLock) = + template deinitSys*(L: SysLock) = deinitSysAux(L) template acquireSys*(L: var SysLock) = acquireSysAux(L) @@ -193,7 +193,7 @@ else: # locks proc initSysCondAux(cond: var SysCondObj, cond_attr: ptr SysCondAttr = nil) {. importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.} - proc deinitSysCondAux(cond: var SysCondObj) {.noSideEffect, + proc deinitSysCondAux(cond: SysCondObj) {.noSideEffect, importc: "pthread_cond_destroy", header: "<pthread.h>".} proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj): cint {. @@ -208,7 +208,7 @@ else: cond = cast[SysCond](c_malloc(csize_t(sizeof(SysCondObj)))) initSysCondAux(cond[], cond_attr) - proc deinitSysCond*(cond: var SysCond) = + proc deinitSysCond*(cond: SysCond) = deinitSysCondAux(cond[]) c_free(cond) @@ -221,7 +221,7 @@ else: else: template initSysCond*(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) = initSysCondAux(cond, cond_attr) - template deinitSysCond*(cond: var SysCond) = + template deinitSysCond*(cond: SysCond) = deinitSysCondAux(cond) template waitSysCond*(cond: var SysCond, lock: var SysLock) = diff --git a/lib/std/private/underscored_calls.nim b/lib/std/private/underscored_calls.nim index 8b0392641..f853572b5 100644 --- a/lib/std/private/underscored_calls.nim +++ b/lib/std/private/underscored_calls.nim @@ -10,7 +10,7 @@ ## This is an internal helper module. Do not use. -import macros +import std/macros proc underscoredCalls*(result, calls, arg0: NimNode) diff --git a/lib/std/setutils.nim b/lib/std/setutils.nim index 4664d6dcc..8e7bc6a92 100644 --- a/lib/std/setutils.nim +++ b/lib/std/setutils.nim @@ -14,7 +14,7 @@ ## * `std/packedsets <packedsets.html>`_ ## * `std/sets <sets.html>`_ -import typetraits, macros +import std/[typetraits, macros] #[ type SetElement* = char|byte|bool|int16|uint16|enum|uint8|int8 diff --git a/lib/std/sha1.nim b/lib/std/sha1.nim index a1a8c4782..213af4229 100644 --- a/lib/std/sha1.nim +++ b/lib/std/sha1.nim @@ -29,8 +29,8 @@ runnableExamples("-r:off"): {.deprecated: "use command `nimble install checksums` and import `checksums/sha1` instead".} -import strutils -from endians import bigEndian32, bigEndian64 +import std/strutils +from std/endians import bigEndian32, bigEndian64 when defined(nimPreviewSlimSystem): import std/syncio diff --git a/lib/std/socketstreams.nim b/lib/std/socketstreams.nim index 41d46e58a..45e906795 100644 --- a/lib/std/socketstreams.nim +++ b/lib/std/socketstreams.nim @@ -64,7 +64,7 @@ ## sendStream.write "I" # Throws an error as we can't write into an already sent buffer ## ``` -import net, streams +import std/[net, streams] type ReadSocketStream* = ref ReadSocketStreamObj diff --git a/lib/std/symlinks.nim b/lib/std/symlinks.nim index 60487740c..dbe908612 100644 --- a/lib/std/symlinks.nim +++ b/lib/std/symlinks.nim @@ -2,7 +2,7 @@ ## .. importdoc:: os.nim -from paths import Path, ReadDirEffect +from std/paths import Path, ReadDirEffect from std/private/ossymlinks import symlinkExists, createSymlink, expandSymlink diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim index 879301f8a..c34a025af 100644 --- a/lib/std/syncio.nim +++ b/lib/std/syncio.nim @@ -151,14 +151,11 @@ proc c_fprintf(f: File, frmt: cstring): cint {. proc c_fputc(c: char, f: File): cint {. importc: "fputc", header: "<stdio.h>".} -template sysFatal(exc, msg) = - raise newException(exc, msg) - proc raiseEIO(msg: string) {.noinline, noreturn.} = - sysFatal(IOError, msg) + raise newException(IOError, msg) proc raiseEOF() {.noinline, noreturn.} = - sysFatal(EOFError, "EOF reached") + raise newException(EOFError, "EOF reached") proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".} @@ -246,7 +243,7 @@ when defined(windows): # machine. We also enable `setConsoleOutputCP(65001)` now by default. # But we cannot call printf directly as the string might contain \0. # So we have to loop over all the sections separated by potential \0s. - var i = c_fprintf(f, "%s", s) + var i = int c_fprintf(f, "%s", s) while i < s.len: if s[i] == '\0': let w = c_fputc('\0', f) @@ -323,7 +320,7 @@ elif defined(windows): const BufSize = 4000 -proc close*(f: File) {.tags: [], gcsafe.} = +proc close*(f: File) {.tags: [], gcsafe, sideEffect.} = ## Closes the file. if not f.isNil: discard c_fclose(f) @@ -422,7 +419,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect], if f.isatty: const numberOfCharsToRead = 2048 var numberOfCharsRead = 0'i32 - var buffer = newWideCString("", numberOfCharsToRead) + var buffer = newWideCString(numberOfCharsToRead) if readConsole(getOsFileHandle(f), addr(buffer[0]), numberOfCharsToRead, addr(numberOfCharsRead), nil) == 0: var error = getLastError() @@ -651,6 +648,9 @@ const "" else: "" + RawFormatOpen: array[FileMode, cstring] = [ + # used for open by FileHandle, which calls `fdopen` + cstring("rb"), "wb", "w+b", "r+b", "ab"] FormatOpen: array[FileMode, cstring] = [ cstring("rb" & NoInheritFlag), "wb" & NoInheritFlag, "w+b" & NoInheritFlag, "r+b" & NoInheritFlag, "ab" & NoInheritFlag @@ -752,7 +752,7 @@ proc open*(f: var File, filehandle: FileHandle, filehandle) else: filehandle if not setInheritable(oshandle, false): return false - f = c_fdopen(filehandle, FormatOpen[mode]) + f = c_fdopen(filehandle, RawFormatOpen[mode]) result = f != nil proc open*(filename: string, @@ -764,9 +764,9 @@ proc open*(filename: string, ## ## The file handle associated with the resulting `File` is not inheritable. if not open(result, filename, mode, bufSize): - sysFatal(IOError, "cannot open: " & filename) + raise newException(IOError, "cannot open: " & filename) -proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.benign.} = +proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.benign, sideEffect.} = ## Sets the position of the file pointer that is used for read/write ## operations. The file's first byte has the index zero. if c_fseek(f, pos, cint(relativeTo)) != 0: @@ -852,7 +852,7 @@ proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.} = finally: close(f) else: - sysFatal(IOError, "cannot open: " & filename) + raise newException(IOError, "cannot open: " & filename) proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} = ## Opens a file named `filename` for writing. Then writes the @@ -865,7 +865,7 @@ proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} = finally: close(f) else: - sysFatal(IOError, "cannot open: " & filename) + raise newException(IOError, "cannot open: " & filename) proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} = ## Opens a file named `filename` for writing. Then writes the @@ -874,7 +874,7 @@ proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} = var f: File = nil if open(f, filename, fmWrite): try: - f.writeBuffer(unsafeAddr content[0], content.len) + discard f.writeBuffer(unsafeAddr content[0], content.len) finally: close(f) else: @@ -895,7 +895,7 @@ proc readLines*(filename: string, n: Natural): seq[string] = finally: close(f) else: - sysFatal(IOError, "cannot open: " & filename) + raise newException(IOError, "cannot open: " & filename) template readLines*(filename: string): seq[ string] {.deprecated: "use readLines with two arguments".} = diff --git a/lib/std/sysatomics.nim b/lib/std/sysatomics.nim index 36a4e5537..2f203b3eb 100644 --- a/lib/std/sysatomics.nim +++ b/lib/std/sysatomics.nim @@ -265,6 +265,7 @@ else: proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, discardable, raises: [], tags: [].} = + ## Atomically increments the integer by some `x`. It returns the new value. when someGcc and hasThreadSupport: result = atomicAddFetch(memLoc.addr, x, ATOMIC_SEQ_CST) elif someVcc and hasThreadSupport: @@ -275,6 +276,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, discardable, raises: result = memLoc proc atomicDec*(memLoc: var int, x: int = 1): int {.inline, discardable, raises: [], tags: [].} = + ## Atomically decrements the integer by some `x`. It returns the new value. when someGcc and hasThreadSupport: when declared(atomicSubFetch): result = atomicSubFetch(memLoc.addr, x, ATOMIC_SEQ_CST) @@ -361,7 +363,7 @@ elif someGcc or defined(tcc): elif defined(icl): proc cpuRelax* {.importc: "_mm_pause", header: "xmmintrin.h".} elif false: - from os import sleep + from std/os import sleep proc cpuRelax* {.inline.} = os.sleep(1) diff --git a/lib/std/sysrand.nim b/lib/std/sysrand.nim index 8526336ad..6f2c6b0c1 100644 --- a/lib/std/sysrand.nim +++ b/lib/std/sysrand.nim @@ -60,7 +60,7 @@ when not defined(js): import std/oserrors when defined(posix): - import posix + import std/posix when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/std/tasks.nim b/lib/std/tasks.nim index 9eb7c97c4..7e59747f5 100644 --- a/lib/std/tasks.nim +++ b/lib/std/tasks.nim @@ -68,7 +68,8 @@ type proc `=copy`*(x: var Task, y: Task) {.error.} -when defined(nimAllowNonVarDestructor): +const arcLike = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) +when defined(nimAllowNonVarDestructor) and arcLike: proc `=destroy`*(t: Task) {.inline, gcsafe.} = ## Frees the resources allocated for a `Task`. if t.args != nil: @@ -109,6 +110,19 @@ template addAllNode(assignParam: NimNode, procParam: NimNode) = tempAssignList.add newLetStmt(tempNode, newDotExpr(objTemp, formalParams[i][0])) scratchRecList.add newIdentDefs(newIdentNode(formalParams[i][0].strVal), assignParam) +proc analyseRootSym(s: NimNode): NimNode = + result = s + while true: + case result.kind + of nnkBracketExpr, nnkDerefExpr, nnkHiddenDeref, + nnkAddr, nnkHiddenAddr, + nnkObjDownConv, nnkObjUpConv: + result = result[0] + of nnkDotExpr, nnkCheckedFieldExpr, nnkHiddenStdConv, nnkHiddenSubConv: + result = result[1] + else: + break + macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkCallStrLit}): Task = ## Converts the call and its arguments to `Task`. runnableExamples: @@ -120,11 +134,14 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC let retType = getTypeInst(e) let returnsVoid = retType.typeKind == ntyVoid + let rootSym = analyseRootSym(e[0]) + expectKind rootSym, nnkSym + when compileOption("threads"): - if not isGcSafe(e[0]): + if not isGcSafe(rootSym): error("'toTask' takes a GC safe call expression", e) - if hasClosure(e[0]): + if hasClosure(rootSym): error("closure call is not allowed", e) if e.len > 1: @@ -208,7 +225,7 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC let funcCall = newCall(e[0], callNode) functionStmtList.add tempAssignList - let funcName = genSym(nskProc, e[0].strVal) + let funcName = genSym(nskProc, rootSym.strVal) let destroyName = genSym(nskProc, "destroyScratch") let objTemp2 = genSym(ident = "obj") let tempNode = quote("@") do: @@ -240,7 +257,7 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC Task(callback: `funcName`, args: `scratchIdent`, destroy: `destroyName`) else: let funcCall = newCall(e[0]) - let funcName = genSym(nskProc, e[0].strVal) + let funcName = genSym(nskProc, rootSym.strVal) if returnsVoid: result = quote do: diff --git a/lib/std/tempfiles.nim b/lib/std/tempfiles.nim index 1160aaaad..539305bde 100644 --- a/lib/std/tempfiles.nim +++ b/lib/std/tempfiles.nim @@ -17,7 +17,7 @@ See also: * `mkstemp` (posix), refs https://man7.org/linux/man-pages/man3/mkstemp.3.html ]# -import os, random +import std / [os, random] when defined(nimPreviewSlimSystem): import std/syncio @@ -29,7 +29,7 @@ const when defined(windows): - import winlean + import std/winlean when defined(nimPreviewSlimSystem): import std/widestrs @@ -46,7 +46,7 @@ when defined(windows): proc close_osfandle(fd: cint): cint {. importc: "_close", header: "<io.h>".} else: - import posix + import std/posix proc c_fdopen( filehandle: cint, diff --git a/lib/std/time_t.nim b/lib/std/time_t.nim index 7fb6e6d46..de051b135 100644 --- a/lib/std/time_t.nim +++ b/lib/std/time_t.nim @@ -14,10 +14,10 @@ when defined(nimdoc): ## Wrapper for `time_t`. On posix, this is an alias to `posix.Time`. elif defined(windows): when defined(i386) and defined(gcc): - type Time* {.importc: "time_t", header: "<time.h>".} = distinct int32 + type Time* {.importc: "time_t", header: "<time.h>".} = distinct clong else: # newest version of Visual C++ defines time_t to be of 64 bits type Time* {.importc: "time_t", header: "<time.h>".} = distinct int64 elif defined(posix): - import posix + import std/posix export posix.Time \ No newline at end of file diff --git a/lib/std/typedthreads.nim b/lib/std/typedthreads.nim index 501a0d0fa..7b0b81968 100644 --- a/lib/std/typedthreads.nim +++ b/lib/std/typedthreads.nim @@ -7,33 +7,73 @@ # distribution, for details about the copyright. # -## Thread support for Nim. -## -## Examples -## ======== -## -## ```Nim -## import std/locks -## -## var -## thr: array[0..4, Thread[tuple[a,b: int]]] -## L: Lock -## -## proc threadFunc(interval: tuple[a,b: int]) {.thread.} = -## for i in interval.a..interval.b: -## acquire(L) # lock stdout -## echo i -## release(L) -## -## initLock(L) -## -## for i in 0..high(thr): -## createThread(thr[i], threadFunc, (i*10, i*10+5)) -## joinThreads(thr) -## -## deinitLock(L) -## ``` - +##[ +Thread support for Nim. Threads allow multiple functions to execute concurrently. + +In Nim, threads are a low-level construct and using a library like `malebolgia`, `taskpools` or `weave` is recommended. + +When creating a thread, you can pass arguments to it. As Nim's garbage collector does not use atomic references, sharing +`ref` and other variables managed by the garbage collector between threads is not supported. +Use global variables to do so, or pointers. + +Memory allocated using [`sharedAlloc`](./system.html#allocShared.t%2CNatural) can be used and shared between threads. + +To communicate between threads, consider using [channels](./system.html#Channel) + +Examples +======== + +```Nim +import std/locks + +var + thr: array[0..4, Thread[tuple[a,b: int]]] + L: Lock + +proc threadFunc(interval: tuple[a,b: int]) {.thread.} = + for i in interval.a..interval.b: + acquire(L) # lock stdout + echo i + release(L) + +initLock(L) + +for i in 0..high(thr): + createThread(thr[i], threadFunc, (i*10, i*10+5)) +joinThreads(thr) + +deinitLock(L) +``` + +When using a memory management strategy that supports shared heaps like `arc` or `boehm`, +you can pass pointer to threads and share memory between them, but the memory must outlive the thread. +The default memory management strategy, `orc`, supports this. +The example below is **not valid** for memory management strategies that use local heaps like `refc`! + +```Nim +import locks + +var l: Lock + +proc threadFunc(obj: ptr seq[int]) {.thread.} = + withLock l: + for i in 0..<100: + obj[].add(obj[].len * obj[].len) + +proc threadHandler() = + var thr: array[0..4, Thread[ptr seq[int]]] + var s = newSeq[int]() + + for i in 0..high(thr): + createThread(thr[i], threadFunc, s.addr) + joinThreads(thr) + echo s + +initLock(l) +threadHandler() +deinitLock(l) +``` +]## import std/private/[threadtypes] diff --git a/lib/std/varints.nim b/lib/std/varints.nim index 0d18b9069..32fe2fffb 100644 --- a/lib/std/varints.nim +++ b/lib/std/varints.nim @@ -82,29 +82,29 @@ proc writeVu64*(z: var openArray[byte], x: uint64): int = z[3] = cast[uint8](y) return 4 z[0] = 251 - varintWrite32(toOpenArray(z, 1, z.high-1), y) + varintWrite32(toOpenArray(z, 1, 4), y) return 5 if w <= 255: z[0] = 252 z[1] = cast[uint8](w) - varintWrite32(toOpenArray(z, 2, z.high-2), y) + varintWrite32(toOpenArray(z, 2, 5), y) return 6 if w <= 65535: z[0] = 253 z[1] = cast[uint8](w shr 8) z[2] = cast[uint8](w) - varintWrite32(toOpenArray(z, 3, z.high-3), y) + varintWrite32(toOpenArray(z, 3, 6), y) return 7 if w <= 16777215: z[0] = 254 z[1] = cast[uint8](w shr 16) z[2] = cast[uint8](w shr 8) z[3] = cast[uint8](w) - varintWrite32(toOpenArray(z, 4, z.high-4), y) + varintWrite32(toOpenArray(z, 4, 7), y) return 8 z[0] = 255 - varintWrite32(toOpenArray(z, 1, z.high-1), w) - varintWrite32(toOpenArray(z, 5, z.high-5), y) + varintWrite32(toOpenArray(z, 1, 4), w) + varintWrite32(toOpenArray(z, 5, 8), y) return 9 proc sar(a, b: int64): int64 = diff --git a/lib/std/widestrs.nim b/lib/std/widestrs.nim index 0bf50be45..2ddf80d14 100644 --- a/lib/std/widestrs.nim +++ b/lib/std/widestrs.nim @@ -25,7 +25,8 @@ when not (defined(cpu16) or defined(cpu8)): bytes: int data: WideCString - when defined(nimAllowNonVarDestructor): + const arcLike = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) + when defined(nimAllowNonVarDestructor) and arcLike: proc `=destroy`(a: WideCStringObj) = if a.data != nil: when compileOption("threads"): @@ -154,6 +155,7 @@ when not (defined(cpu16) or defined(cpu8)): createWide(result, size * 2 + 2) proc newWideCString*(source: cstring, L: int): WideCStringObj = + ## Warning:: `source` needs to be preallocated with the length `L` createWide(result, L * 2 + 2) var d = 0 for ch in runes(source, L): diff --git a/lib/std/with.nim b/lib/std/with.nim index 8043a0b8a..c2eaa4bef 100644 --- a/lib/std/with.nim +++ b/lib/std/with.nim @@ -14,7 +14,7 @@ ## ## **Since:** version 1.2. -import macros, private / underscored_calls +import std/[macros, private / underscored_calls] macro with*(arg: typed; calls: varargs[untyped]): untyped = ## This macro provides `chaining`:idx: of function calls. diff --git a/lib/std/wordwrap.nim b/lib/std/wordwrap.nim index 7dcfc7f59..9333f880b 100644 --- a/lib/std/wordwrap.nim +++ b/lib/std/wordwrap.nim @@ -9,7 +9,7 @@ ## This module contains an algorithm to wordwrap a Unicode string. -import strutils, unicode +import std/[strutils, unicode] proc olen(s: string; start, lastExclusive: int): int = var i = start diff --git a/lib/std/wrapnils.nim b/lib/std/wrapnils.nim index 235638134..0b75c270e 100644 --- a/lib/std/wrapnils.nim +++ b/lib/std/wrapnils.nim @@ -13,7 +13,7 @@ consider handling indexing operations, eg: doAssert ?.default(seq[int])[3] == default(int) ]# -import macros +import std/macros runnableExamples: type Foo = ref object @@ -122,7 +122,7 @@ macro `?.`*(a: typed): auto = `lhs` # the code below is not needed for `?.` -from options import Option, isSome, get, option, unsafeGet, UnpackDefect +from std/options import Option, isSome, get, option, unsafeGet, UnpackDefect macro `??.`*(a: typed): Option = ## Same as `?.` but returns an `Option`. diff --git a/lib/system.nim b/lib/system.nim index c3cad4f71..2f9cdc5f9 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -125,9 +125,6 @@ proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = const ThisIsSystem = true -proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} - ## Leaked implementation detail. Do not use. - proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. magic: "NewFinalize", noSideEffect.} ## Creates a new object of type `T` and returns a safe (traced) @@ -161,9 +158,11 @@ when defined(nimHasEnsureMove): ## Ensures that `x` is moved to the new location, otherwise it gives ## an error at the compile time. runnableExamples: - var x = "Hello" - let y = ensureMove(x) - doAssert y == "Hello" + proc foo = + var x = "Hello" + let y = ensureMove(x) + doAssert y == "Hello" + foo() discard "implemented in injectdestructors" type @@ -366,19 +365,24 @@ proc arrPut[I: Ordinal;T,S](a: T; i: I; const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) -when defined(nimAllowNonVarDestructor) and arcLikeMem: - proc `=destroy`*(x: string) {.inline, magic: "Destroy".} = +when defined(nimAllowNonVarDestructor) and arcLikeMem and defined(nimPreviewNonVarDestructor): + proc `=destroy`*[T](x: T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. discard - - proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} = +else: + proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. discard - proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} = - discard + when defined(nimAllowNonVarDestructor) and arcLikeMem: + proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} = + discard -proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = - ## Generic `destructor`:idx: implementation that can be overridden. - discard + proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} = + discard + + proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} = + discard when defined(nimHasDup): proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} = @@ -457,10 +461,6 @@ when not defined(js) and not defined(nimSeqsV2): data: UncheckedArray[char] NimString = ptr NimStringDesc -when notJSnotNims and not defined(nimSeqsV2): - template space(s: PGenericSeq): int {.dirty.} = - s.reserved and not (seqShallowFlag or strlitFlag) - when notJSnotNims: include "system/hti" @@ -631,7 +631,7 @@ proc newSeq*[T](len = 0.Natural): seq[T] = ## ## See also: ## * `newSeqOfCap <#newSeqOfCap,Natural>`_ - ## * `newSeqUninitialized <#newSeqUninitialized,Natural>`_ + ## * `newSeqUninit <#newSeqUninit,Natural>`_ newSeq(result, len) proc newSeqOfCap*[T](cap: Natural): seq[T] {. @@ -925,7 +925,7 @@ proc reset*[T](obj: var T) {.noSideEffect.} = obj = default(typeof(obj)) proc setLen*[T](s: var seq[T], newlen: Natural) {. - magic: "SetLengthSeq", noSideEffect.} + magic: "SetLengthSeq", noSideEffect, nodestroy.} ## Sets the length of seq `s` to `newlen`. `T` may be any sequence type. ## ## If the current length is greater than the new length, @@ -1037,7 +1037,7 @@ const ## Possible values: ## `"i386"`, `"alpha"`, `"powerpc"`, `"powerpc64"`, `"powerpc64el"`, ## `"sparc"`, `"amd64"`, `"mips"`, `"mipsel"`, `"arm"`, `"arm64"`, - ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, '"loongarch64"'. + ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, `"loongarch64"`. seqShallowFlag = low(int) strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \ @@ -1048,6 +1048,10 @@ const hasThreadSupport = compileOption("threads") and not defined(nimscript) hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own +when notJSnotNims and not defined(nimSeqsV2): + template space(s: PGenericSeq): int = + s.reserved and not (seqShallowFlag or strlitFlag) + when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"): # tcc doesn't support TLS {.error: "`--tlsEmulation:on` must be used when using threads with tcc backend".} @@ -1117,8 +1121,6 @@ template sysAssert(cond: bool, msg: string) = const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) -when notJSnotNims and hostOS != "standalone" and hostOS != "any": - include "system/cgprocs" when notJSnotNims and hasAlloc and not defined(nimSeqsV2): proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.} @@ -1431,7 +1433,6 @@ proc isNil*[T: proc | iterator {.closure.}](x: T): bool {.noSideEffect, magic: " ## Fast check whether `x` is nil. This is sometimes more efficient than ## `== nil`. - when defined(nimHasTopDownInference): # magic used for seq type inference proc `@`*[T](a: openArray[T]): seq[T] {.magic: "OpenArrayToSeq".} = @@ -1604,14 +1605,30 @@ when not defined(js) and defined(nimV2): traceImpl: pointer typeInfoV1: pointer # for backwards compat, usually nil flags: int + when defined(gcDestructors): + when defined(cpp): + vTable: ptr UncheckedArray[pointer] # vtable for types + else: + vTable: UncheckedArray[pointer] # vtable for types PNimTypeV2 = ptr TNimTypeV2 +proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".} + when notJSnotNims and defined(nimSeqsV2): include "system/strs_v2" include "system/seqs_v2" when not defined(js): - proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] = + template newSeqImpl(T, len) = + result = newSeqOfCap[T](len) + {.cast(noSideEffect).}: + when defined(nimSeqsV2): + cast[ptr int](addr result)[] = len + else: + var s = cast[PGenericSeq](result) + s.len = len + + proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] {.deprecated: "Use `newSeqUninit` instead".} = ## Creates a new sequence of type `seq[T]` with length `len`. ## ## Only available for numbers types. Note that the sequence will be @@ -1630,6 +1647,26 @@ when not defined(js): var s = cast[PGenericSeq](result) s.len = len + func newSeqUninit*[T](len: Natural): seq[T] = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Only available for types, which don't contain + ## managed memory or have destructors. + ## Note that the sequence will be uninitialized. + ## After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + runnableExamples: + var x = newSeqUninit[int](3) + assert len(x) == 3 + x[0] = 10 + when supportsCopyMem(T): + when nimvm: + result = newSeq[T](len) + else: + newSeqImpl(T, len) + else: + {.error: "The type T cannot contain managed memory or have destructors".} + proc newStringUninit*(len: Natural): string = ## Returns a new string of length `len` but with uninitialized ## content. One needs to fill the string character after character @@ -1637,12 +1674,22 @@ when not defined(js): ## ## This procedure exists only for optimization purposes; ## the same effect can be achieved with the `&` operator or with `add`. - result = newStringOfCap(len) - when defined(nimSeqsV2): - cast[ptr int](addr result)[] = len + when nimvm: + result = newString(len) else: - var s = cast[PGenericSeq](result) - s.len = len + result = newStringOfCap(len) + when defined(nimSeqsV2): + let s = cast[ptr NimStringV2](addr result) + if len > 0: + s.len = len + s.p.data[len] = '\0' + else: + let s = cast[NimString](result) + s.len = len + s.data[len] = '\0' +else: + proc newStringUninit*(len: Natural): string {. + magic: "NewString", importc: "mnewString", noSideEffect.} {.pop.} @@ -1655,8 +1702,24 @@ when not defined(nimscript): when not declared(sysFatal): include "system/fatal" +type + PFrame* = ptr TFrame ## Represents a runtime frame of the call stack; + ## part of the debugger API. + # keep in sync with nimbase.h `struct TFrame_` + TFrame* {.importc, nodecl, final.} = object ## The frame itself. + prev*: PFrame ## Previous frame; used for chaining the call stack. + procname*: cstring ## Name of the proc that is currently executing. + line*: int ## Line number of the proc that is currently executing. + filename*: cstring ## Filename of the proc that is currently executing. + len*: int16 ## Length of the inspectable slots. + calldepth*: int16 ## Used for max call depth checking. + when NimStackTraceMsgs: + frameMsgLen*: int ## end position in frameMsgBuf for this frame. when defined(nimV2): + var + framePtr {.threadvar.}: PFrame + include system/arc template newException*(exceptn: typedesc, message: string; @@ -1801,20 +1864,6 @@ when notJSnotNims: ## writes an error message and terminates the program, except when ## using `--os:any` -type - PFrame* = ptr TFrame ## Represents a runtime frame of the call stack; - ## part of the debugger API. - # keep in sync with nimbase.h `struct TFrame_` - TFrame* {.importc, nodecl, final.} = object ## The frame itself. - prev*: PFrame ## Previous frame; used for chaining the call stack. - procname*: cstring ## Name of the proc that is currently executing. - line*: int ## Line number of the proc that is currently executing. - filename*: cstring ## Filename of the proc that is currently executing. - len*: int16 ## Length of the inspectable slots. - calldepth*: int16 ## Used for max call depth checking. - when NimStackTraceMsgs: - frameMsgLen*: int ## end position in frameMsgBuf for this frame. - when defined(js) or defined(nimdoc): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = ## Appends `y` to `x` in place. @@ -1823,14 +1872,14 @@ when defined(js) or defined(nimdoc): tmp.add(cstring("ab")) tmp.add(cstring("cd")) doAssert tmp == "abcd" - asm """ + {.emit: """ if (`x` === null) { `x` = []; } var off = `x`.length; `x`.length += `y`.length; for (var i = 0; i < `y`.length; ++i) { `x`[off+i] = `y`.charCodeAt(i); } - """ + """.} proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} = ## Appends `y` to `x` in place. ## Only implemented for JS backend. @@ -1946,15 +1995,11 @@ when defined(nimAuditDelete): else: {.pragma: auditDelete.} -proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} = +proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, systemRaisesDefect, auditDelete.} = ## Deletes the item at index `i` by moving all `x[i+1..^1]` items by one position. ## ## This is an `O(n)` operation. ## - ## .. note:: With `-d:nimStrictDelete`, an index error is produced when the index passed - ## to it was out of bounds. `-d:nimStrictDelete` will become the default - ## in upcoming versions. - ## ## See also: ## * `del <#del,seq[T],Natural>`_ for O(1) operation ## @@ -1963,7 +2008,7 @@ proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} = s.delete(2) doAssert s == @[1, 2, 4, 5] - when defined(nimStrictDelete): + when not defined(nimAuditDelete): if i > high(x): # xxx this should call `raiseIndexError2(i, high(x))` after some refactoring raise (ref IndexDefect)(msg: "index out of bounds: '" & $i & "' < '" & $x.len & "' failed") @@ -2040,7 +2085,8 @@ when notJSnotNims: proc cmpMem(a, b: pointer, size: Natural): int = nimCmpMem(a, b, size).int -when not defined(js): +when not defined(js) or defined(nimscript): + # nimscript can be defined if config file for js compilation proc cmp(x, y: string): int = when nimvm: if x < y: result = -1 @@ -2057,12 +2103,14 @@ when not defined(js): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be ## of length `len`. + if a == nil: return @[] newSeq(result, len) for i in 0..len-1: result[i] = $a[i] proc cstringArrayToSeq*(a: cstringArray): seq[string] = ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be ## terminated by `nil`. + if a == nil: return @[] var L = 0 while a[L] != nil: inc(L) result = cstringArrayToSeq(a, L) @@ -2087,7 +2135,7 @@ when not defined(js) and declared(alloc0) and declared(dealloc): inc(i) dealloc(a) -when notJSnotNims: +when notJSnotNims and not gotoBasedExceptions: type PSafePoint = ptr TSafePoint TSafePoint {.compilerproc, final.} = object @@ -2162,6 +2210,16 @@ when not defined(js): when notJSnotNims: when hostOS != "standalone" and hostOS != "any": + type + LibHandle = pointer # private type + ProcAddr = pointer # library loading and loading of procs: + + proc nimLoadLibrary(path: string): LibHandle {.compilerproc, hcrInline, nonReloadable.} + proc nimUnloadLibrary(lib: LibHandle) {.compilerproc, hcrInline, nonReloadable.} + proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc, hcrInline, nonReloadable.} + + proc nimLoadLibraryError(path: string) {.compilerproc, hcrInline, nonReloadable.} + include "system/dyncalls" import system/countbits_impl @@ -2246,25 +2304,61 @@ when notJSnotNims: proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} = ## Retrieves the raw proc pointer of the closure `x`. This is - ## useful for interfacing closures with C/C++, hash compuations, etc. + ## useful for interfacing closures with C/C++, hash computations, etc. + ## If `rawEnv(x)` returns `nil`, the proc which the result points to + ## takes as many parameters as `x`, but with `{.nimcall.}` as its calling + ## convention instead of `{.closure.}`, otherwise it takes one more parameter + ## which is a `pointer`, and it still has `{.nimcall.}` as its calling convention. + ## To invoke the resulted proc, what this returns has to be casted into a `proc`, + ## not a `ptr proc`, and, in a case where `rawEnv(x)` returns non-`nil`, + ## the last and additional argument has to be the result of `rawEnv(x)`. + ## This is not available for the JS target. #[ The conversion from function pointer to `void*` is a tricky topic, but this should work at least for c++ >= c++11, e.g. for `dlsym` support. refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869, https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c ]# + runnableExamples: + proc makeClosure(x: int): (proc(y: int): int) = + var n = x + result = ( + proc(y: int): int = + n += y + return n + ) + + var + c1 = makeClosure(10) + e = c1.rawEnv() + p = c1.rawProc() + + if e.isNil(): + let c2 = cast[proc(y: int): int {.nimcall.}](p) + echo c2(2) + else: + let c3 = cast[proc(y: int; env: pointer): int {.nimcall.}](p) + echo c3(3, e) + {.emit: """ `result` = (void*)`x`.ClP_0; """.} proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} = ## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`. + ## This is not available for the JS target. {.emit: """ `result` = `x`.ClE_0; """.} - proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} = - ## It can be used to determine if a first class iterator has finished. +proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} = + ## It can be used to determine if a first class iterator has finished. + when defined(js): + # TODO: mangle `:state` + {.emit: """ + `result` = (`x`.ClE_0).HEX3Astate < 0; + """.} + else: {.emit: """ `result` = ((NI*) `x`.ClE_0)[1] < 0; """.} @@ -2272,7 +2366,8 @@ when notJSnotNims: from std/private/digitsutils import addInt export addInt -when defined(js): +when defined(js) and not defined(nimscript): + # nimscript can be defined if config file for js compilation include "system/jssys" include "system/reprjs" @@ -2436,6 +2531,8 @@ when hasAlloc or defined(nimscript): ## var a = "abc" ## a.insert("zz", 0) # a <- "zzabc" ## ``` + if item.len == 0: # prevents self-assignment + return var xl = x.len setLen(x, xl+item.len) var j = xl-1 @@ -2605,7 +2702,7 @@ proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect, proc strcmp(a, b: cstring): cint {.noSideEffect, importc, header: "<string.h>".} if pointer(x) == pointer(y): result = true - elif x.isNil or y.isNil: result = false + elif pointer(x) == nil or pointer(y) == nil: result = false else: result = strcmp(x, y) == 0 template closureScope*(body: untyped): untyped = @@ -2701,6 +2798,18 @@ when not defined(js): proc toOpenArray*[T](x: seq[T]; first, last: int): openArray[T] {. magic: "Slice".} + ## Allows passing the slice of `x` from the element at `first` to the element + ## at `last` to `openArray[T]` parameters without copying it. + ## + ## Example: + ## ```nim + ## proc test(x: openArray[int]) = + ## doAssert x == [1, 2, 3] + ## + ## let s = @[0, 1, 2, 3, 4] + ## s.toOpenArray(1, 3).test + ## ``` + proc toOpenArray*[T](x: openArray[T]; first, last: int): openArray[T] {. magic: "Slice".} proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {. @@ -2715,6 +2824,9 @@ proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {. proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {. magic: "Slice".} +proc toOpenArrayChar*(x: openArray[byte]; first, last: int): openArray[char] {. + magic: "Slice".} + when defined(genode): var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.} ## Hook into the Genode component bootstrap process. @@ -2758,7 +2870,7 @@ when notJSnotNims: hostOS != "any" proc raiseEIO(msg: string) {.noinline, noreturn.} = - sysFatal(IOError, msg) + raise newException(IOError, msg) proc echoBinSafe(args: openArray[string]) {.compilerproc.} = when defined(androidNDK): @@ -2788,7 +2900,7 @@ when notJSnotNims: # machine. We also enable `setConsoleOutputCP(65001)` now by default. # But we cannot call printf directly as the string might contain \0. # So we have to loop over all the sections separated by potential \0s. - var i = c_fprintf(f, "%s", s) + var i = int c_fprintf(f, "%s", s) while i < s.len: if s[i] == '\0': let w = c_fputc('\0', f) @@ -2839,4 +2951,5 @@ proc arrayWith*[T](y: T, size: static int): array[size, T] {.raises: [].} = when nimvm: result[i] = y else: - result[i] = `=dup`(y) + # TODO: fixme it should be `=dup` + result[i] = y diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index edb094f33..3de6d8713 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -20,6 +20,37 @@ template track(op, address, size) = # We manage *chunks* of memory. Each chunk is a multiple of the page size. # Each chunk starts at an address that is divisible by the page size. +# Small chunks may be divided into smaller cells of reusable pointers to reduce the number of page allocations. + +# An allocation of a small pointer looks approximately like this +#[ + + alloc -> rawAlloc -> No free chunk available > Request a new page from tslf -> result = chunk.data -------------+ + | | + v | + Free chunk available | + | | + v v + Fetch shared cells -> No free cells available -> Advance acc -> result = chunk.data + chunk.acc -------> return + (may not add new cells) ^ + | | + v | + Free cells available -> result = chunk.freeList -> Advance chunk.freeList -----------------------------------+ +]# +# so it is split into 3 paths, where the last path is preferred to prevent unnecessary allocations. +# +# +# A deallocation of a small pointer then looks like this +#[ + dealloc -> rawDealloc -> chunk.owner == addr(a) --------------> This thread owns the chunk ------> The current chunk is active -> Chunk is completely unused -----> Chunk references no foreign cells + | | (Add cell into the current chunk) | Return the current chunk back to tlsf + | | | | + v v v v + A different thread owns this chunk. The current chunk is not active. chunk.free was < size Chunk references foreign cells, noop + Add the cell to a.sharedFreeLists Add the cell into the active chunk Activate the chunk (end) + (end) (end) (end) +]# +# So "true" deallocation is delayed for as long as possible in favor of reusing cells. const nimMinHeapPages {.intdefine.} = 128 # 0.5 MB @@ -71,6 +102,8 @@ const type FreeCell {.final, pure.} = object + # A free cell is a pointer that has been freed, meaning it became available for reuse. + # It may become foreign if it is lent to a chunk that did not create it, doing so reduces the amount of needed pages. next: ptr FreeCell # next free cell in chunk (overlaid with refcount) when not defined(gcDestructors): zeroField: int # 0 means cell is not used (overlaid with typ field) @@ -90,11 +123,18 @@ type SmallChunk = object of BaseChunk next, prev: PSmallChunk # chunks of the same size - freeList: ptr FreeCell - free: int # how many bytes remain - acc: int # accumulator for small object allocation - when defined(gcDestructors): - sharedFreeList: ptr FreeCell # make no attempt at avoiding false sharing for now for this object field + freeList: ptr FreeCell # Singly linked list of cells. They may be from foreign chunks or from the current chunk. + # Should be `nil` when the chunk isn't active in `a.freeSmallChunks`. + free: int32 # Bytes this chunk is able to provide using both the accumulator and free cells. + # When a cell is considered foreign, its source chunk's free field is NOT adjusted until it + # reaches dealloc while the source chunk is active. + # Instead, the receiving chunk gains the capacity and thus reserves space in the foreign chunk. + acc: uint32 # Offset from data, used when there are no free cells available but the chunk is considered free. + foreignCells: int # When a free cell is given to a chunk that is not its origin, + # both the cell and the source chunk are considered foreign. + # Receiving a foreign cell can happen both when deallocating from another thread or when + # the active chunk in `a.freeSmallChunks` is not the current chunk. + # Freeing a chunk while `foreignCells > 0` leaks memory as all references to it become lost. data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory BigChunk = object of BaseChunk # not necessarily > PageSize! @@ -109,7 +149,12 @@ type MemRegion = object when not defined(gcDestructors): minLargeObj, maxLargeObj: int - freeSmallChunks: array[0..max(1,SmallChunkSize div MemAlign-1), PSmallChunk] + freeSmallChunks: array[0..max(1, SmallChunkSize div MemAlign-1), PSmallChunk] + # List of available chunks per size class. Only one is expected to be active per class. + when defined(gcDestructors): + sharedFreeLists: array[0..max(1, SmallChunkSize div MemAlign-1), ptr FreeCell] + # When a thread frees a pointer it did not create, it must not adjust the counters. + # Instead, the cell is placed here and deferred until the next allocation. flBitmap: uint32 slBitmap: array[RealFli, uint32] matrix: array[RealFli, array[MaxSli, PBigChunk]] @@ -334,7 +379,7 @@ when not defined(gcDestructors): n.link[0] = a.freeAvlNodes a.freeAvlNodes = n -proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int) = +proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int): ptr HeapLinks = var it = addr(a.heapLinks) while it != nil and it.len >= it.chunks.len: it = it.next if it == nil: @@ -343,10 +388,12 @@ proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int) = a.heapLinks.next = n n.chunks[0] = (p, size) n.len = 1 + result = n else: let L = it.len it.chunks[L] = (p, size) inc it.len + result = it when not defined(gcDestructors): include "system/avltree" @@ -431,7 +478,7 @@ iterator allObjects(m: var MemRegion): pointer {.inline.} = let size = c.size var a = cast[int](addr(c.data)) - let limit = a + c.acc + let limit = a + c.acc.int while a <% limit: yield cast[pointer](a) a = a +% size @@ -490,10 +537,10 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk = incCurrMem(a, size) inc(a.freeMem, size) - a.addHeapLink(result, size) + let heapLink = a.addHeapLink(result, size) when defined(debugHeapLinks): cprintf("owner: %p; result: %p; next pointer %p; size: %ld\n", addr(a), - result, result.heapLink, result.size) + result, heapLink, size) when defined(memtracker): trackLocation(addr result.size, sizeof(int)) @@ -775,41 +822,42 @@ when defined(gcDestructors): sysAssert c.next == nil, "c.next pointer must be nil" atomicPrepend a.sharedFreeListBigChunks, c - proc addToSharedFreeList(c: PSmallChunk; f: ptr FreeCell) {.inline.} = - atomicPrepend c.sharedFreeList, f + proc addToSharedFreeList(c: PSmallChunk; f: ptr FreeCell; size: int) {.inline.} = + atomicPrepend c.owner.sharedFreeLists[size], f + + const MaxSteps = 20 proc compensateCounters(a: var MemRegion; c: PSmallChunk; size: int) = # rawDealloc did NOT do the usual: # `inc(c.free, size); dec(a.occ, size)` because it wasn't the owner of these # memory locations. We have to compensate here for these for the entire list. - # Well, not for the entire list, but for `max` elements of the list because - # we split the list in order to achieve bounded response times. var it = c.freeList - var x = 0 - var maxIters = 20 # make it time-bounded + var total = 0 while it != nil: - if maxIters == 0: - let rest = it.next.loada - if rest != nil: - it.next.storea nil - addToSharedFreeList(c, rest) - break - inc x, size - it = it.next.loada - dec maxIters - inc(c.free, x) - dec(a.occ, x) + inc total, size + let chunk = cast[PSmallChunk](pageAddr(it)) + if c != chunk: + # The cell is foreign, potentially even from a foreign thread. + # It must block the current chunk from being freed, as doing so would leak memory. + inc c.foreignCells + it = it.next + # By not adjusting the foreign chunk we reserve space in it to prevent deallocation + inc(c.free, total) + dec(a.occ, total) proc freeDeferredObjects(a: var MemRegion; root: PBigChunk) = var it = root - var maxIters = 20 # make it time-bounded + var maxIters = MaxSteps # make it time-bounded while true: + let rest = it.next.loada + it.next.storea nil + deallocBigChunk(a, cast[PBigChunk](it)) if maxIters == 0: - let rest = it.next.loada - it.next.storea nil - addToSharedFreeListBigChunks(a, rest) + if rest != nil: + addToSharedFreeListBigChunks(a, rest) + sysAssert a.sharedFreeListBigChunks != nil, "re-enqueing failed" break - it = it.next.loada + it = rest dec maxIters if it == nil: break @@ -824,56 +872,85 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer = #c_fprintf(stdout, "alloc; size: %ld; %ld\n", requestedSize, size) if size <= SmallChunkSize-smallChunkOverhead(): + template fetchSharedCells(tc: PSmallChunk) = + # Consumes cells from (potentially) foreign threads from `a.sharedFreeLists[s]` + when defined(gcDestructors): + if tc.freeList == nil: + when hasThreadSupport: + # Steal the entire list from `sharedFreeList`: + tc.freeList = atomicExchangeN(addr a.sharedFreeLists[s], nil, ATOMIC_RELAXED) + else: + tc.freeList = a.sharedFreeLists[s] + a.sharedFreeLists[s] = nil + # if `tc.freeList` isn't nil, `tc` will gain capacity. + # We must calculate how much it gained and how many foreign cells are included. + compensateCounters(a, tc, size) + # allocate a small block: for small chunks, we use only its next pointer let s = size div MemAlign var c = a.freeSmallChunks[s] if c == nil: + # There is no free chunk of the requested size available, we need a new one. c = getSmallChunk(a) + # init all fields in case memory didn't get zeroed c.freeList = nil + c.foreignCells = 0 sysAssert c.size == PageSize, "rawAlloc 3" c.size = size - c.acc = size - when defined(gcDestructors): - c.sharedFreeList = nil - c.free = SmallChunkSize - smallChunkOverhead() - size + c.acc = size.uint32 + c.free = SmallChunkSize - smallChunkOverhead() - size.int32 sysAssert c.owner == addr(a), "rawAlloc: No owner set!" c.next = nil c.prev = nil - listAdd(a.freeSmallChunks[s], c) + # Shared cells are fetched here in case `c.size * 2 >= SmallChunkSize - smallChunkOverhead()`. + # For those single cell chunks, we would otherwise have to allocate a new one almost every time. + fetchSharedCells(c) + if c.free >= size: + # Because removals from `a.freeSmallChunks[s]` only happen in the other alloc branch and during dealloc, + # we must not add it to the list if it cannot be used the next time a pointer of `size` bytes is needed. + listAdd(a.freeSmallChunks[s], c) result = addr(c.data) sysAssert((cast[int](result) and (MemAlign-1)) == 0, "rawAlloc 4") else: + # There is a free chunk of the requested size available, use it. sysAssert(allocInv(a), "rawAlloc: begin c != nil") sysAssert c.next != c, "rawAlloc 5" #if c.size != size: # c_fprintf(stdout, "csize: %lld; size %lld\n", c.size, size) sysAssert c.size == size, "rawAlloc 6" - when defined(gcDestructors): - if c.freeList == nil: - when hasThreadSupport: - c.freeList = atomicExchangeN(addr c.sharedFreeList, nil, ATOMIC_RELAXED) - else: - c.freeList = c.sharedFreeList - c.sharedFreeList = nil - compensateCounters(a, c, size) if c.freeList == nil: - sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize, + sysAssert(c.acc.int + smallChunkOverhead() + size <= SmallChunkSize, "rawAlloc 7") - result = cast[pointer](cast[int](addr(c.data)) +% c.acc) + result = cast[pointer](cast[int](addr(c.data)) +% c.acc.int) inc(c.acc, size) else: + # There are free cells available, prefer them over the accumulator result = c.freeList when not defined(gcDestructors): sysAssert(c.freeList.zeroField == 0, "rawAlloc 8") c.freeList = c.freeList.next + if cast[PSmallChunk](pageAddr(result)) != c: + # This cell isn't a blocker for the current chunk's deallocation anymore + dec(c.foreignCells) + else: + sysAssert(c == cast[PSmallChunk](pageAddr(result)), "rawAlloc: Bad cell") + # Even if the cell we return is foreign, the local chunk's capacity decreases. + # The capacity was previously reserved in the source chunk (when it first got allocated), + # then added into the current chunk during dealloc, + # so the source chunk will not be freed or leak memory because of this. dec(c.free, size) sysAssert((cast[int](result) and (MemAlign-1)) == 0, "rawAlloc 9") sysAssert(allocInv(a), "rawAlloc: end c != nil") - sysAssert(allocInv(a), "rawAlloc: before c.free < size") - if c.free < size: - sysAssert(allocInv(a), "rawAlloc: before listRemove test") - listRemove(a.freeSmallChunks[s], c) - sysAssert(allocInv(a), "rawAlloc: end listRemove test") + # We fetch deferred cells *after* advancing `c.freeList`/`acc` to adjust `c.free`. + # If after the adjustment it turns out there's free cells available, + # the chunk stays in `a.freeSmallChunks[s]` and the need for a new chunk is delayed. + fetchSharedCells(c) + sysAssert(allocInv(a), "rawAlloc: before c.free < size") + if c.free < size: + # Even after fetching shared cells the chunk has no usable memory left. It is no longer the active chunk + sysAssert(allocInv(a), "rawAlloc: before listRemove test") + listRemove(a.freeSmallChunks[s], c) + sysAssert(allocInv(a), "rawAlloc: end listRemove test") sysAssert(((cast[int](result) and PageMask) - smallChunkOverhead()) %% size == 0, "rawAlloc 21") sysAssert(allocInv(a), "rawAlloc: end small size") @@ -905,7 +982,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer = trackSize(c.size) sysAssert(isAccessible(a, result), "rawAlloc 14") sysAssert(allocInv(a), "rawAlloc: end") - when logAlloc: cprintf("var pointer_%p = alloc(%ld)\n", result, requestedSize) + when logAlloc: cprintf("var pointer_%p = alloc(%ld) # %p\n", result, requestedSize, addr a) proc rawAlloc0(a: var MemRegion, requestedSize: int): pointer = result = rawAlloc(a, requestedSize) @@ -921,7 +998,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) = if isSmallChunk(c): # `p` is within a small chunk: var c = cast[PSmallChunk](c) - var s = c.size + let s = c.size # ^ We might access thread foreign storage here. # The other thread cannot possibly free this block as it's still alive. var f = cast[ptr FreeCell](p) @@ -936,31 +1013,48 @@ proc rawDealloc(a: var MemRegion, p: pointer) = #echo("setting to nil: ", $cast[int](addr(f.zeroField))) sysAssert(f.zeroField != 0, "rawDealloc 1") f.zeroField = 0 - f.next = c.freeList - c.freeList = f when overwriteFree: # set to 0xff to check for usage after free bugs: nimSetMem(cast[pointer](cast[int](p) +% sizeof(FreeCell)), -1'i32, s -% sizeof(FreeCell)) - # check if it is not in the freeSmallChunks[s] list: - if c.free < s: - # add it to the freeSmallChunks[s] array: - listAdd(a.freeSmallChunks[s div MemAlign], c) - inc(c.free, s) + let activeChunk = a.freeSmallChunks[s div MemAlign] + if activeChunk != nil and c != activeChunk: + # This pointer is not part of the active chunk, lend it out + # and do not adjust the current chunk (same logic as compensateCounters.) + # Put the cell into the active chunk, + # may prevent a queue of available chunks from forming in a.freeSmallChunks[s div MemAlign]. + # This queue would otherwise waste memory in the form of free cells until we return to those chunks. + f.next = activeChunk.freeList + activeChunk.freeList = f # lend the cell + inc(activeChunk.free, s) # By not adjusting the current chunk's capacity it is prevented from being freed + inc(activeChunk.foreignCells) # The cell is now considered foreign from the perspective of the active chunk else: - inc(c.free, s) - if c.free == SmallChunkSize-smallChunkOverhead(): - listRemove(a.freeSmallChunks[s div MemAlign], c) - c.size = SmallChunkSize - freeBigChunk(a, cast[PBigChunk](c)) + f.next = c.freeList + c.freeList = f + if c.free < s: + # The chunk could not have been active as it didn't have enough space to give + listAdd(a.freeSmallChunks[s div MemAlign], c) + inc(c.free, s) + else: + inc(c.free, s) + # Free only if the entire chunk is unused and there are no borrowed cells. + # If the chunk were to be freed while it references foreign cells, + # the foreign chunks will leak memory and can never be freed. + if c.free == SmallChunkSize-smallChunkOverhead() and c.foreignCells == 0: + listRemove(a.freeSmallChunks[s div MemAlign], c) + c.size = SmallChunkSize + freeBigChunk(a, cast[PBigChunk](c)) else: + when logAlloc: cprintf("dealloc(pointer_%p) # SMALL FROM %p CALLER %p\n", p, c.owner, addr(a)) + when defined(gcDestructors): - addToSharedFreeList(c, f) + addToSharedFreeList(c, f, s div MemAlign) sysAssert(((cast[int](p) and PageMask) - smallChunkOverhead()) %% s == 0, "rawDealloc 2") else: # set to 0xff to check for usage after free bugs: when overwriteFree: nimSetMem(p, -1'i32, c.size -% bigChunkOverhead()) + when logAlloc: cprintf("dealloc(pointer_%p) # BIG %p\n", p, c.owner) when defined(gcDestructors): if c.owner == addr(a): deallocBigChunk(a, cast[PBigChunk](c)) @@ -968,8 +1062,9 @@ proc rawDealloc(a: var MemRegion, p: pointer) = addToSharedFreeListBigChunks(c.owner[], cast[PBigChunk](c)) else: deallocBigChunk(a, cast[PBigChunk](c)) + sysAssert(allocInv(a), "rawDealloc: end") - when logAlloc: cprintf("dealloc(pointer_%p)\n", p) + #when logAlloc: cprintf("dealloc(pointer_%p)\n", p) when not defined(gcDestructors): proc isAllocatedPtr(a: MemRegion, p: pointer): bool = @@ -980,7 +1075,7 @@ when not defined(gcDestructors): var c = cast[PSmallChunk](c) var offset = (cast[int](p) and (PageSize-1)) -% smallChunkOverhead() - result = (c.acc >% offset) and (offset %% c.size == 0) and + result = (c.acc.int >% offset) and (offset %% c.size == 0) and (cast[ptr FreeCell](p).zeroField >% 1) else: var c = cast[PBigChunk](c) @@ -998,7 +1093,7 @@ when not defined(gcDestructors): var c = cast[PSmallChunk](c) var offset = (cast[int](p) and (PageSize-1)) -% smallChunkOverhead() - if c.acc >% offset: + if c.acc.int >% offset: sysAssert(cast[int](addr(c.data)) +% offset == cast[int](p), "offset is not what you think it is") var d = cast[ptr FreeCell](cast[int](addr(c.data)) +% @@ -1091,7 +1186,7 @@ proc deallocOsPages(a: var MemRegion) = let (p, size) = it.chunks[i] when defined(debugHeapLinks): cprintf("owner %p; dealloc A: %p size: %ld; next: %p\n", addr(a), - it, it.size, next) + it, size, next) sysAssert size >= PageSize, "origSize too small" osDeallocPages(p, size) it = next diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index a8a4bd767..3098e17d6 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -65,7 +65,7 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or SIGSEGV* = cint(11) SIGTERM* = cint(15) SIGPIPE* = cint(13) - SIG_DFL* = cast[CSighandlerT](0) + SIG_DFL* = CSighandlerT(nil) elif defined(haiku): const SIGABRT* = cint(6) @@ -75,7 +75,7 @@ elif defined(haiku): SIGSEGV* = cint(11) SIGTERM* = cint(15) SIGPIPE* = cint(7) - SIG_DFL* = cast[CSighandlerT](0) + SIG_DFL* = CSighandlerT(nil) else: when defined(nimscript): {.error: "SIGABRT not ported to your platform".} @@ -187,6 +187,9 @@ proc c_sprintf*(buf, frmt: cstring): cint {. importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.} # we use it only in a way that cannot lead to security issues +proc c_snprintf*(buf: cstring, n: csize_t, frmt: cstring): cint {. + importc: "snprintf", header: "<stdio.h>", varargs, noSideEffect.} + when defined(zephyr) and not defined(zephyrUseLibcMalloc): proc c_malloc*(size: csize_t): pointer {. importc: "k_malloc", header: "<kernel.h>".} @@ -224,7 +227,7 @@ proc rawWriteString*(f: CFilePtr, s: cstring, length: int) {.compilerproc, nonRe proc rawWrite*(f: CFilePtr, s: cstring) {.compilerproc, nonReloadable, inline.} = # we cannot throw an exception here! - discard c_fwrite(s, 1, cast[csize_t](s.len), f) + discard c_fwrite(s, 1, c_strlen(s), f) discard c_fflush(f) {.pop.} diff --git a/lib/system/arc.nim b/lib/system/arc.nim index 0624bd4e3..d001fcaa5 100644 --- a/lib/system/arc.nim +++ b/lib/system/arc.nim @@ -26,6 +26,9 @@ else: rcMask = 0b111 rcShift = 3 # shift by rcShift to get the reference counter +const + orcLeakDetector = defined(nimOrcLeakDetector) + type RefHeader = object rc: int # the object header is now a single RC field. @@ -36,9 +39,21 @@ type # in O(1) without doubly linked lists when defined(nimArcDebug) or defined(nimArcIds): refId: int + when defined(gcOrc) and orcLeakDetector: + filename: cstring + line: int Cell = ptr RefHeader +template setFrameInfo(c: Cell) = + when orcLeakDetector: + if framePtr != nil and framePtr.prev != nil: + c.filename = framePtr.prev.filename + c.line = framePtr.prev.line + else: + c.filename = nil + c.line = 0 + template head(p: pointer): Cell = cast[Cell](cast[int](p) -% sizeof(RefHeader)) @@ -87,6 +102,7 @@ proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} = cfprintf(cstderr, "[nimNewObj] %p %ld\n", result, head(result).count) when traceCollector: cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result) + setFrameInfo head(result) proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} = # Same as 'newNewObj' but do not initialize the memory to zero. @@ -109,6 +125,7 @@ proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} = when traceCollector: cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result) + setFrameInfo head(result) proc nimDecWeakRef(p: pointer) {.compilerRtl, inl.} = decrement head(p) @@ -202,15 +219,22 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} = writeStackTrace() cfprintf(cstderr, "[DecRef] %p %ld\n", p, cell.count) - if cell.count == 0: - result = true - when traceCollector: - cprintf("[ABOUT TO DESTROY] %p\n", cell) + when defined(gcAtomicArc) and hasThreadSupport: + # `atomicDec` returns the new value + if atomicDec(cell.rc, rcIncrement) == -rcIncrement: + result = true + when traceCollector: + cprintf("[ABOUT TO DESTROY] %p\n", cell) else: - decrement cell - # According to Lins it's correct to do nothing else here. - when traceCollector: - cprintf("[DECREF] %p\n", cell) + if cell.count == 0: + result = true + when traceCollector: + cprintf("[ABOUT TO DESTROY] %p\n", cell) + else: + decrement cell + # According to Lins it's correct to do nothing else here. + when traceCollector: + cprintf("[DECREF] %p\n", cell) proc GC_unref*[T](x: ref T) = ## New runtime only supports this operation for 'ref T'. @@ -236,3 +260,8 @@ template tearDownForeignThreadGc* = proc isObjDisplayCheck(source: PNimTypeV2, targetDepth: int16, token: uint32): bool {.compilerRtl, inl.} = result = targetDepth <= source.depth and source.display[targetDepth] == token + +when defined(gcDestructors): + proc nimGetVTable(p: pointer, index: int): pointer + {.compilerRtl, inline, raises: [].} = + result = cast[ptr PNimTypeV2](p).vTable[index] diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim index fa7ca784d..e229a0f4b 100644 --- a/lib/system/arithmetics.nim +++ b/lib/system/arithmetics.nim @@ -1,4 +1,4 @@ -proc succ*[T: Ordinal](x: T, y: int = 1): T {.magic: "Succ", noSideEffect.} = +proc succ*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Succ", noSideEffect.} = ## Returns the `y`-th successor (default: 1) of the value `x`. ## ## If such a value does not exist, `OverflowDefect` is raised @@ -7,7 +7,7 @@ proc succ*[T: Ordinal](x: T, y: int = 1): T {.magic: "Succ", noSideEffect.} = assert succ(5) == 6 assert succ(5, 3) == 8 -proc pred*[T: Ordinal](x: T, y: int = 1): T {.magic: "Pred", noSideEffect.} = +proc pred*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Pred", noSideEffect.} = ## Returns the `y`-th predecessor (default: 1) of the value `x`. ## ## If such a value does not exist, `OverflowDefect` is raised @@ -16,7 +16,7 @@ proc pred*[T: Ordinal](x: T, y: int = 1): T {.magic: "Pred", noSideEffect.} = assert pred(5) == 4 assert pred(5, 3) == 2 -proc inc*[T: Ordinal](x: var T, y: int = 1) {.magic: "Inc", noSideEffect.} = +proc inc*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Inc", noSideEffect.} = ## Increments the ordinal `x` by `y`. ## ## If such a value does not exist, `OverflowDefect` is raised or a compile @@ -28,7 +28,7 @@ proc inc*[T: Ordinal](x: var T, y: int = 1) {.magic: "Inc", noSideEffect.} = inc(i, 3) assert i == 6 -proc dec*[T: Ordinal](x: var T, y: int = 1) {.magic: "Dec", noSideEffect.} = +proc dec*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Dec", noSideEffect.} = ## Decrements the ordinal `x` by `y`. ## ## If such a value does not exist, `OverflowDefect` is raised or a compile diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim index 9d0d248c3..9a7645f9b 100644 --- a/lib/system/cgprocs.nim +++ b/lib/system/cgprocs.nim @@ -8,13 +8,3 @@ # # Headers for procs that the code generator depends on ("compilerprocs") - -type - LibHandle = pointer # private type - ProcAddr = pointer # library loading and loading of procs: - -proc nimLoadLibrary(path: string): LibHandle {.compilerproc, hcrInline, nonReloadable.} -proc nimUnloadLibrary(lib: LibHandle) {.compilerproc, hcrInline, nonReloadable.} -proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc, hcrInline, nonReloadable.} - -proc nimLoadLibraryError(path: string) {.compilerproc, hcrInline, nonReloadable.} diff --git a/lib/system/channels_builtin.nim b/lib/system/channels_builtin.nim index 088003e4b..02b4d8cbf 100644 --- a/lib/system/channels_builtin.nim +++ b/lib/system/channels_builtin.nim @@ -394,7 +394,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) = q.ready = false if typ != q.elemType: releaseSys(q.lock) - sysFatal(ValueError, "cannot receive message of wrong type") + raise newException(ValueError, "cannot receive message of wrong type") rawRecv(q, res, typ) if q.maxItems > 0 and q.count == q.maxItems - 1: # Parent thread is awaiting in send. Wake it up. diff --git a/lib/system/comparisons.nim b/lib/system/comparisons.nim index 9759c3c99..a8d78bb93 100644 --- a/lib/system/comparisons.nim +++ b/lib/system/comparisons.nim @@ -324,7 +324,7 @@ proc `==`*[T](x, y: seq[T]): bool {.noSideEffect.} = return true else: var sameObject = false - asm """`sameObject` = `x` === `y`""" + {.emit: """`sameObject` = `x` === `y`;""".} if sameObject: return true if x.len != y.len: diff --git a/lib/system/compilation.nim b/lib/system/compilation.nim index 7cf80eb17..cdb976ed5 100644 --- a/lib/system/compilation.nim +++ b/lib/system/compilation.nim @@ -6,7 +6,7 @@ const ## ``` # see also std/private/since - NimMinor* {.intdefine.}: int = 1 + NimMinor* {.intdefine.}: int = 2 ## is the minor number of Nim's version. ## Odd for devel, even for releases. @@ -144,16 +144,17 @@ template currentSourcePath*: string = instantiationInfo(-1, true).filename ## Returns the full file-system path of the current source. ## ## To get the directory containing the current source, use it with - ## `os.parentDir() <os.html#parentDir%2Cstring>`_ as `currentSourcePath.parentDir()`. + ## `ospaths2.parentDir() <ospaths2.html#parentDir%2Cstring>`_ as + ## `currentSourcePath.parentDir()`. ## ## The path returned by this template is set at compile time. ## ## See the docstring of `macros.getProjectPath() <macros.html#getProjectPath>`_ - ## for an example to see the distinction between the `currentSourcePath` - ## and `getProjectPath`. + ## for an example to see the distinction between the `currentSourcePath()` + ## and `getProjectPath()`. ## ## See also: - ## * `getCurrentDir proc <os.html#getCurrentDir>`_ + ## * `ospaths2.getCurrentDir() proc <ospaths2.html#getCurrentDir>`_ proc slurp*(filename: string): string {.magic: "Slurp".} ## This is an alias for `staticRead <#staticRead,string>`_. diff --git a/lib/system/embedded.nim b/lib/system/embedded.nim index e0b053c7b..ea6776f58 100644 --- a/lib/system/embedded.nim +++ b/lib/system/embedded.nim @@ -19,8 +19,9 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = discard proc popFrame {.compilerRtl, inl.} = discard proc setFrame(s: PFrame) {.compilerRtl, inl.} = discard -proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = discard -proc popSafePoint {.compilerRtl, inl.} = discard +when not gotoBasedExceptions: + proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = discard + proc popSafePoint {.compilerRtl, inl.} = discard proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} = discard proc popCurrentException {.compilerRtl, inl.} = discard diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 6b40ca391..dae5c4a4a 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -73,26 +73,45 @@ type when NimStackTraceMsgs: var frameMsgBuf* {.threadvar.}: string + +when not defined(nimV2): + var + framePtr {.threadvar.}: PFrame + var - framePtr {.threadvar.}: PFrame - excHandler {.threadvar.}: PSafePoint - # list of exception handlers - # a global variable for the root of all try blocks currException {.threadvar.}: ref Exception - gcFramePtr {.threadvar.}: GcFrame -type - FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame, - excHandler: PSafePoint, currException: ref Exception] +when not gotoBasedExceptions: + var + excHandler {.threadvar.}: PSafePoint + # list of exception handlers + # a global variable for the root of all try blocks + gcFramePtr {.threadvar.}: GcFrame + +when gotoBasedExceptions: + type + FrameState = tuple[framePtr: PFrame, + currException: ref Exception] +else: + type + FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame, + excHandler: PSafePoint, currException: ref Exception] proc getFrameState*(): FrameState {.compilerRtl, inl.} = - return (gcFramePtr, framePtr, excHandler, currException) + when gotoBasedExceptions: + return (framePtr, currException) + else: + return (gcFramePtr, framePtr, excHandler, currException) proc setFrameState*(state: FrameState) {.compilerRtl, inl.} = - gcFramePtr = state.gcFramePtr - framePtr = state.framePtr - excHandler = state.excHandler - currException = state.currException + when gotoBasedExceptions: + framePtr = state.framePtr + currException = state.currException + else: + gcFramePtr = state.gcFramePtr + framePtr = state.framePtr + excHandler = state.excHandler + currException = state.currException proc getFrame*(): PFrame {.compilerRtl, inl.} = framePtr @@ -114,20 +133,21 @@ when false: proc setFrame*(s: PFrame) {.compilerRtl, inl.} = framePtr = s -proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr -proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev -proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s -proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} = - s.prev = gcFramePtr - zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer)) - gcFramePtr = s +when not gotoBasedExceptions: + proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr + proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev + proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s + proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} = + s.prev = gcFramePtr + zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer)) + gcFramePtr = s -proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = - s.prev = excHandler - excHandler = s + proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = + s.prev = excHandler + excHandler = s -proc popSafePoint {.compilerRtl, inl.} = - excHandler = excHandler.prev + proc popSafePoint {.compilerRtl, inl.} = + excHandler = excHandler.prev proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inl.} = e.up = currException @@ -407,15 +427,16 @@ proc reportUnhandledError(e: ref Exception) {.nodestroy, gcsafe.} = when hostOS != "any": reportUnhandledErrorAux(e) -proc nimLeaveFinally() {.compilerRtl.} = - when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions: - {.emit: "throw;".} - else: - if excHandler != nil: - c_longjmp(excHandler.context, 1) +when not gotoBasedExceptions: + proc nimLeaveFinally() {.compilerRtl.} = + when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions: + {.emit: "throw;".} else: - reportUnhandledError(currException) - rawQuit(1) + if excHandler != nil: + c_longjmp(excHandler.context, 1) + else: + reportUnhandledError(currException) + rawQuit(1) when gotoBasedExceptions: var nimInErrorMode {.threadvar.}: bool diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index f1f94d078..25c05e52d 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -16,19 +16,19 @@ const when hostOS == "standalone": include "$projectpath/panicoverride" - func sysFatal(exceptn: typedesc, message: string) {.inline.} = + func sysFatal(exceptn: typedesc[Defect], message: string) {.inline.} = panic(message) - func sysFatal(exceptn: typedesc, message, arg: string) {.inline.} = + func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline.} = rawoutput(message) panic(arg) -elif (quirkyExceptions or defined(nimPanics)) and not defined(nimscript): +elif quirkyExceptions and not defined(nimscript): import ansi_c func name(t: typedesc): string {.magic: "TypeTrait".} - func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline, noreturn.} = when nimvm: # TODO when doAssertRaises works in CT, add a test for it raise (ref exceptn)(msg: message & arg) @@ -45,14 +45,14 @@ elif (quirkyExceptions or defined(nimPanics)) and not defined(nimscript): cstderr.rawWrite buf rawQuit 1 - func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc[Defect], message: string) {.inline, noreturn.} = sysFatal(exceptn, message, "") else: - func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc[Defect], message: string) {.inline, noreturn.} = raise (ref exceptn)(msg: message) - func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline, noreturn.} = raise (ref exceptn)(msg: message & arg) {.pop.} diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 35ab26903..9289c7f55 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -78,7 +78,7 @@ when defined(memProfiler): proc nimProfile(requestedSize: int) {.benign.} when hasThreadSupport: - import sharedlist + import std/sharedlist const rcIncrement = 0b1000 # so that lowest 3 bits are not touched diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 72d22f08b..c885a6893 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -27,7 +27,7 @@ when defined(memProfiler): proc nimProfile(requestedSize: int) when hasThreadSupport: - import sharedlist + import std/sharedlist type WalkOp = enum diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 9acaae88b..a26aff982 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -59,7 +59,7 @@ type tyOwned, tyUnused1, tyUnused2, tyVarargsHidden, tyUncheckedArray, - tyProxyHidden, + tyErrorHidden, tyBuiltInTypeClassHidden, tyUserTypeClassHidden, tyUserTypeClassInstHidden, diff --git a/lib/system/indices.nim b/lib/system/indices.nim index f4a140346..f2bad2528 100644 --- a/lib/system/indices.nim +++ b/lib/system/indices.nim @@ -110,6 +110,9 @@ proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.s ## var a = [1, 2, 3, 4] ## assert a[0..2] == @[1, 2, 3] ## ``` + ## + ## See also: + ## * `toOpenArray(array[I, T];I,I) <#toOpenArray,array[I,T],I,I>`_ let xa = a ^^ x.a let L = (a ^^ x.b) - xa + 1 result = newSeq[T](L) @@ -136,6 +139,9 @@ proc `[]`*[T; U, V: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] {.systemR ## var s = @[1, 2, 3, 4] ## assert s[0..2] == @[1, 2, 3] ## ``` + ## + ## See also: + ## * `toOpenArray(openArray[T];int,int) <#toOpenArray,openArray[T],int,int>`_ let a = s ^^ x.a let L = (s ^^ x.b) - a + 1 newSeq(result, L) diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim index 4bd12680f..125bee98f 100644 --- a/lib/system/iterators.nim +++ b/lib/system/iterators.nim @@ -8,12 +8,17 @@ when not defined(nimNoLentIterators): else: template lent2(T): untyped = T +template unCheckedInc(x) = + {.push overflowChecks: off.} + inc(x) + {.pop.} + iterator items*[T: not char](a: openArray[T]): lent2 T {.inline.} = ## Iterates over each item of `a`. var i = 0 while i < len(a): yield a[i] - inc(i) + unCheckedInc(i) iterator items*[T: char](a: openArray[T]): T {.inline.} = ## Iterates over each item of `a`. @@ -23,14 +28,14 @@ iterator items*[T: char](a: openArray[T]): T {.inline.} = var i = 0 while i < len(a): yield a[i] - inc(i) + unCheckedInc(i) iterator mitems*[T](a: var openArray[T]): var T {.inline.} = ## Iterates over each item of `a` so that you can modify the yielded value. var i = 0 while i < len(a): yield a[i] - inc(i) + unCheckedInc(i) iterator items*[IX, T](a: array[IX, T]): T {.inline.} = ## Iterates over each item of `a`. @@ -39,7 +44,7 @@ iterator items*[IX, T](a: array[IX, T]): T {.inline.} = while true: yield a[i] if i >= high(IX): break - inc(i) + unCheckedInc(i) iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} = ## Iterates over each item of `a` so that you can modify the yielded value. @@ -48,7 +53,7 @@ iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} = while true: yield a[i] if i >= high(IX): break - inc(i) + unCheckedInc(i) iterator items*[T](a: set[T]): T {.inline.} = ## Iterates over each element of `a`. `items` iterates only over the @@ -56,8 +61,11 @@ iterator items*[T](a: set[T]): T {.inline.} = ## able to hold). var i = low(T).int while i <= high(T).int: - if T(i) in a: yield T(i) - inc(i) + when T is enum and not defined(js): + if cast[T](i) in a: yield cast[T](i) + else: + if T(i) in a: yield T(i) + unCheckedInc(i) iterator items*(a: cstring): char {.inline.} = ## Iterates over each item of `a`. @@ -76,7 +84,7 @@ iterator items*(a: cstring): char {.inline.} = let n = len(a) while i < n: yield a[i] - inc(i) + unCheckedInc(i) when defined(js): impl() else: when nimvm: @@ -86,7 +94,7 @@ iterator items*(a: cstring): char {.inline.} = var i = 0 while a[i] != '\0': yield a[i] - inc(i) + unCheckedInc(i) iterator mitems*(a: var cstring): var char {.inline.} = ## Iterates over each item of `a` so that you can modify the yielded value. @@ -109,7 +117,7 @@ iterator mitems*(a: var cstring): var char {.inline.} = let n = len(a) while i < n: yield a[i] - inc(i) + unCheckedInc(i) when defined(js): impl() else: when nimvm: impl() @@ -117,7 +125,7 @@ iterator mitems*(a: var cstring): var char {.inline.} = var i = 0 while a[i] != '\0': yield a[i] - inc(i) + unCheckedInc(i) iterator items*[T: enum and Ordinal](E: typedesc[T]): T = ## Iterates over the values of `E`. @@ -140,7 +148,7 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} = var i = 0 while i < len(a): yield (i, a[i]) - inc(i) + unCheckedInc(i) iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} = ## Iterates over each item of `a`. Yields `(index, a[index])` pairs. @@ -148,7 +156,7 @@ iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} var i = 0 while i < len(a): yield (i, a[i]) - inc(i) + unCheckedInc(i) iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} = ## Iterates over each item of `a`. Yields `(index, a[index])` pairs. @@ -157,7 +165,7 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} = while true: yield (i, a[i]) if i >= high(IX): break - inc(i) + unCheckedInc(i) iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} = ## Iterates over each item of `a`. Yields `(index, a[index])` pairs. @@ -167,7 +175,7 @@ iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inlin while true: yield (i, a[i]) if i >= high(IX): break - inc(i) + unCheckedInc(i) iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} = ## Iterates over each item of `a`. Yields `(index, a[index])` pairs. @@ -175,7 +183,7 @@ iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} = let L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the seq changed while iterating over it") iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} = @@ -185,7 +193,7 @@ iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} = let L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the seq changed while iterating over it") iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} = @@ -194,7 +202,7 @@ iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} = let L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the string changed while iterating over it") iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} = @@ -204,7 +212,7 @@ iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} = let L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the string changed while iterating over it") iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} = @@ -214,12 +222,12 @@ iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} = var L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) else: var i = 0 while a[i] != '\0': yield (i, a[i]) - inc(i) + unCheckedInc(i) iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} = ## Iterates over each item of `a`. Yields `(index, a[index])` pairs. @@ -229,12 +237,12 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} = var L = len(a) while i < L: yield (i, a[i]) - inc(i) + unCheckedInc(i) else: var i = 0 while a[i] != '\0': yield (i, a[i]) - inc(i) + unCheckedInc(i) iterator items*[T](a: seq[T]): lent2 T {.inline.} = ## Iterates over each item of `a`. @@ -242,7 +250,7 @@ iterator items*[T](a: seq[T]): lent2 T {.inline.} = let L = len(a) while i < L: yield a[i] - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the seq changed while iterating over it") iterator mitems*[T](a: var seq[T]): var T {.inline.} = @@ -251,7 +259,7 @@ iterator mitems*[T](a: var seq[T]): var T {.inline.} = let L = len(a) while i < L: yield a[i] - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the seq changed while iterating over it") iterator items*(a: string): char {.inline.} = @@ -260,7 +268,7 @@ iterator items*(a: string): char {.inline.} = let L = len(a) while i < L: yield a[i] - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the string changed while iterating over it") iterator mitems*(a: var string): var char {.inline.} = @@ -269,7 +277,7 @@ iterator mitems*(a: var string): var char {.inline.} = let L = len(a) while i < L: yield a[i] - inc(i) + unCheckedInc(i) assert(len(a) == L, "the length of the string changed while iterating over it") diff --git a/lib/system/iterators_1.nim b/lib/system/iterators_1.nim index be61fd62c..d00e3f823 100644 --- a/lib/system/iterators_1.nim +++ b/lib/system/iterators_1.nim @@ -16,7 +16,7 @@ iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} = let x = collect(newSeq): for i in countdown(7, 3): i - + assert x == @[7, 6, 5, 4, 3] let y = collect(newseq): @@ -32,7 +32,10 @@ iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} = elif T is IntLikeForCount and T is Ordinal: var res = int(a) while res >= int(b): - yield T(res) + when defined(nimHasCastExtendedVm): + yield cast[T](res) + else: + yield T(res) dec(res, step) else: var res = a @@ -64,7 +67,10 @@ iterator countup*[T](a, b: T, step: Positive = 1): T {.inline.} = when T is IntLikeForCount and T is Ordinal: var res = int(a) while res <= int(b): - yield T(res) + when defined(nimHasCastExtendedVm): + yield cast[T](res) + else: + yield T(res) inc(res, step) else: var res = a @@ -89,7 +95,10 @@ iterator `..`*[T](a, b: T): T {.inline.} = when T is IntLikeForCount and T is Ordinal: var res = int(a) while res <= int(b): - yield T(res) + when defined(nimHasCastExtendedVm): + yield cast[T](res) + else: + yield T(res) inc(res) else: var res = a diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 3bf506e1e..5599240fd 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -49,7 +49,7 @@ proc nimCharToStr(x: char): string {.compilerproc.} = result[0] = x proc isNimException(): bool {.asmNoStackFrame.} = - asm "return `lastJSError` && `lastJSError`.m_type;" + {.emit: "return `lastJSError` && `lastJSError`.m_type;".} proc getCurrentException*(): ref Exception {.compilerRtl, benign.} = if isNimException(): result = cast[ref Exception](lastJSError) @@ -72,6 +72,10 @@ proc getCurrentExceptionMsg*(): string = proc setCurrentException*(exc: ref Exception) = lastJSError = cast[PJSError](exc) +proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} = + ## Used to set up exception handling for closure iterators + setCurrentException(e) + proc auxWriteStackTrace(f: PCallFrame): string = type TempFrame = tuple[procname: cstring, line: int, filename: cstring] @@ -148,7 +152,7 @@ proc raiseException(e: ref Exception, ename: cstring) {. unhandledException(e) when NimStackTrace: e.trace = rawWriteStackTrace() - asm "throw `e`;" + {.emit: "throw `e`;".} proc reraiseException() {.compilerproc, asmNoStackFrame.} = if lastJSError == nil: @@ -158,7 +162,7 @@ proc reraiseException() {.compilerproc, asmNoStackFrame.} = if isNimException(): unhandledException(cast[ref Exception](lastJSError)) - asm "throw lastJSError;" + {.emit: "throw lastJSError;".} proc raiseOverflow {.exportc: "raiseOverflow", noreturn, compilerproc.} = raise newException(OverflowDefect, "over- or underflow") @@ -176,7 +180,7 @@ proc raiseFieldError2(f: string, discVal: string) {.compilerproc, noreturn.} = raise newException(FieldDefect, formatFieldDefect(f, discVal)) proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = {}; for (var i = 0; i < arguments.length; ++i) { var x = arguments[i]; @@ -189,7 +193,7 @@ proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} = } } return result; - """ + """.} proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} = {.emit: """ @@ -277,62 +281,64 @@ proc toJSStr(s: string): cstring {.compilerproc.} = result = join(res) proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} = - asm """ - return new Array(`len`); - """ + {.emit: """ + var result = new Array(`len`); + for (var i = 0; i < `len`; i++) {result[i] = 0;} + return result; + """.} proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} = # argument type is a fake - asm """ + {.emit: """ var result = 0; for (var elem in `a`) { ++result; } return result; - """ + """.} proc SetEq(a, b: int): bool {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ for (var elem in `a`) { if (!`b`[elem]) return false; } for (var elem in `b`) { if (!`a`[elem]) return false; } return true; - """ + """.} proc SetLe(a, b: int): bool {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ for (var elem in `a`) { if (!`b`[elem]) return false; } return true; - """ + """.} proc SetLt(a, b: int): bool {.compilerproc.} = result = SetLe(a, b) and not SetEq(a, b) proc SetMul(a, b: int): int {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ var result = {}; for (var elem in `a`) { if (`b`[elem]) { result[elem] = true; } } return result; - """ + """.} proc SetPlus(a, b: int): int {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ var result = {}; for (var elem in `a`) { result[elem] = true; } for (var elem in `b`) { result[elem] = true; } return result; - """ + """.} proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ var result = {}; for (var elem in `a`) { if (!`b`[elem]) { result[elem] = true; } } return result; - """ + """.} proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`a` == `b`) return 0; if (!`a`) return -1; if (!`b`) return 1; @@ -341,7 +347,7 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} = if (result != 0) return result; } return `a`.length - `b`.length; - """ + """.} proc cmp(x, y: string): int = when nimvm: @@ -352,7 +358,7 @@ proc cmp(x, y: string): int = result = cmpStrings(x, y) proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`a` == `b`) return true; if (`a` === null && `b`.length == 0) return true; if (`b` === null && `a`.length == 0) return true; @@ -362,29 +368,29 @@ proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerproc.} = for (var i = 0; i < alen; ++i) if (`a`[i] != `b`[i]) return false; return true; - """ + """.} when defined(kwin): proc rawEcho {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ var buf = ""; for (var i = 0; i < arguments.length; ++i) { buf += `toJSStr`(arguments[i]); } print(buf); - """ + """.} elif not defined(nimOldEcho): proc ewriteln(x: cstring) = log(x) proc rawEcho {.compilerproc, asmNoStackFrame.} = - asm """ + {.emit: """ var buf = ""; for (var i = 0; i < arguments.length; ++i) { buf += `toJSStr`(arguments[i]); } console.log(buf); - """ + """.} else: proc ewriteln(x: cstring) = @@ -412,84 +418,84 @@ else: # Arithmetic: proc checkOverflowInt(a: int) {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`a` > 2147483647 || `a` < -2147483648) `raiseOverflow`(); - """ + """.} proc addInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` + `b`; `checkOverflowInt`(result); return result; - """ + """.} proc subInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` - `b`; `checkOverflowInt`(result); return result; - """ + """.} proc mulInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` * `b`; `checkOverflowInt`(result); return result; - """ + """.} proc divInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`b` == 0) `raiseDivByZero`(); if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); return Math.trunc(`a` / `b`); - """ + """.} proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`b` == 0) `raiseDivByZero`(); if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); return Math.trunc(`a` % `b`); - """ + """.} proc checkOverflowInt64(a: int64) {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`a` > 9223372036854775807n || `a` < -9223372036854775808n) `raiseOverflow`(); - """ + """.} proc addInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` + `b`; `checkOverflowInt64`(result); return result; - """ + """.} proc subInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` - `b`; `checkOverflowInt64`(result); return result; - """ + """.} proc mulInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ var result = `a` * `b`; `checkOverflowInt64`(result); return result; - """ + """.} proc divInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`b` == 0n) `raiseDivByZero`(); if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`(); return `a` / `b`; - """ + """.} proc modInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = - asm """ + {.emit: """ if (`b` == 0n) `raiseDivByZero`(); if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`(); return `a` % `b`; - """ + """.} proc negInt(a: int): int {.compilerproc.} = result = a*(-1) @@ -506,7 +512,7 @@ proc absInt64(a: int64): int64 {.compilerproc.} = proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b -proc chckNilDisp(p: pointer) {.compilerproc.} = +proc chckNilDisp(p: JSRef) {.compilerproc.} = if p == nil: sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil") @@ -524,22 +530,22 @@ proc nimCopyAux(dest, src: JSRef, n: ptr TNimNode) {.compilerproc.} = case n.kind of nkNone: sysAssert(false, "nimCopyAux") of nkSlot: - asm """ + {.emit: """ `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ); - """ + """.} of nkList: - asm """ + {.emit: """ for (var i = 0; i < `n`.sons.length; i++) { nimCopyAux(`dest`, `src`, `n`.sons[i]); } - """ + """.} of nkCase: - asm """ + {.emit: """ `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ); for (var i = 0; i < `n`.sons.length; ++i) { nimCopyAux(`dest`, `src`, `n`.sons[i][1]); } - """ + """.} proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef = case ti.kind @@ -547,9 +553,9 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef = if not isFatPointer(ti): result = src else: - asm "`result` = [`src`[0], `src`[1]];" + {.emit: "`result` = [`src`[0], `src`[1]];".} of tySet: - asm """ + {.emit: """ if (`dest` === null || `dest` === undefined) { `dest` = {}; } @@ -558,18 +564,18 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef = } for (var key in `src`) { `dest`[key] = `src`[key]; } `result` = `dest`; - """ + """.} of tyTuple, tyObject: if ti.base != nil: result = nimCopy(dest, src, ti.base) elif ti.kind == tyObject: - asm "`result` = (`dest` === null || `dest` === undefined) ? {m_type: `ti`} : `dest`;" + {.emit: "`result` = (`dest` === null || `dest` === undefined) ? {m_type: `ti`} : `dest`;".} else: - asm "`result` = (`dest` === null || `dest` === undefined) ? {} : `dest`;" + {.emit: "`result` = (`dest` === null || `dest` === undefined) ? {} : `dest`;".} nimCopyAux(result, src, ti.node) of tyArrayConstr, tyArray: # In order to prevent a type change (TypedArray -> Array) and to have better copying performance, # arrays constructors are considered separately - asm """ + {.emit: """ if(ArrayBuffer.isView(`src`)) { if(`dest` === null || `dest` === undefined || `dest`.length != `src`.length) { `dest` = new `src`.constructor(`src`); @@ -591,9 +597,9 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef = } } } - """ + """.} of tySequence, tyOpenArray: - asm """ + {.emit: """ if (`src` === null) { `result` = null; } @@ -606,55 +612,24 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef = `result`[i] = nimCopy(`result`[i], `src`[i], `ti`.base); } } - """ + """.} of tyString: - asm """ + {.emit: """ if (`src` !== null) { `result` = `src`.slice(0); } - """ + """.} else: result = src -proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} = - asm "`result` = null;" - case ti.kind - of tyPtr, tyRef, tyVar, tyNil: - if isFatPointer(ti): - asm """ - `result` = [null, 0]; - """ - of tySet: - asm """ - `result` = {}; - """ - of tyTuple, tyObject: - if ti.kind == tyObject: - asm "`result` = {m_type: `ti`};" - else: - asm "`result` = {};" - of tySequence, tyOpenArray, tyString: - asm """ - `result` = []; - """ - of tyArrayConstr, tyArray: - asm """ - `result` = new Array(`x`.length); - for (var i = 0; i < `x`.length; ++i) { - `result`[i] = genericReset(`x`[i], `ti`.base); - } - """ - else: - discard - proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {. asmNoStackFrame, compilerproc.} = # types are fake - asm """ + {.emit: """ var result = new Array(`len`); for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`); return result; - """ + """.} proc chckIndx(i, a, b: int): int {.compilerproc.} = if i >= a and i <= b: return i @@ -683,7 +658,7 @@ proc isObj(obj, subclass: PNimType): bool {.compilerproc.} = return true proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} = - asm "`x`.push(`c`);" + {.emit: "`x`.push(`c`);".} {.pop.} @@ -710,9 +685,9 @@ proc parseFloatNative(a: openarray[char]): float = let cstr = cstring str - asm """ + {.emit: """ `result` = Number(`cstr`); - """ + """.} proc nimParseBiggestFloat(s: openarray[char], number: var BiggestFloat): int {.compilerproc.} = var sign: bool @@ -779,3 +754,15 @@ if (!Math.trunc) { }; } """.} + +proc cmpClosures(a, b: JSRef): bool {.compilerproc, asmNoStackFrame.} = + # Both `a` and `b` need to be a closure + {.emit: """ + if (`a` !== null && `a`.ClP_0 !== undefined && + `b` !== null && `b`.ClP_0 !== undefined) { + return `a`.ClP_0 == `b`.ClP_0 && `a`.ClE_0 == `b`.ClE_0; + } else { + return `a` == `b`; + } + """ + .} diff --git a/lib/system/memory.nim b/lib/system/memory.nim index ebda60d8d..156773c48 100644 --- a/lib/system/memory.nim +++ b/lib/system/memory.nim @@ -43,6 +43,7 @@ proc nimCmpMem*(a, b: pointer, size: Natural): cint {.compilerproc, nonReloadabl inc i proc nimCStrLen*(a: cstring): int {.compilerproc, nonReloadable, inline.} = + if a.isNil: return 0 when useLibC: cast[int](c_strlen(a)) else: diff --git a/lib/system/mm/go.nim b/lib/system/mm/go.nim index 9ec25fb65..8f3aeb964 100644 --- a/lib/system/mm/go.nim +++ b/lib/system/mm/go.nim @@ -109,7 +109,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} = writebarrierptr(addr(result), newSeq(typ, len)) proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} = - result = newObj(typ, align(GenericSeqSize, typ.base.align) + cap * typ.base.size) + result = newObjNoInit(typ, align(GenericSeqSize, typ.base.align) + cap * typ.base.size) cast[PGenericSeq](result).len = 0 cast[PGenericSeq](result).reserved = cap cast[PGenericSeq](result).elemSize = typ.base.size diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index a2c897b04..cf81f6d86 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -161,6 +161,7 @@ template `--`*(key, val: untyped) = ## ```nim ## --path:somePath # same as switch("path", "somePath") ## --path:"someOtherPath" # same as switch("path", "someOtherPath") + ## --hint:"[Conf]:off" # same as switch("hint", "[Conf]:off") ## ``` switch(strip(astToStr(key)), strip(astToStr(val))) @@ -252,11 +253,12 @@ proc cpDir*(`from`, to: string) {.raises: [OSError].} = proc exec*(command: string) {. raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} = ## Executes an external process. If the external process terminates with - ## a non-zero exit code, an OSError exception is raised. + ## a non-zero exit code, an OSError exception is raised. The command is + ## executed relative to the current source path. ## - ## **Note:** If you need a version of `exec` that returns the exit code - ## and text output of the command, you can use `system.gorgeEx - ## <system.html#gorgeEx,string,string,string>`_. + ## .. note:: If you need a version of `exec` that returns the exit code + ## and text output of the command, you can use `system.gorgeEx + ## <system.html#gorgeEx,string,string,string>`_. log "exec: " & command: if rawExec(command) != 0: raise newException(OSError, "FAILED: " & command) @@ -266,11 +268,17 @@ proc exec*(command: string, input: string, cache = "") {. raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} = ## Executes an external process. If the external process terminates with ## a non-zero exit code, an OSError exception is raised. + ## + ## .. warning:: This version of `exec` is executed relative to the nimscript + ## module path, which affects how the command resolves relative paths. Thus + ## it is generally better to use `gorgeEx` directly when you need more + ## control over the execution environment or when working with commands + ## that deal with relative paths. log "exec: " & command: let (output, exitCode) = gorgeEx(command, input, cache) + echo output if exitCode != 0: raise newException(OSError, "FAILED: " & command) - echo output proc selfExec*(command: string) {. raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} = diff --git a/lib/system/orc.nim b/lib/system/orc.nim index 335d49d0f..c02a24989 100644 --- a/lib/system/orc.nim +++ b/lib/system/orc.nim @@ -81,10 +81,14 @@ proc trace(s: Cell; desc: PNimTypeV2; j: var GcEnv) {.inline.} = include threadids -when logOrc: +when logOrc or orcLeakDetector: proc writeCell(msg: cstring; s: Cell; desc: PNimTypeV2) = - cfprintf(cstderr, "%s %s %ld root index: %ld; RC: %ld; color: %ld; thread: %ld\n", - msg, desc.name, s.refId, s.rootIdx, s.rc shr rcShift, s.color, getThreadId()) + when orcLeakDetector: + cfprintf(cstderr, "%s %s file: %s:%ld; color: %ld; thread: %ld\n", + msg, desc.name, s.filename, s.line, s.color, getThreadId()) + else: + cfprintf(cstderr, "%s %s %ld root index: %ld; RC: %ld; color: %ld; thread: %ld\n", + msg, desc.name, s.refId, s.rootIdx, s.rc shr rcShift, s.color, getThreadId()) proc free(s: Cell; desc: PNimTypeV2) {.inline.} = when traceCollector: @@ -142,7 +146,7 @@ proc unregisterCycle(s: Cell) = let idx = s.rootIdx-1 when false: if idx >= roots.len or idx < 0: - cprintf("[Bug!] %ld\n", idx) + cprintf("[Bug!] %ld %ld\n", idx, roots.len) rawQuit 1 roots.d[idx] = roots.d[roots.len-1] roots.d[idx][0].rootIdx = idx+1 @@ -299,6 +303,14 @@ proc collectColor(s: Cell; desc: PNimTypeV2; col: int; j: var GcEnv) = t.setColor(colBlack) trace(t, desc, j) +const + defaultThreshold = when defined(nimFixedOrc): 10_000 else: 128 + +when defined(nimStressOrc): + const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8 +else: + var rootsThreshold {.threadvar.}: int + proc collectCyclesBacon(j: var GcEnv; lowMark: int) = # pretty direct translation from # https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf @@ -337,20 +349,28 @@ proc collectCyclesBacon(j: var GcEnv; lowMark: int) = s.rootIdx = 0 collectColor(s, roots.d[i][1], colToCollect, j) + # Bug #22927: `free` calls destructors which can append to `roots`. + # We protect against this here by setting `roots.len` to 0 and also + # setting the threshold so high that no cycle collection can be triggered + # until we are out of this critical section: + when not defined(nimStressOrc): + let oldThreshold = rootsThreshold + rootsThreshold = high(int) + roots.len = 0 + for i in 0 ..< j.toFree.len: + when orcLeakDetector: + writeCell("CYCLIC OBJECT FREED", j.toFree.d[i][0], j.toFree.d[i][1]) free(j.toFree.d[i][0], j.toFree.d[i][1]) + when not defined(nimStressOrc): + rootsThreshold = oldThreshold + inc j.freed, j.toFree.len deinit j.toFree - #roots.len = 0 -const - defaultThreshold = when defined(nimFixedOrc): 10_000 else: 128 - -when defined(nimStressOrc): - const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8 -else: - var rootsThreshold {.threadvar.}: int +when defined(nimOrcStats): + var freedCyclicObjects {.threadvar.}: int proc partialCollect(lowMark: int) = when false: @@ -365,6 +385,8 @@ proc partialCollect(lowMark: int) = roots.len - lowMark) roots.len = lowMark deinit j.traceStack + when defined(nimOrcStats): + inc freedCyclicObjects, j.freed proc collectCycles() = ## Collect cycles. @@ -385,7 +407,8 @@ proc collectCycles() = collectCyclesBacon(j, 0) deinit j.traceStack - deinit roots + if roots.len == 0: + deinit roots when not defined(nimStressOrc): # compute the threshold based on the previous history @@ -405,6 +428,16 @@ proc collectCycles() = when logOrc: cfprintf(cstderr, "[collectCycles] end; freed %ld new threshold %ld touched: %ld mem: %ld rcSum: %ld edges: %ld\n", j.freed, rootsThreshold, j.touched, getOccupiedMem(), j.rcSum, j.edges) + when defined(nimOrcStats): + inc freedCyclicObjects, j.freed + +when defined(nimOrcStats): + type + OrcStats* = object ## Statistics of the cycle collector subsystem. + freedCyclicObjects*: int ## Number of freed cyclic objects. + proc GC_orcStats*(): OrcStats = + ## Returns the statistics of the cycle collector subsystem. + result = OrcStats(freedCyclicObjects: freedCyclicObjects) proc registerCycle(s: Cell; desc: PNimTypeV2) = s.rootIdx = roots.len+1 diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 6b6f7e340..13118e40b 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -17,7 +17,7 @@ proc reprFloat(x: float): string {.compilerproc.} = return $x proc reprPointer(x: pointer): string {.compilerproc.} = result = newString(60) - let n = c_sprintf(cast[cstring](addr result[0]), "%p", x) + let n = c_snprintf(cast[cstring](addr result[0]), csize_t(60), "%p", x) setLen(result, n) proc reprStrAux(result: var string, s: cstring; len: int) = diff --git a/lib/system/repr_v2.nim b/lib/system/repr_v2.nim index f81c615e9..d2aef536c 100644 --- a/lib/system/repr_v2.nim +++ b/lib/system/repr_v2.nim @@ -41,7 +41,7 @@ proc repr*(x: char): string {.noSideEffect, raises: [].} = ## ```Nim ## assert repr('c') == "'c'" ## ``` - result.add '\'' + result = "'" # Elides string creations if not needed if x in {'\\', '\0'..'\31', '\127'..'\255'}: result.add '\\' @@ -54,7 +54,7 @@ proc repr*(x: char): string {.noSideEffect, raises: [].} = proc repr*(x: string | cstring): string {.noSideEffect, raises: [].} = ## repr for a string argument. Returns `x` ## converted to a quoted and escaped string. - result.add '\"' + result = "\"" for i in 0..<x.len: if x[i] in {'"', '\\', '\0'..'\31', '\127'..'\255'}: result.add '\\' @@ -99,7 +99,7 @@ proc repr*(p: proc | iterator {.closure.}): string = ## repr of a proc as its address repr(cast[ptr pointer](unsafeAddr p)[]) -template repr*[T: distinct|range](x: T): string = +template repr*[T: distinct|(range and not enum)](x: T): string = when T is range: # add a branch to handle range repr(rangeBase(typeof(x))(x)) elif T is distinct: diff --git a/lib/system/reprjs.nim b/lib/system/reprjs.nim index 30e84ebee..761d66aec 100644 --- a/lib/system/reprjs.nim +++ b/lib/system/reprjs.nim @@ -29,7 +29,7 @@ proc reprBool(x: bool): string {.compilerRtl.} = proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} = var tmp: bool let item = typ.node.sons[e] - {.emit: "`tmp` = `item` !== undefined".} + {.emit: "`tmp` = `item` !== undefined;".} if tmp: result = makeNimstrLit(item.name) else: @@ -136,7 +136,7 @@ proc reprArray(a: pointer, typ: PNimType, add(result, "]") proc isPointedToNil(p: pointer): bool = - {. emit: "if (`p` === null) {`result` = true};\n" .} + {. emit: "if (`p` === null) {`result` = true;}\n" .} proc reprRef(result: var string, p: pointer, typ: PNimType, cl: var ReprClosure) = diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index b71b81762..572e77408 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -8,7 +8,7 @@ # -# import typetraits +# import std/typetraits # strs already imported allocateds for us. @@ -16,8 +16,6 @@ {.push warning[StrictNotNil]: off.} # See https://github.com/nim-lang/Nim/issues/21401 -proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".} - ## Default seq implementation used by Nim's core. type NimSeqPayloadBase = object @@ -50,6 +48,15 @@ proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises else: result = nil +proc newSeqPayloadUninit(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises: [].} = + # Used in `newSeqOfCap()`. + if cap > 0: + var p = cast[ptr NimSeqPayloadBase](alignedAlloc(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize, elemAlign)) + p.cap = cap + result = p + else: + result = nil + template `+!`(p: pointer, s: int): pointer = cast[pointer](cast[int](p) +% s) @@ -70,15 +77,48 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin var p = cast[ptr NimSeqPayloadBase](p) let oldCap = p.cap and not strlitFlag let newCap = max(resize(oldCap), len+addlen) + var q: ptr NimSeqPayloadBase if (p.cap and strlitFlag) == strlitFlag: - var q = cast[ptr NimSeqPayloadBase](alignedAlloc0(headerSize + elemSize * newCap, elemAlign)) + q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign)) + copyMem(q +! headerSize, p +! headerSize, len * elemSize) + else: + let oldSize = headerSize + elemSize * oldCap + let newSize = headerSize + elemSize * newCap + q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign)) + + zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize) + q.cap = newCap + result = q + +proc zeroNewElements(len: int; q: pointer; addlen, elemSize, elemAlign: int) {. + noSideEffect, tags: [], raises: [], compilerRtl.} = + {.noSideEffect.}: + let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign) + zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize) + +proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {. + noSideEffect, tags: [], raises: [], compilerRtl.} = + {.noSideEffect.}: + let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign) + if addlen <= 0: + result = p + elif p == nil: + result = newSeqPayloadUninit(len+addlen, elemSize, elemAlign) + else: + # Note: this means we cannot support things that have internal pointers as + # they get reallocated here. This needs to be documented clearly. + var p = cast[ptr NimSeqPayloadBase](p) + let oldCap = p.cap and not strlitFlag + let newCap = max(resize(oldCap), len+addlen) + if (p.cap and strlitFlag) == strlitFlag: + var q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign)) copyMem(q +! headerSize, p +! headerSize, len * elemSize) q.cap = newCap result = q else: let oldSize = headerSize + elemSize * oldCap let newSize = headerSize + elemSize * newCap - var q = cast[ptr NimSeqPayloadBase](alignedRealloc0(p, oldSize, newSize, elemAlign)) + var q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign)) q.cap = newCap result = q @@ -95,16 +135,17 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} = {.noSideEffect.}: cast[ptr NimSeqV2[T]](addr x).len = newLen -proc grow*[T](x: var seq[T]; newLen: Natural; value: T) = +proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} = let oldLen = x.len #sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'" if newLen <= oldLen: return var xu = cast[ptr NimSeqV2[T]](addr x) if xu.p == nil or (xu.p.cap and not strlitFlag) < newLen: - xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T))) + xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T))) xu.len = newLen for i in oldLen .. newLen-1: - xu.p.data[i] = value + wasMoved(xu.p.data[i]) + `=copy`(xu.p.data[i], value) proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} = ## Generic proc for adding a data item `y` to a container `x`. @@ -117,7 +158,7 @@ proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, n let oldLen = x.len var xu = cast[ptr NimSeqV2[T]](addr x) if xu.p == nil or (xu.p.cap and not strlitFlag) < oldLen+1: - xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T))) + xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, 1, sizeof(T), alignof(T))) xu.len = oldLen+1 # .nodestroy means `xu.p.data[oldLen] = value` is compiled into a # copyMem(). This is fine as know by construction that @@ -125,7 +166,7 @@ proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, n # We also save the `wasMoved + destroy` pair for the sink parameter. xu.p.data[oldLen] = y -proc setLen[T](s: var seq[T], newlen: Natural) = +proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} = {.noSideEffect.}: if newlen < s.len: shrink(s, newlen) @@ -134,7 +175,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) = if newlen <= oldLen: return var xu = cast[ptr NimSeqV2[T]](addr s) if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen: - xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) + xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) xu.len = newlen for i in oldLen..<newlen: xu.p.data[i] = default(T) @@ -143,11 +184,9 @@ proc newSeq[T](s: var seq[T], len: Natural) = shrink(s, 0) setLen(s, len) -proc sameSeqPayload(x: pointer, y: pointer): bool {.compilerproc, inline.} = +proc sameSeqPayload(x: pointer, y: pointer): bool {.compilerRtl, inl.} = result = cast[ptr NimRawSeq](x)[].p == cast[ptr NimRawSeq](y)[].p -template capacityImpl(sek: NimSeqV2): int = - if sek.p != nil: (sek.p.cap and not strlitFlag) else: 0 func capacity*[T](self: seq[T]): int {.inline.} = ## Returns the current capacity of the seq. @@ -157,9 +196,32 @@ func capacity*[T](self: seq[T]): int {.inline.} = lst.add "Nim" assert lst.capacity == 42 - {.cast(noSideEffect).}: - let sek = unsafeAddr self - result = capacityImpl(cast[ptr NimSeqV2[T]](sek)[]) + let sek = cast[ptr NimSeqV2[T]](unsafeAddr self) + result = if sek.p != nil: sek.p.cap and not strlitFlag else: 0 +func setLenUninit*[T](s: var seq[T], newlen: Natural) {.nodestroy.} = + ## Sets the length of seq `s` to `newlen`. `T` may be any sequence type. + ## New slots will not be initialized. + ## + ## If the current length is greater than the new length, + ## `s` will be truncated. + ## ```nim + ## var x = @[10, 20] + ## x.setLenUninit(5) + ## x[4] = 50 + ## assert x[4] == 50 + ## x.setLenUninit(1) + ## assert x == @[10] + ## ``` + {.noSideEffect.}: + if newlen < s.len: + shrink(s, newlen) + else: + let oldLen = s.len + if newlen <= oldLen: return + var xu = cast[ptr NimSeqV2[T]](addr s) + if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen: + xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) + xu.len = newlen {.pop.} # See https://github.com/nim-lang/Nim/issues/21401 diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim index 60c63501c..89046253b 100644 --- a/lib/system/strmantle.nim +++ b/lib/system/strmantle.nim @@ -23,6 +23,14 @@ proc cmpStrings(a, b: string): int {.inline, compilerproc.} = else: result = alen - blen +proc leStrings(a, b: string): bool {.inline, compilerproc.} = + # required by upcoming backends (NIR). + cmpStrings(a, b) <= 0 + +proc ltStrings(a, b: string): bool {.inline, compilerproc.} = + # required by upcoming backends (NIR). + cmpStrings(a, b) < 0 + proc eqStrings(a, b: string): bool {.inline, compilerproc.} = let alen = a.len let blen = b.len diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim index e161172b2..404b4f78d 100644 --- a/lib/system/strs_v2.nim +++ b/lib/system/strs_v2.nim @@ -166,7 +166,7 @@ proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} = s.len = newLen proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} = - if a.p == b.p: return + if a.p == b.p and a.len == b.len: return if isLiteral(b): # we can shallow copy literals: frees(a) @@ -201,9 +201,16 @@ proc prepareMutation*(s: var string) {.inline.} = let s = unsafeAddr s nimPrepareStrMutationV2(cast[ptr NimStringV2](s)[]) +proc nimAddStrV1(s: var NimStringV2; src: NimStringV2) {.compilerRtl, inl.} = + #if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag): + prepareAdd(s, src.len) + appendString s, src + +proc nimDestroyStrV1(s: NimStringV2) {.compilerRtl, inl.} = + frees(s) -template capacityImpl(str: NimStringV2): int = - if str.p != nil: str.p.cap else: 0 +proc nimStrAtLe(s: string; idx: int; ch: char): bool {.compilerRtl, inl.} = + result = idx < s.len and s[idx] <= ch func capacity*(self: string): int {.inline.} = ## Returns the current capacity of the string. @@ -213,6 +220,5 @@ func capacity*(self: string): int {.inline.} = str.add "Nim" assert str.capacity == 42 - {.cast(noSideEffect).}: - let str = unsafeAddr self - result = capacityImpl(cast[ptr NimStringV2](str)[]) + let str = cast[ptr NimStringV2](unsafeAddr self) + result = if str.p != nil: str.p.cap and not strlitFlag else: 0 diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index b8dc7101d..3621c4960 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -47,27 +47,22 @@ else: template allocStrNoInit(size: untyped): untyped = cast[NimString](newObjNoInit(addr(strDesc), size)) -proc rawNewStringNoInit(space: int): NimString {.compilerproc.} = - var s = space - if s < 7: s = 7 +proc rawNewStringNoInit(space: int): NimString = + let s = max(space, 7) result = allocStrNoInit(sizeof(TGenericSeq) + s + 1) result.reserved = s - result.len = 0 when defined(gogc): result.elemSize = 1 proc rawNewString(space: int): NimString {.compilerproc.} = - var s = space - if s < 7: s = 7 - result = allocStr(sizeof(TGenericSeq) + s + 1) - result.reserved = s + result = rawNewStringNoInit(space) result.len = 0 - when defined(gogc): - result.elemSize = 1 + result.data[0] = '\0' proc mnewString(len: int): NimString {.compilerproc.} = - result = rawNewString(len) + result = rawNewStringNoInit(len) result.len = len + zeroMem(addr result.data[0], len + 1) proc copyStrLast(s: NimString, start, last: int): NimString {.compilerproc.} = # This is not used by most recent versions of the compiler anymore, but @@ -75,13 +70,10 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerproc.} = let start = max(start, 0) if s == nil: return nil let len = min(last, s.len-1) - start + 1 - if len > 0: - result = rawNewStringNoInit(len) - result.len = len - copyMem(addr(result.data), addr(s.data[start]), len) - result.data[len] = '\0' - else: - result = rawNewString(len) + result = rawNewStringNoInit(len) + result.len = len + copyMem(addr(result.data), addr(s.data[start]), len) + result.data[len] = '\0' proc copyStr(s: NimString, start: int): NimString {.compilerproc.} = # This is not used by most recent versions of the compiler anymore, but @@ -96,7 +88,8 @@ proc nimToCStringConv(s: NimString): cstring {.compilerproc, nonReloadable, inli proc toNimStr(str: cstring, len: int): NimString {.compilerproc.} = result = rawNewStringNoInit(len) result.len = len - copyMem(addr(result.data), str, len + 1) + copyMem(addr(result.data), str, len) + result.data[len] = '\0' proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} = if str == nil: NimString(nil) @@ -201,7 +194,7 @@ proc addChar(s: NimString, c: char): NimString = proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} = if dest == nil: - result = rawNewStringNoInit(addlen) + result = rawNewString(addlen) elif dest.len + addlen <= dest.space: result = dest else: # slow path: @@ -227,15 +220,18 @@ proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} = proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} = let n = max(newLen, 0) if s == nil: - result = mnewString(newLen) + if n == 0: + return s + else: + result = mnewString(n) elif n <= s.space: result = s else: - let sp = max(resize(s.space), newLen) + let sp = max(resize(s.space), n) result = rawNewStringNoInit(sp) result.len = s.len - copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len+1) - zeroMem(addr result.data[s.len], newLen - s.len) + copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len) + zeroMem(addr result.data[s.len], n - s.len) result.reserved = sp result.len = n result.data[n] = '\0' @@ -308,7 +304,10 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. compilerRtl.} = sysAssert typ.kind == tySequence, "setLengthSeqV2: type is not a seq" if s == nil: - result = cast[PGenericSeq](newSeq(typ, newLen)) + if newLen == 0: + result = s + else: + result = cast[PGenericSeq](newSeq(typ, newLen)) else: let elemSize = typ.base.size let elemAlign = typ.base.align @@ -340,3 +339,25 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. result = s zeroMem(dataPointer(result, elemAlign, elemSize, result.len), (newLen-%result.len) *% elemSize) result.len = newLen + +func capacity*(self: string): int {.inline.} = + ## Returns the current capacity of the string. + # See https://github.com/nim-lang/RFCs/issues/460 + runnableExamples: + var str = newStringOfCap(cap = 42) + str.add "Nim" + assert str.capacity == 42 + + let str = cast[NimString](self) + result = if str != nil: str.space else: 0 + +func capacity*[T](self: seq[T]): int {.inline.} = + ## Returns the current capacity of the seq. + # See https://github.com/nim-lang/RFCs/issues/460 + runnableExamples: + var lst = newSeqOfCap[string](cap = 42) + lst.add "Nim" + assert lst.capacity == 42 + + let sek = cast[PGenericSeq](self) + result = if sek != nil: sek.space else: 0 diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index f8c6ce021..79681376b 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -10,7 +10,7 @@ ## This module implements a small wrapper for some needed Win API procedures, ## so that the Nim compiler does not depend on the huge Windows module. -import dynlib +import std/dynlib when defined(nimHasStyleChecks): {.push styleChecks: off.} diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index b94ddaa21..9921b7ffd 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -28,7 +28,7 @@ # https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html # -from strutils import startsWith +from std/strutils import startsWith when defined(nimPreviewSlimSystem): import std/syncio @@ -51,17 +51,17 @@ when sslVersion != "": const DLLSSLName* = "libssl." & sslVersion & ".dylib" DLLUtilName* = "libcrypto." & sslVersion & ".dylib" - from posix import SocketHandle + from std/posix import SocketHandle elif defined(windows): const DLLSSLName* = "libssl-" & sslVersion & ".dll" DLLUtilName* = "libcrypto-" & sslVersion & ".dll" - from winlean import SocketHandle + from std/winlean import SocketHandle else: const DLLSSLName* = "libssl.so." & sslVersion DLLUtilName* = "libcrypto.so." & sslVersion - from posix import SocketHandle + from std/posix import SocketHandle elif useWinVersion: when defined(openssl10) or defined(nimOldDlls): @@ -82,7 +82,7 @@ elif useWinVersion: DLLSSLName* = "(libssl-1_1|ssleay32|libssl32).dll" DLLUtilName* = "(libcrypto-1_1|libeay32).dll" - from winlean import SocketHandle + from std/winlean import SocketHandle else: # same list of versions but ordered differently? when defined(osx): @@ -102,9 +102,9 @@ else: const DLLSSLName* = "libssl.so" & versions DLLUtilName* = "libcrypto.so" & versions - from posix import SocketHandle + from std/posix import SocketHandle -import dynlib +import std/dynlib {.pragma: lcrypto, cdecl, dynlib: DLLUtilName, importc.} {.pragma: lssl, cdecl, dynlib: DLLSSLName, importc.} @@ -779,7 +779,7 @@ proc md5*(d: ptr uint8; n: csize_t; md: ptr uint8): ptr uint8{.importc: "MD5".} proc md5_Transform*(c: var MD5_CTX; b: ptr uint8){.importc: "MD5_Transform".} {.pop.} -from strutils import toHex, toLowerAscii +from std/strutils import toHex, toLowerAscii proc hexStr(buf: cstring): string = # turn md5s output into a nice hex str |