remove compiler/strutils2.nim (#20748)
* use std strutils toLowerAscii char * avoid additional call and assign * remove compiler/strutils2.nim * canonical
This commit is contained in:
parent
a3d32a4176
commit
10e7f18d01
3 changed files with 7 additions and 103 deletions
|
|
@ -10,7 +10,7 @@
|
||||||
import
|
import
|
||||||
std/[strutils, os, tables, terminal, macros, times],
|
std/[strutils, os, tables, terminal, macros, times],
|
||||||
std/private/miscdollars,
|
std/private/miscdollars,
|
||||||
options, lineinfos, pathutils, strutils2
|
options, lineinfos, pathutils
|
||||||
|
|
||||||
import ropes except `%`
|
import ropes except `%`
|
||||||
|
|
||||||
|
|
@ -24,6 +24,10 @@ template instLoc*(): InstantiationInfo = instantiationInfo(-2, fullPaths = true)
|
||||||
template toStdOrrKind(stdOrr): untyped =
|
template toStdOrrKind(stdOrr): untyped =
|
||||||
if stdOrr == stdout: stdOrrStdout else: stdOrrStderr
|
if stdOrr == stdout: stdOrrStdout else: stdOrrStderr
|
||||||
|
|
||||||
|
proc toLowerAscii(a: var string) {.inline.} =
|
||||||
|
for c in mitems(a):
|
||||||
|
if isUpperAscii(c): c = char(uint8(c) xor 0b0010_0000'u8)
|
||||||
|
|
||||||
proc flushDot*(conf: ConfigRef) =
|
proc flushDot*(conf: ConfigRef) =
|
||||||
## safe to call multiple times
|
## safe to call multiple times
|
||||||
# xxx one edge case not yet handled is when `printf` is called at CT with `compiletimeFFI`.
|
# xxx one edge case not yet handled is when `printf` is called at CT with `compiletimeFFI`.
|
||||||
|
|
@ -78,7 +82,7 @@ when defined(nimpretty):
|
||||||
proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
|
proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
|
||||||
substr(conf.m.fileInfos[fid.int].fullContent, a, b)
|
substr(conf.m.fileInfos[fid.int].fullContent, a, b)
|
||||||
|
|
||||||
proc canonicalCase(path: var string) =
|
proc canonicalCase(path: var string) {.inline.} =
|
||||||
## the idea is to only use this for checking whether a path is already in
|
## the idea is to only use this for checking whether a path is already in
|
||||||
## the table but otherwise keep the original case
|
## the table but otherwise keep the original case
|
||||||
when FileSystemCaseSensitive: discard
|
when FileSystemCaseSensitive: discard
|
||||||
|
|
@ -101,16 +105,13 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
|
||||||
|
|
||||||
try:
|
try:
|
||||||
canon = canonicalizePath(conf, filename)
|
canon = canonicalizePath(conf, filename)
|
||||||
when not defined(nimSeqsV2):
|
|
||||||
shallow(canon.string)
|
|
||||||
except OSError:
|
except OSError:
|
||||||
canon = filename
|
canon = filename
|
||||||
# The compiler uses "filenames" such as `command line` or `stdin`
|
# The compiler uses "filenames" such as `command line` or `stdin`
|
||||||
# This flag indicates that we are working with such a path here
|
# This flag indicates that we are working with such a path here
|
||||||
pseudoPath = true
|
pseudoPath = true
|
||||||
|
|
||||||
var canon2: string
|
var canon2 = canon.string
|
||||||
forceCopy(canon2, canon.string) # because `canon` may be shallow
|
|
||||||
canon2.canonicalCase
|
canon2.canonicalCase
|
||||||
|
|
||||||
if conf.m.filenameToIndexTbl.hasKey(canon2):
|
if conf.m.filenameToIndexTbl.hasKey(canon2):
|
||||||
|
|
@ -119,7 +120,6 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
|
||||||
else:
|
else:
|
||||||
isKnownFile = false
|
isKnownFile = false
|
||||||
result = conf.m.fileInfos.len.FileIndex
|
result = conf.m.fileInfos.len.FileIndex
|
||||||
#echo "ID ", result.int, " ", canon2
|
|
||||||
conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: RelativeFile filename
|
conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: RelativeFile filename
|
||||||
else: relativeTo(canon, conf.projectPath)))
|
else: relativeTo(canon, conf.projectPath)))
|
||||||
conf.m.filenameToIndexTbl[canon2] = result
|
conf.m.filenameToIndexTbl[canon2] = result
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
##[
|
|
||||||
internal API for now, subject to modifications and moving around
|
|
||||||
|
|
||||||
string API's focusing on performance, that can be used as building blocks
|
|
||||||
for other routines.
|
|
||||||
|
|
||||||
Un-necessary allocations are avoided and appropriate algorithms are used at the
|
|
||||||
expense of code clarity when justified.
|
|
||||||
]##
|
|
||||||
|
|
||||||
proc dataPointer*[T](a: T): pointer =
|
|
||||||
## same as C++ `data` that works with std::string, std::vector etc.
|
|
||||||
## Note: safe to use when a.len == 0 but whether the result is nil or not
|
|
||||||
## is implementation defined for performance reasons.
|
|
||||||
# this could be improved with ocmpiler support to avoid the `if`, e.g. in C++
|
|
||||||
# `&a[0]` is well defined even if a.size() == 0
|
|
||||||
when T is string | seq:
|
|
||||||
if a.len == 0: nil else: cast[pointer](a[0].unsafeAddr)
|
|
||||||
elif T is array:
|
|
||||||
when a.len > 0: a.unsafeAddr
|
|
||||||
else: nil
|
|
||||||
elif T is cstring:
|
|
||||||
cast[pointer](a)
|
|
||||||
else: static: doAssert false, $T
|
|
||||||
|
|
||||||
proc setLen*(result: var string, n: int, isInit: bool) =
|
|
||||||
## when isInit = false, elements are left uninitialized, analog to `{.noinit.}`
|
|
||||||
## else, there are 0-initialized.
|
|
||||||
# xxx placeholder until system.setLen supports this
|
|
||||||
# to distinguish between algorithms that need 0-initialization vs not; note
|
|
||||||
# that `setLen` for string is inconsistent with `setLen` for seq.
|
|
||||||
# likwise with `newString` vs `newSeq`. This should be fixed in `system`.
|
|
||||||
let n0 = result.len
|
|
||||||
result.setLen(n)
|
|
||||||
if isInit and n > n0:
|
|
||||||
zeroMem(result[n0].addr, n - n0)
|
|
||||||
|
|
||||||
proc forceCopy*(result: var string, a: string) =
|
|
||||||
## also forces a copy if `a` is shallow
|
|
||||||
# the naitve `result = a` would not work if `a` is shallow
|
|
||||||
let n = a.len
|
|
||||||
result.setLen n, isInit = false
|
|
||||||
copyMem(result.dataPointer, a.dataPointer, n)
|
|
||||||
|
|
||||||
proc isUpperAscii(c: char): bool {.inline.} =
|
|
||||||
# avoids import strutils.isUpperAscii
|
|
||||||
c in {'A'..'Z'}
|
|
||||||
|
|
||||||
proc toLowerAscii*(a: var string) =
|
|
||||||
## optimized and inplace overload of strutils.toLowerAscii
|
|
||||||
# refs https://github.com/timotheecour/Nim/pull/54
|
|
||||||
# this is 10X faster than a naive implementation using a an optimization trick
|
|
||||||
# that can be adapted in similar contexts. Predictable writes avoid write
|
|
||||||
# hazards and lead to better machine code, compared to random writes arising
|
|
||||||
# from: `if c.isUpperAscii: c = ...`
|
|
||||||
for c in mitems(a):
|
|
||||||
c = chr(c.ord + (if c.isUpperAscii: (ord('a') - ord('A')) else: 0))
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
discard """
|
|
||||||
matrix: "--gc:refc; --gc:orc"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import "$lib/.." / compiler/strutils2
|
|
||||||
import std/assertions
|
|
||||||
|
|
||||||
block: # setLen
|
|
||||||
var a = "abc"
|
|
||||||
a.setLen 0
|
|
||||||
a.setLen 3, isInit = false
|
|
||||||
when defined(gcRefc): # bug #19763
|
|
||||||
doAssert a[1] == 'b'
|
|
||||||
a.setLen 0
|
|
||||||
a.setLen 3, isInit = true
|
|
||||||
doAssert a[1] == '\0'
|
|
||||||
|
|
||||||
block: # forceCopy
|
|
||||||
var a: string
|
|
||||||
a = "foo"
|
|
||||||
when defined(gcRefc):
|
|
||||||
shallow(a)
|
|
||||||
var b: string
|
|
||||||
b = a
|
|
||||||
doAssert b[0].addr == a[0].addr
|
|
||||||
var c: string
|
|
||||||
c.forceCopy a
|
|
||||||
doAssert c == a
|
|
||||||
doAssert c[0].addr != a[0].addr
|
|
||||||
|
|
||||||
block: # toLowerAscii
|
|
||||||
var a = "fooBAr"
|
|
||||||
a.toLowerAscii
|
|
||||||
doAssert a == "foobar"
|
|
||||||
|
|
||||||
block: # dataPointer
|
|
||||||
var a: string
|
|
||||||
discard a.dataPointer
|
|
||||||
# doAssert a.dataPointer == nil # not guaranteed
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue