-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Feat: stdlib: adds system.string.setLenUninit
#24836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devel
Are you sure you want to change the base?
Conversation
|
|
ping, would be nice to see this PR merged |
I think I was stuck on not being sure if it's done and both string versions actually work, since some of CI errors at the time were unrelated. Those string/seq impls is a mess of conditionals and I don't trust locally-run tests. |
- Required for a followup to nim-lang#15951 - Accompanies nim-lang#19727 but for strings + `sysstr` housekeeping: - Removed redundant `len` and `reserved` sets already performed by prior `rawNewStringNoInit`calls.
6ca4735
to
059a3f9
Compare
Without `hasAlloc` `system/sysstr` is not included in system so `setLengthStrUninit` is not in the scope.
Lines 2316 to 2326 in 2e45f61
Adding a |
lib/system/sysstr.nim
Outdated
return s | ||
else: | ||
result = mnewString(n) | ||
return if n == 0: s else: mnewString(n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not what the original code did and a distraction. Bring back the old version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, if we don't return early from this case (and checking for nil is cleraly an "early return" kind of branch),
we're setting len
and the nul-byte for the result again at lines 229-230
Lines 229 to 230 in 2e45f61
result.len = n | |
result.data[n] = '\0' |
mnewString
sets the len
and the null-byte on each call for the returned string (though, the null-byte implicitly, by zeroMem
call):
Lines 62 to 65 in 2e45f61
proc mnewString(len: int): NimString {.compilerproc.} = | |
result = rawNewStringNoInit(len) | |
result.len = len | |
zeroMem(addr result.data[0], len + 1) |
Original code for the s == nil and n != 0
went like this:
# start of the mnewString call
result = rawNewStringNoInit(n)
result.len = n
zeroMem(addr result.data[0], n + 1) # n (or len in the proc) + 1 sets the null-byte
# after-coditional tail of setLengthStr
result.len = n
result.data[n] = '\0'
So this is redundant.
How about I separate the nil
case into separate if statement to signify it's an early-return case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, it could look like this:
proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
let n = max(newLen, 0)
if s == nil: # early return check
if n == 0:
return s
else:
return mnewString(n) # sets everything required
if n <= s.space:
result = s
else:
let sp = max(resize(s.space), n)
result = rawNewStringNoInit(sp) # len and null-byte not set
copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len)
zeroMem(addr result.data[s.len], n - s.len)
result.len = n
result.data[n] = '\0'
This is more explicit and in terms of logic completely equal to the original version, barring reduntant field touches, but I'm not totally sure what's "distracting" to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my previous version is more succinct, but indeed it might be better to change the elif
at ln.227 to a separate if
to separate the early-return statement.
Apart from my code review remarks, seems fine. |
So I went with expanding that early return conditional at line 232 a bit and added some internal docs. If it's still not up your alley I can change the code to whatever. If it's ok as is, do you want me to squash it? BTW, you can't currently build docs with
|
Adds
system.setLenUninit
for thestring
type. Allows setting length without initializing new memory on growth.add(a: var string, b: openArray[char])
#15951setLenUninit
for seqsv2 #22767 (refnewSeqUninitialized
over-constrained,setLenUninitialized
missing #19727) but for stringssysstr
housekeeping:len
andreserved
sets already performed by priorrawNewStringNoInit
calls.