mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 05:23:20 +00:00
Use more Natural and Positive numbers in proc parameters
- Didn't go through all modules, only the main ones I thought of - Building the compiler and tests still work
This commit is contained in:
@@ -24,7 +24,7 @@ proc `*`*(x: int, order: SortOrder): int {.inline.} =
|
||||
var y = order.ord - 1
|
||||
result = (x xor y) - y
|
||||
|
||||
proc reverse*[T](a: var openArray[T], first, last: int) =
|
||||
proc reverse*[T](a: var openArray[T], first, last: Natural) =
|
||||
## reverses the array ``a[first..last]``.
|
||||
var x = first
|
||||
var y = last
|
||||
@@ -37,7 +37,7 @@ proc reverse*[T](a: var openArray[T]) =
|
||||
## reverses the array `a`.
|
||||
reverse(a, 0, a.high)
|
||||
|
||||
proc reversed*[T](a: openArray[T], first, last: int): seq[T] =
|
||||
proc reversed*[T](a: openArray[T], first, last: Natural): seq[T] =
|
||||
## returns the reverse of the array `a[first..last]`.
|
||||
result = newSeq[T](last - first + 1)
|
||||
var x = first
|
||||
|
||||
@@ -19,7 +19,7 @@ import
|
||||
type
|
||||
BitScalar = int
|
||||
|
||||
const
|
||||
const
|
||||
InitIntSetSize = 8 # must be a power of two!
|
||||
TrunkShift = 9
|
||||
BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and
|
||||
@@ -31,11 +31,11 @@ const
|
||||
|
||||
type
|
||||
PTrunk = ref TTrunk
|
||||
TTrunk {.final.} = object
|
||||
TTrunk {.final.} = object
|
||||
next: PTrunk # all nodes are connected with this pointer
|
||||
key: int # start address at bit 0
|
||||
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
|
||||
|
||||
|
||||
TTrunkSeq = seq[PTrunk]
|
||||
IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set
|
||||
counter, max: int
|
||||
@@ -44,42 +44,42 @@ type
|
||||
|
||||
{.deprecated: [TIntSet: IntSet].}
|
||||
|
||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
proc intSetGet(t: IntSet, key: int): PTrunk =
|
||||
proc intSetGet(t: IntSet, key: int): PTrunk =
|
||||
var h = key and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
result = nil
|
||||
|
||||
proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||
proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||
var h = desc.key and t.max
|
||||
while data[h] != nil:
|
||||
while data[h] != nil:
|
||||
assert(data[h] != desc)
|
||||
h = nextTry(h, t.max)
|
||||
assert(data[h] == nil)
|
||||
data[h] = desc
|
||||
|
||||
proc intSetEnlarge(t: var IntSet) =
|
||||
proc intSetEnlarge(t: var IntSet) =
|
||||
var n: TTrunkSeq
|
||||
var oldMax = t.max
|
||||
t.max = ((t.max + 1) * 2) - 1
|
||||
newSeq(n, t.max + 1)
|
||||
for i in countup(0, oldMax):
|
||||
for i in countup(0, oldMax):
|
||||
if t.data[i] != nil: intSetRawInsert(t, n, t.data[i])
|
||||
swap(t.data, n)
|
||||
|
||||
proc intSetPut(t: var IntSet, key: int): PTrunk =
|
||||
proc intSetPut(t: var IntSet, key: int): PTrunk =
|
||||
var h = key and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
if mustRehash(t.max + 1, t.counter): intSetEnlarge(t)
|
||||
@@ -94,43 +94,43 @@ proc intSetPut(t: var IntSet, key: int): PTrunk =
|
||||
t.data[h] = result
|
||||
|
||||
proc contains*(s: IntSet, key: int): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
## returns true iff `key` is in `s`.
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
else:
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl*(s: var IntSet, key: int) =
|
||||
|
||||
proc incl*(s: var IntSet, key: int) =
|
||||
## includes an element `key` in `s`.
|
||||
var t = intSetPut(s, `shr`(key, TrunkShift))
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||
`shl`(1, u and IntMask)
|
||||
|
||||
proc excl*(s: var IntSet, key: int) =
|
||||
proc excl*(s: var IntSet, key: int) =
|
||||
## excludes `key` from the set `s`.
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
|
||||
not `shl`(1, u and IntMask)
|
||||
|
||||
proc containsOrIncl*(s: var IntSet, key: int): bool =
|
||||
proc containsOrIncl*(s: var IntSet, key: int): bool =
|
||||
## returns true if `s` contains `key`, otherwise `key` is included in `s`
|
||||
## and false is returned.
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
if not result:
|
||||
if not result:
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||
`shl`(1, u and IntMask)
|
||||
else:
|
||||
else:
|
||||
incl(s, key)
|
||||
result = false
|
||||
|
||||
|
||||
proc initIntSet*: IntSet =
|
||||
## creates a new int set that is empty.
|
||||
newSeq(result.data, InitIntSetSize)
|
||||
@@ -140,14 +140,14 @@ proc initIntSet*: IntSet =
|
||||
|
||||
proc assign*(dest: var IntSet, src: IntSet) =
|
||||
## copies `src` to `dest`. `dest` does not need to be initialized by
|
||||
## `initIntSet`.
|
||||
## `initIntSet`.
|
||||
dest.counter = src.counter
|
||||
dest.max = src.max
|
||||
newSeq(dest.data, src.data.len)
|
||||
|
||||
|
||||
var it = src.head
|
||||
while it != nil:
|
||||
|
||||
|
||||
var h = it.key and dest.max
|
||||
while dest.data[h] != nil: h = nextTry(h, dest.max)
|
||||
assert(dest.data[h] == nil)
|
||||
@@ -168,7 +168,7 @@ iterator items*(s: IntSet): int {.inline.} =
|
||||
while r != nil:
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var w = r.bits[i]
|
||||
var w = r.bits[i]
|
||||
# taking a copy of r.bits[i] here is correct, because
|
||||
# modifying operations are not allowed during traversation
|
||||
var j = 0
|
||||
|
||||
@@ -114,7 +114,7 @@ proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc rightSize*(count: int): int {.inline.} =
|
||||
proc rightSize*(count: Natural): int {.inline.} =
|
||||
## Return the value of `initialSize` to support `count` items.
|
||||
##
|
||||
## If more items are expected to be added, simply add that
|
||||
|
||||
@@ -128,7 +128,7 @@ proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc rightSize*(count: int): int {.inline.} =
|
||||
proc rightSize*(count: Natural): int {.inline.} =
|
||||
## Return the value of `initialSize` to support `count` items.
|
||||
##
|
||||
## If more items are expected to be added, simply add that
|
||||
|
||||
@@ -386,7 +386,7 @@ proc split*(s: string, sep: string): seq[string] {.noSideEffect,
|
||||
## `split iterator <#split.i,string,string>`_.
|
||||
accumulateResult(split(s, sep))
|
||||
|
||||
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||
proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
||||
rtl, extern: "nsuToHex".} =
|
||||
## Converts `x` to its hexadecimal representation.
|
||||
##
|
||||
@@ -403,7 +403,7 @@ proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||
# handle negative overflow
|
||||
if n == 0 and x < 0: n = -1
|
||||
|
||||
proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect,
|
||||
proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
|
||||
rtl, extern: "nsuIntToStr".} =
|
||||
## Converts `x` to its decimal representation.
|
||||
##
|
||||
@@ -499,7 +499,7 @@ proc parseEnum*[T: enum](s: string, default: T): T =
|
||||
return e
|
||||
result = default
|
||||
|
||||
proc repeat*(c: char, count: int): string {.noSideEffect,
|
||||
proc repeat*(c: char, count: Natural): string {.noSideEffect,
|
||||
rtl, extern: "nsuRepeatChar".} =
|
||||
## Returns a string of length `count` consisting only of
|
||||
## the character `c`. You can use this proc to left align strings. Example:
|
||||
@@ -514,7 +514,7 @@ proc repeat*(c: char, count: int): string {.noSideEffect,
|
||||
result = newString(count)
|
||||
for i in 0..count-1: result[i] = c
|
||||
|
||||
proc repeat*(s: string, n: int): string {.noSideEffect,
|
||||
proc repeat*(s: string, n: Natural): string {.noSideEffect,
|
||||
rtl, extern: "nsuRepeatStr".} =
|
||||
## Returns String `s` concatenated `n` times. Example:
|
||||
##
|
||||
@@ -523,7 +523,7 @@ proc repeat*(s: string, n: int): string {.noSideEffect,
|
||||
result = newStringOfCap(n * s.len)
|
||||
for i in 1..n: result.add(s)
|
||||
|
||||
template spaces*(n: int): string = repeat(' ',n)
|
||||
template spaces*(n: Natural): string = repeat(' ',n)
|
||||
## Returns a String with `n` space characters. You can use this proc
|
||||
## to left align strings. Example:
|
||||
##
|
||||
@@ -535,15 +535,15 @@ template spaces*(n: int): string = repeat(' ',n)
|
||||
## echo text1 & spaces(max(0, width - text1.len)) & "|"
|
||||
## echo text2 & spaces(max(0, width - text2.len)) & "|"
|
||||
|
||||
proc repeatChar*(count: int, c: char = ' '): string {.deprecated.} = repeat(c, count)
|
||||
proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = repeat(c, count)
|
||||
## deprecated: use repeat() or spaces()
|
||||
|
||||
proc repeatStr*(count: int, s: string): string {.deprecated.} = repeat(s, count)
|
||||
proc repeatStr*(count: Natural, s: string): string {.deprecated.} = repeat(s, count)
|
||||
## deprecated: use repeat(string, count) or string.repeat(count)
|
||||
|
||||
proc align*(s: string, count: int, padding = ' '): string {.
|
||||
proc align*(s: string, count: Natural, padding = ' '): string {.
|
||||
noSideEffect, rtl, extern: "nsuAlignString".} =
|
||||
## Aligns a string `s` with `padding`, so that is of length `count`.
|
||||
## Aligns a string `s` with `padding`, so that it is of length `count`.
|
||||
##
|
||||
## `padding` characters (by default spaces) are added before `s` resulting in
|
||||
## right alignment. If ``s.len >= count``, no spaces are added and `s` is
|
||||
@@ -682,7 +682,7 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect,
|
||||
inc(i)
|
||||
if suffix[i] == '\0': return true
|
||||
|
||||
proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
|
||||
proc continuesWith*(s, substr: string, start: Natural): bool {.noSideEffect,
|
||||
rtl, extern: "nsuContinuesWith".} =
|
||||
## Returns true iff ``s`` continues with ``substr`` at position ``start``.
|
||||
##
|
||||
@@ -693,8 +693,8 @@ proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
|
||||
if s[i+start] != substr[i]: return false
|
||||
inc(i)
|
||||
|
||||
proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
|
||||
inline.} =
|
||||
proc addSep*(dest: var string, sep = ", ", startLen: Natural = 0)
|
||||
{.noSideEffect, inline.} =
|
||||
## Adds a separator to `dest` only if its length is bigger than `startLen`.
|
||||
##
|
||||
## A shorthand for:
|
||||
@@ -784,7 +784,7 @@ proc findAux(s, sub: string, start: int, a: SkipTable): int =
|
||||
inc(j, a[s[j+m]])
|
||||
return -1
|
||||
|
||||
proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
|
||||
proc find*(s, sub: string, start: Natural = 0): int {.noSideEffect,
|
||||
rtl, extern: "nsuFindStr".} =
|
||||
## Searches for `sub` in `s` starting at position `start`.
|
||||
##
|
||||
@@ -793,7 +793,7 @@ proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
|
||||
preprocessSub(sub, a)
|
||||
result = findAux(s, sub, start, a)
|
||||
|
||||
proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect,
|
||||
proc find*(s: string, sub: char, start: Natural = 0): int {.noSideEffect,
|
||||
rtl, extern: "nsuFindChar".} =
|
||||
## Searches for `sub` in `s` starting at position `start`.
|
||||
##
|
||||
@@ -802,7 +802,7 @@ proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect,
|
||||
if sub == s[i]: return i
|
||||
return -1
|
||||
|
||||
proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect,
|
||||
proc find*(s: string, chars: set[char], start: Natural = 0): int {.noSideEffect,
|
||||
rtl, extern: "nsuFindCharSet".} =
|
||||
## Searches for `chars` in `s` starting at position `start`.
|
||||
##
|
||||
@@ -933,7 +933,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
|
||||
var j = findAux(s, sub, i, a)
|
||||
if j < 0: break
|
||||
# word boundary?
|
||||
if (j == 0 or s[j-1] notin wordChars) and
|
||||
if (j == 0 or s[j-1] notin wordChars) and
|
||||
(j+sub.len >= s.len or s[j+sub.len] notin wordChars):
|
||||
add result, substr(s, i, j - 1)
|
||||
add result, by
|
||||
@@ -976,7 +976,7 @@ proc parseOctInt*(s: string): int {.noSideEffect,
|
||||
of '\0': break
|
||||
else: raise newException(ValueError, "invalid integer: " & s)
|
||||
|
||||
proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||
proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
||||
rtl, extern: "nsuToOct".} =
|
||||
## Converts `x` into its octal representation.
|
||||
##
|
||||
@@ -992,7 +992,7 @@ proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||
shift = shift + 3
|
||||
mask = mask shl 3
|
||||
|
||||
proc toBin*(x: BiggestInt, len: int): string {.noSideEffect,
|
||||
proc toBin*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
||||
rtl, extern: "nsuToBin".} =
|
||||
## Converts `x` into its binary representation.
|
||||
##
|
||||
@@ -1221,7 +1221,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
|
||||
## of significant digits to be printed.
|
||||
## `precision`'s default value is the maximum number of meaningful digits
|
||||
## after the decimal point for Nim's ``biggestFloat`` type.
|
||||
##
|
||||
##
|
||||
## If ``precision == 0``, it tries to format it nicely.
|
||||
const floatFormatToChar: array[FloatFormatMode, char] = ['g', 'f', 'e']
|
||||
var
|
||||
@@ -1286,7 +1286,7 @@ proc findNormalized(x: string, inArray: openArray[string]): int =
|
||||
return -1
|
||||
|
||||
proc invalidFormatString() {.noinline.} =
|
||||
raise newException(ValueError, "invalid format string")
|
||||
raise newException(ValueError, "invalid format string")
|
||||
|
||||
proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
|
||||
noSideEffect, rtl, extern: "nsuAddf".} =
|
||||
@@ -1416,7 +1416,7 @@ when isMainModule:
|
||||
|
||||
doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
|
||||
doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc"
|
||||
|
||||
|
||||
type MyEnum = enum enA, enB, enC, enuD, enE
|
||||
doAssert parseEnum[MyEnum]("enu_D") == enuD
|
||||
|
||||
|
||||
1930
lib/pure/unicode.nim
1930
lib/pure/unicode.nim
File diff suppressed because it is too large
Load Diff
@@ -173,12 +173,6 @@ proc new*(T: typedesc): ref T =
|
||||
## reference to it as result value
|
||||
new(result)
|
||||
|
||||
proc unsafeNew*[T](a: var ref T, size: int) {.magic: "New", noSideEffect.}
|
||||
## creates a new object of type ``T`` and returns a safe (traced)
|
||||
## reference to it in ``a``. This is **unsafe** as it allocates an object
|
||||
## of the passed ``size``. This should only be used for optimization
|
||||
## purposes when you know what you're doing!
|
||||
|
||||
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
|
||||
## leaked implementation detail. Do not use.
|
||||
|
||||
@@ -513,7 +507,13 @@ type
|
||||
ESynch: Exception
|
||||
].}
|
||||
|
||||
proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
|
||||
proc unsafeNew*[T](a: var ref T, size: Natural) {.magic: "New", noSideEffect.}
|
||||
## creates a new object of type ``T`` and returns a safe (traced)
|
||||
## reference to it in ``a``. This is **unsafe** as it allocates an object
|
||||
## of the passed ``size``. This should only be used for optimization
|
||||
## purposes when you know what you're doing!
|
||||
|
||||
proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.}
|
||||
## returns the size of ``x`` in bytes. Since this is a low-level proc,
|
||||
## its usage is discouraged - using ``new`` for the most cases suffices
|
||||
## that one never needs to know ``x``'s size. As a special semantic rule,
|
||||
@@ -547,7 +547,7 @@ proc dec*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Dec", noSideEffect.
|
||||
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
|
||||
## short notation for: ``x = pred(x, y)``.
|
||||
|
||||
proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
|
||||
proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.}
|
||||
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
||||
## This is equivalent to ``s = @[]; setlen(s, len)``, but more
|
||||
## efficient since no reallocation is needed.
|
||||
@@ -565,7 +565,7 @@ proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
|
||||
## inputStrings[2] = "would crash"
|
||||
## #inputStrings[3] = "out of bounds"
|
||||
|
||||
proc newSeq*[T](len = 0): seq[T] =
|
||||
proc newSeq*[T](len = 0.Natural): seq[T] =
|
||||
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
||||
##
|
||||
## Note that the sequence will be filled with zeroed entries, which can be a
|
||||
@@ -939,7 +939,7 @@ proc `@` * [IDX, T](a: array[IDX, T]): seq[T] {.
|
||||
## sequences with the array constructor: ``@[1, 2, 3]`` has the type
|
||||
## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
|
||||
|
||||
proc setLen*[T](s: var seq[T], newlen: int) {.
|
||||
proc setLen*[T](s: var seq[T], newlen: Natural) {.
|
||||
magic: "SetLengthSeq", noSideEffect.}
|
||||
## sets the length of `s` to `newlen`.
|
||||
## ``T`` may be any sequence type.
|
||||
@@ -947,14 +947,14 @@ proc setLen*[T](s: var seq[T], newlen: int) {.
|
||||
## ``s`` will be truncated. `s` cannot be nil! To initialize a sequence with
|
||||
## a size, use ``newSeq`` instead.
|
||||
|
||||
proc setLen*(s: var string, newlen: int) {.
|
||||
proc setLen*(s: var string, newlen: Natural) {.
|
||||
magic: "SetLengthStr", noSideEffect.}
|
||||
## sets the length of `s` to `newlen`.
|
||||
## If the current length is greater than the new length,
|
||||
## ``s`` will be truncated. `s` cannot be nil! To initialize a string with
|
||||
## a size, use ``newString`` instead.
|
||||
|
||||
proc newString*(len: int): string {.
|
||||
proc newString*(len: Natural): string {.
|
||||
magic: "NewString", importc: "mnewString", noSideEffect.}
|
||||
## returns a new string of length ``len`` but with uninitialized
|
||||
## content. One needs to fill the string character after character
|
||||
@@ -962,7 +962,7 @@ proc newString*(len: int): string {.
|
||||
## optimization purposes; the same effect can be achieved with the
|
||||
## ``&`` operator or with ``add``.
|
||||
|
||||
proc newStringOfCap*(cap: int): string {.
|
||||
proc newStringOfCap*(cap: Natural): string {.
|
||||
magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.}
|
||||
## returns a new string of length ``0`` but with capacity `cap`.This
|
||||
## procedure exists only for optimization purposes; the same effect can
|
||||
@@ -1152,21 +1152,21 @@ proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
|
||||
## is a reason why the default assignment does a deep copy of sequences
|
||||
## and strings.
|
||||
|
||||
proc del*[T](x: var seq[T], i: int) {.noSideEffect.} =
|
||||
proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
||||
## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
|
||||
## This is an O(1) operation.
|
||||
let xl = x.len
|
||||
shallowCopy(x[i], x[xl-1])
|
||||
setLen(x, xl-1)
|
||||
|
||||
proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} =
|
||||
proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
||||
## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
|
||||
## This is an O(n) operation.
|
||||
let xl = x.len
|
||||
for j in i..xl-2: shallowCopy(x[j], x[j+1])
|
||||
setLen(x, xl-1)
|
||||
|
||||
proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} =
|
||||
proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
|
||||
## inserts `item` into `x` at position `i`.
|
||||
let xl = x.len
|
||||
setLen(x, xl+1)
|
||||
@@ -1312,19 +1312,19 @@ proc substr*(s: string, first, last: int): string {.
|
||||
## or `limit`:idx: a string's length.
|
||||
|
||||
when not defined(nimrodVM):
|
||||
proc zeroMem*(p: pointer, size: int) {.importc, noDecl, benign.}
|
||||
proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.}
|
||||
## overwrites the contents of the memory at ``p`` with the value 0.
|
||||
## Exactly ``size`` bytes will be overwritten. Like any procedure
|
||||
## dealing with raw memory this is *unsafe*.
|
||||
|
||||
proc copyMem*(dest, source: pointer, size: int) {.
|
||||
proc copyMem*(dest, source: pointer, size: Natural) {.
|
||||
importc: "memcpy", header: "<string.h>", benign.}
|
||||
## copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
|
||||
## regions may not overlap. Like any procedure dealing with raw
|
||||
## memory this is *unsafe*.
|
||||
|
||||
proc moveMem*(dest, source: pointer, size: int) {.
|
||||
proc moveMem*(dest, source: pointer, size: Natural) {.
|
||||
importc: "memmove", header: "<string.h>", benign.}
|
||||
## copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
|
||||
@@ -1332,7 +1332,7 @@ when not defined(nimrodVM):
|
||||
## and is thus somewhat more safe than ``copyMem``. Like any procedure
|
||||
## dealing with raw memory this is still *unsafe*, though.
|
||||
|
||||
proc equalMem*(a, b: pointer, size: int): bool {.
|
||||
proc equalMem*(a, b: pointer, size: Natural): bool {.
|
||||
importc: "equalMem", noDecl, noSideEffect.}
|
||||
## compares the memory blocks ``a`` and ``b``. ``size`` bytes will
|
||||
## be compared. If the blocks are equal, true is returned, false
|
||||
@@ -1340,7 +1340,7 @@ when not defined(nimrodVM):
|
||||
## *unsafe*.
|
||||
|
||||
when hostOS != "standalone":
|
||||
proc alloc*(size: int): pointer {.noconv, rtl, tags: [], benign.}
|
||||
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
|
||||
## allocates a new memory block with at least ``size`` bytes. The
|
||||
## block has to be freed with ``realloc(block, 0)`` or
|
||||
## ``dealloc(block)``. The block is not initialized, so reading
|
||||
@@ -1355,7 +1355,7 @@ when not defined(nimrodVM):
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `createSharedU` to allocate from a shared heap.
|
||||
cast[ptr T](alloc(T.sizeof * size))
|
||||
proc alloc0*(size: int): pointer {.noconv, rtl, tags: [], benign.}
|
||||
proc alloc0*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
|
||||
## allocates a new memory block with at least ``size`` bytes. The
|
||||
## block has to be freed with ``realloc(block, 0)`` or
|
||||
## ``dealloc(block)``. The block is initialized with all bytes
|
||||
@@ -1370,8 +1370,8 @@ when not defined(nimrodVM):
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `createShared` to allocate from a shared heap.
|
||||
cast[ptr T](alloc0(T.sizeof * size))
|
||||
proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [],
|
||||
benign.}
|
||||
proc realloc*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
|
||||
benign.}
|
||||
## grows or shrinks a given memory block. If p is **nil** then a new
|
||||
## memory block is returned. In either way the block has at least
|
||||
## ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
|
||||
@@ -1398,7 +1398,7 @@ when not defined(nimrodVM):
|
||||
## Use `deallocShared` to deallocate from a shared heap.
|
||||
proc free*[T](p: ptr T) {.inline, benign.} =
|
||||
dealloc(p)
|
||||
proc allocShared*(size: int): pointer {.noconv, rtl, benign.}
|
||||
proc allocShared*(size: Natural): pointer {.noconv, rtl, benign.}
|
||||
## allocates a new memory block on the shared heap with at
|
||||
## least ``size`` bytes. The block has to be freed with
|
||||
## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
|
||||
@@ -1412,7 +1412,7 @@ when not defined(nimrodVM):
|
||||
## is not initialized, so reading from it before writing to it is
|
||||
## undefined behaviour!
|
||||
cast[ptr T](allocShared(T.sizeof * size))
|
||||
proc allocShared0*(size: int): pointer {.noconv, rtl, benign.}
|
||||
proc allocShared0*(size: Natural): pointer {.noconv, rtl, benign.}
|
||||
## allocates a new memory block on the shared heap with at
|
||||
## least ``size`` bytes. The block has to be freed with
|
||||
## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
|
||||
@@ -1425,8 +1425,8 @@ when not defined(nimrodVM):
|
||||
## The block is initialized with all bytes
|
||||
## containing zero, so it is somewhat safer than ``createSharedU``.
|
||||
cast[ptr T](allocShared0(T.sizeof * size))
|
||||
proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl,
|
||||
benign.}
|
||||
proc reallocShared*(p: pointer, newSize: Natural): pointer {.noconv, rtl,
|
||||
benign.}
|
||||
## grows or shrinks a given memory block on the heap. If p is **nil**
|
||||
## then a new memory block is returned. In either way the block has at
|
||||
## least ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
|
||||
@@ -2489,37 +2489,37 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||
proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.}
|
||||
## retrieves the file size (in bytes) of `f`.
|
||||
|
||||
proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: int): int {.
|
||||
proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {.
|
||||
tags: [ReadIOEffect], benign.}
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc readChars*(f: File, a: var openArray[char], start, len: int): int {.
|
||||
proc readChars*(f: File, a: var openArray[char], start, len: Natural): int {.
|
||||
tags: [ReadIOEffect], benign.}
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc readBuffer*(f: File, buffer: pointer, len: int): int {.
|
||||
proc readBuffer*(f: File, buffer: pointer, len: Natural): int {.
|
||||
tags: [ReadIOEffect], benign.}
|
||||
## reads `len` bytes into the buffer pointed to by `buffer`. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: int): int {.
|
||||
proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: Natural): int {.
|
||||
tags: [WriteIOEffect], benign.}
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeChars*(f: File, a: openArray[char], start, len: int): int {.
|
||||
proc writeChars*(f: File, a: openArray[char], start, len: Natural): int {.
|
||||
tags: [WriteIOEffect], benign.}
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeBuffer*(f: File, buffer: pointer, len: int): int {.
|
||||
proc writeBuffer*(f: File, buffer: pointer, len: Natural): int {.
|
||||
tags: [WriteIOEffect], benign.}
|
||||
## writes the bytes of buffer pointed to by the parameter `buffer` to the
|
||||
## file `f`. Returns the number of actual written bytes, which may be less
|
||||
@@ -2541,7 +2541,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||
when not defined(nimfix):
|
||||
{.deprecated: [fileHandle: getFileHandle].}
|
||||
|
||||
proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] =
|
||||
proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
|
||||
## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
|
||||
## of length ``len``.
|
||||
newSeq(result, len)
|
||||
@@ -2811,14 +2811,14 @@ elif defined(JS):
|
||||
proc getTotalMem(): int = return -1
|
||||
|
||||
proc dealloc(p: pointer) = discard
|
||||
proc alloc(size: int): pointer = discard
|
||||
proc alloc0(size: int): pointer = discard
|
||||
proc realloc(p: pointer, newsize: int): pointer = discard
|
||||
proc alloc(size: Natural): pointer = discard
|
||||
proc alloc0(size: Natural): pointer = discard
|
||||
proc realloc(p: pointer, newsize: Natural): pointer = discard
|
||||
|
||||
proc allocShared(size: int): pointer = discard
|
||||
proc allocShared0(size: int): pointer = discard
|
||||
proc allocShared(size: Natural): pointer = discard
|
||||
proc allocShared0(size: Natural): pointer = discard
|
||||
proc deallocShared(p: pointer) = discard
|
||||
proc reallocShared(p: pointer, newsize: int): pointer = discard
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer = discard
|
||||
|
||||
when defined(JS):
|
||||
include "system/jssys"
|
||||
@@ -3164,7 +3164,7 @@ when false:
|
||||
payload()
|
||||
|
||||
when hostOS != "standalone":
|
||||
proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} =
|
||||
proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
|
||||
## inserts `item` into `x` at position `i`.
|
||||
var xl = x.len
|
||||
setLen(x, xl+item.len)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
|
||||
# Low level allocator for Nim. Has been designed to support the GC.
|
||||
# TODO:
|
||||
# TODO:
|
||||
# - eliminate "used" field
|
||||
# - make searching for block O(1)
|
||||
{.push profiler:off.}
|
||||
@@ -21,37 +21,37 @@
|
||||
# used with a size of 0:
|
||||
const weirdUnmap = not (defined(amd64) or defined(i386)) or defined(windows)
|
||||
|
||||
when defined(posix):
|
||||
when defined(posix):
|
||||
const
|
||||
PROT_READ = 1 # page can be read
|
||||
PROT_WRITE = 2 # page can be written
|
||||
MAP_PRIVATE = 2'i32 # Changes are private
|
||||
|
||||
PROT_READ = 1 # page can be read
|
||||
PROT_WRITE = 2 # page can be written
|
||||
MAP_PRIVATE = 2'i32 # Changes are private
|
||||
|
||||
when defined(macosx) or defined(bsd):
|
||||
const MAP_ANONYMOUS = 0x1000
|
||||
elif defined(solaris):
|
||||
elif defined(solaris):
|
||||
const MAP_ANONYMOUS = 0x100
|
||||
else:
|
||||
var
|
||||
MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
|
||||
|
||||
|
||||
proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
|
||||
off: int): pointer {.header: "<sys/mman.h>".}
|
||||
|
||||
proc munmap(adr: pointer, len: int) {.header: "<sys/mman.h>".}
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = mmap(nil, size, PROT_READ or PROT_WRITE,
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = mmap(nil, size, PROT_READ or PROT_WRITE,
|
||||
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
|
||||
if result == nil or result == cast[pointer](-1):
|
||||
raiseOutOfMem()
|
||||
|
||||
|
||||
proc osDeallocPages(p: pointer, size: int) {.inline} =
|
||||
when reallyOsDealloc: munmap(p, size)
|
||||
|
||||
elif defined(windows):
|
||||
|
||||
elif defined(windows):
|
||||
const
|
||||
MEM_RESERVE = 0x2000
|
||||
MEM_RESERVE = 0x2000
|
||||
MEM_COMMIT = 0x1000
|
||||
MEM_TOP_DOWN = 0x100000
|
||||
PAGE_READWRITE = 0x04
|
||||
@@ -62,12 +62,12 @@ elif defined(windows):
|
||||
proc virtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
|
||||
flProtect: int32): pointer {.
|
||||
header: "<windows.h>", stdcall, importc: "VirtualAlloc".}
|
||||
|
||||
proc virtualFree(lpAddress: pointer, dwSize: int,
|
||||
|
||||
proc virtualFree(lpAddress: pointer, dwSize: int,
|
||||
dwFreeType: int32) {.header: "<windows.h>", stdcall,
|
||||
importc: "VirtualFree".}
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = virtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT,
|
||||
PAGE_READWRITE)
|
||||
if result == nil: raiseOutOfMem()
|
||||
@@ -82,7 +82,7 @@ elif defined(windows):
|
||||
when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
|
||||
#VirtualFree(p, size, MEM_DECOMMIT)
|
||||
|
||||
else:
|
||||
else:
|
||||
{.error: "Port memory manager to your platform".}
|
||||
|
||||
# --------------------- end of non-portable code -----------------------------
|
||||
@@ -97,17 +97,17 @@ const
|
||||
InitialMemoryRequest = ChunkOsReturn div 2 # < ChunkOsReturn!
|
||||
SmallChunkSize = PageSize
|
||||
|
||||
type
|
||||
type
|
||||
PTrunk = ptr TTrunk
|
||||
TTrunk {.final.} = object
|
||||
TTrunk {.final.} = object
|
||||
next: PTrunk # all nodes are connected with this pointer
|
||||
key: int # start address at bit 0
|
||||
bits: array[0..IntsPerTrunk-1, int] # a bit vector
|
||||
|
||||
|
||||
TTrunkBuckets = array[0..255, PTrunk]
|
||||
TIntSet {.final.} = object
|
||||
TIntSet {.final.} = object
|
||||
data: TTrunkBuckets
|
||||
|
||||
|
||||
type
|
||||
TAlignType = BiggestFloat
|
||||
TFreeCell {.final, pure.} = object
|
||||
@@ -123,14 +123,14 @@ type
|
||||
prevSize: int # size of previous chunk; for coalescing
|
||||
size: int # if < PageSize it is a small chunk
|
||||
used: bool # later will be optimized into prevSize...
|
||||
|
||||
|
||||
TSmallChunk = object of TBaseChunk
|
||||
next, prev: PSmallChunk # chunks of the same size
|
||||
freeList: ptr TFreeCell
|
||||
free: int # how many bytes remain
|
||||
free: int # how many bytes remain
|
||||
acc: int # accumulator for small object allocation
|
||||
data: TAlignType # start of usable memory
|
||||
|
||||
|
||||
TBigChunk = object of TBaseChunk # not necessarily > PageSize!
|
||||
next, prev: PBigChunk # chunks of the same (or bigger) size
|
||||
align: int
|
||||
@@ -139,7 +139,7 @@ type
|
||||
template smallChunkOverhead(): expr = sizeof(TSmallChunk)-sizeof(TAlignType)
|
||||
template bigChunkOverhead(): expr = sizeof(TBigChunk)-sizeof(TAlignType)
|
||||
|
||||
proc roundup(x, v: int): int {.inline.} =
|
||||
proc roundup(x, v: int): int {.inline.} =
|
||||
result = (x + (v-1)) and not (v-1)
|
||||
sysAssert(result >= x, "roundup: result < x")
|
||||
#return ((-x) and (v-1)) +% x
|
||||
@@ -153,7 +153,7 @@ sysAssert(roundup(65, 8) == 72, "roundup broken 2")
|
||||
# endings of big chunks. This is needed by the merging operation. The only
|
||||
# remaining operation is best-fit for big chunks. Since there is a size-limit
|
||||
# for big chunks (because greater than the limit means they are returned back
|
||||
# to the OS), a fixed size array can be used.
|
||||
# to the OS), a fixed size array can be used.
|
||||
|
||||
type
|
||||
PLLChunk = ptr TLLChunk
|
||||
@@ -163,21 +163,21 @@ type
|
||||
next: PLLChunk # next low-level chunk; only needed for dealloc
|
||||
|
||||
PAvlNode = ptr TAvlNode
|
||||
TAvlNode {.pure, final.} = object
|
||||
link: array[0..1, PAvlNode] # Left (0) and right (1) links
|
||||
TAvlNode {.pure, final.} = object
|
||||
link: array[0..1, PAvlNode] # Left (0) and right (1) links
|
||||
key, upperBound: int
|
||||
level: int
|
||||
|
||||
|
||||
TMemRegion {.final, pure.} = object
|
||||
minLargeObj, maxLargeObj: int
|
||||
freeSmallChunks: array[0..SmallChunkSize div MemAlign-1, PSmallChunk]
|
||||
llmem: PLLChunk
|
||||
currMem, maxMem, freeMem: int # memory sizes (allocated from OS)
|
||||
lastSize: int # needed for the case that OS gives us pages linearly
|
||||
lastSize: int # needed for the case that OS gives us pages linearly
|
||||
freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access
|
||||
chunkStarts: TIntSet
|
||||
root, deleted, last, freeAvlNodes: PAvlNode
|
||||
|
||||
|
||||
# shared:
|
||||
var
|
||||
bottomData: TAvlNode
|
||||
@@ -191,7 +191,7 @@ proc initAllocator() =
|
||||
bottom.link[1] = bottom
|
||||
{.pop.}
|
||||
|
||||
proc incCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
|
||||
proc incCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
|
||||
inc(a.currMem, bytes)
|
||||
|
||||
proc decCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
|
||||
@@ -199,11 +199,11 @@ proc decCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
|
||||
dec(a.currMem, bytes)
|
||||
|
||||
proc getMaxMem(a: var TMemRegion): int =
|
||||
# Since we update maxPagesCount only when freeing pages,
|
||||
# Since we update maxPagesCount only when freeing pages,
|
||||
# maxPagesCount may not be up to date. Thus we use the
|
||||
# maximum of these both values here:
|
||||
result = max(a.currMem, a.maxMem)
|
||||
|
||||
|
||||
proc llAlloc(a: var TMemRegion, size: int): pointer =
|
||||
# *low-level* alloc for the memory managers data structures. Deallocation
|
||||
# is done at he end of the allocator's life time.
|
||||
@@ -251,15 +251,15 @@ proc llDeallocAll(a: var TMemRegion) =
|
||||
var next = it.next
|
||||
osDeallocPages(it, PageSize)
|
||||
it = next
|
||||
|
||||
proc intSetGet(t: TIntSet, key: int): PTrunk =
|
||||
|
||||
proc intSetGet(t: TIntSet, key: int): PTrunk =
|
||||
var it = t.data[key and high(t.data)]
|
||||
while it != nil:
|
||||
while it != nil:
|
||||
if it.key == key: return it
|
||||
it = it.next
|
||||
result = nil
|
||||
|
||||
proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
|
||||
proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
|
||||
result = intSetGet(t, key)
|
||||
if result == nil:
|
||||
result = cast[PTrunk](llAlloc(a, sizeof(result[])))
|
||||
@@ -267,20 +267,20 @@ proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
|
||||
t.data[key and high(t.data)] = result
|
||||
result.key = key
|
||||
|
||||
proc contains(s: TIntSet, key: int): bool =
|
||||
proc contains(s: TIntSet, key: int): bool =
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
else:
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl(a: var TMemRegion, s: var TIntSet, key: int) =
|
||||
|
||||
proc incl(a: var TMemRegion, s: var TIntSet, key: int) =
|
||||
var t = intSetPut(a, s, key shr TrunkShift)
|
||||
var u = key and TrunkMask
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
|
||||
|
||||
proc excl(s: var TIntSet, key: int) =
|
||||
proc excl(s: var TIntSet, key: int) =
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
@@ -304,11 +304,11 @@ iterator elements(t: TIntSet): int {.inline.} =
|
||||
w = w shr 1
|
||||
inc(i)
|
||||
r = r.next
|
||||
|
||||
proc isSmallChunk(c: PChunk): bool {.inline.} =
|
||||
|
||||
proc isSmallChunk(c: PChunk): bool {.inline.} =
|
||||
return c.size <= SmallChunkSize-smallChunkOverhead()
|
||||
|
||||
proc chunkUnused(c: PChunk): bool {.inline.} =
|
||||
|
||||
proc chunkUnused(c: PChunk): bool {.inline.} =
|
||||
result = not c.used
|
||||
|
||||
iterator allObjects(m: TMemRegion): pointer {.inline.} =
|
||||
@@ -319,7 +319,7 @@ iterator allObjects(m: TMemRegion): pointer {.inline.} =
|
||||
if not chunkUnused(c):
|
||||
if isSmallChunk(c):
|
||||
var c = cast[PSmallChunk](c)
|
||||
|
||||
|
||||
let size = c.size
|
||||
var a = cast[ByteAddress](addr(c.data))
|
||||
let limit = a + c.acc
|
||||
@@ -334,17 +334,17 @@ proc isCell(p: pointer): bool {.inline.} =
|
||||
result = cast[ptr TFreeCell](p).zeroField >% 1
|
||||
|
||||
# ------------- chunk management ----------------------------------------------
|
||||
proc pageIndex(c: PChunk): int {.inline.} =
|
||||
proc pageIndex(c: PChunk): int {.inline.} =
|
||||
result = cast[ByteAddress](c) shr PageShift
|
||||
|
||||
proc pageIndex(p: pointer): int {.inline.} =
|
||||
proc pageIndex(p: pointer): int {.inline.} =
|
||||
result = cast[ByteAddress](p) shr PageShift
|
||||
|
||||
proc pageAddr(p: pointer): PChunk {.inline.} =
|
||||
proc pageAddr(p: pointer): PChunk {.inline.} =
|
||||
result = cast[PChunk](cast[ByteAddress](p) and not PageMask)
|
||||
#sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
|
||||
|
||||
proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
|
||||
proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
|
||||
incCurrMem(a, size)
|
||||
inc(a.freeMem, size)
|
||||
result = cast[PBigChunk](osAllocPages(size))
|
||||
@@ -373,7 +373,7 @@ proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
|
||||
result.prevSize = 0 # unknown
|
||||
a.lastSize = size # for next request
|
||||
|
||||
proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
|
||||
proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
|
||||
# update next.prevSize:
|
||||
var c = cast[PChunk](p)
|
||||
var nxt = cast[ByteAddress](p) +% c.size
|
||||
@@ -387,36 +387,36 @@ proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
|
||||
dec(a.freeMem, size)
|
||||
#c_fprintf(c_stdout, "[Alloc] back to OS: %ld\n", size)
|
||||
|
||||
proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} =
|
||||
proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} =
|
||||
result = contains(a.chunkStarts, pageIndex(p))
|
||||
|
||||
proc contains[T](list, x: T): bool =
|
||||
proc contains[T](list, x: T): bool =
|
||||
var it = list
|
||||
while it != nil:
|
||||
if it == x: return true
|
||||
it = it.next
|
||||
|
||||
|
||||
proc writeFreeList(a: TMemRegion) =
|
||||
var it = a.freeChunksList
|
||||
c_fprintf(c_stdout, "freeChunksList: %p\n", it)
|
||||
while it != nil:
|
||||
c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n",
|
||||
while it != nil:
|
||||
c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n",
|
||||
it, it.next, it.prev)
|
||||
it = it.next
|
||||
|
||||
proc listAdd[T](head: var T, c: T) {.inline.} =
|
||||
proc listAdd[T](head: var T, c: T) {.inline.} =
|
||||
sysAssert(c notin head, "listAdd 1")
|
||||
sysAssert c.prev == nil, "listAdd 2"
|
||||
sysAssert c.next == nil, "listAdd 3"
|
||||
c.next = head
|
||||
if head != nil:
|
||||
if head != nil:
|
||||
sysAssert head.prev == nil, "listAdd 4"
|
||||
head.prev = c
|
||||
head = c
|
||||
|
||||
proc listRemove[T](head: var T, c: T) {.inline.} =
|
||||
sysAssert(c in head, "listRemove")
|
||||
if c == head:
|
||||
if c == head:
|
||||
head = c.next
|
||||
sysAssert c.prev == nil, "listRemove 2"
|
||||
if head != nil: head.prev = nil
|
||||
@@ -426,15 +426,15 @@ proc listRemove[T](head: var T, c: T) {.inline.} =
|
||||
if c.next != nil: c.next.prev = c.prev
|
||||
c.next = nil
|
||||
c.prev = nil
|
||||
|
||||
proc updatePrevSize(a: var TMemRegion, c: PBigChunk,
|
||||
prevSize: int) {.inline.} =
|
||||
|
||||
proc updatePrevSize(a: var TMemRegion, c: PBigChunk,
|
||||
prevSize: int) {.inline.} =
|
||||
var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
|
||||
sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "updatePrevSize")
|
||||
if isAccessible(a, ri):
|
||||
ri.prevSize = prevSize
|
||||
|
||||
proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
||||
|
||||
proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
||||
var c = c
|
||||
sysAssert(c.size >= PageSize, "freeBigChunk")
|
||||
inc(a.freeMem, c.size)
|
||||
@@ -448,7 +448,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
||||
inc(c.size, ri.size)
|
||||
excl(a.chunkStarts, pageIndex(ri))
|
||||
when coalescLeft:
|
||||
if c.prevSize != 0:
|
||||
if c.prevSize != 0:
|
||||
var le = cast[PChunk](cast[ByteAddress](c) -% c.prevSize)
|
||||
sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
|
||||
if isAccessible(a, le) and chunkUnused(le):
|
||||
@@ -467,7 +467,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
||||
else:
|
||||
freeOsChunks(a, c, c.size)
|
||||
|
||||
proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
|
||||
proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
|
||||
var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
|
||||
sysAssert(rest notin a.freeChunksList, "splitChunk")
|
||||
rest.size = c.size - size
|
||||
@@ -480,7 +480,7 @@ proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
|
||||
incl(a, a.chunkStarts, pageIndex(rest))
|
||||
listAdd(a.freeChunksList, rest)
|
||||
|
||||
proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
# use first fit for now:
|
||||
sysAssert((size and PageMask) == 0, "getBigChunk 1")
|
||||
sysAssert(size > 0, "getBigChunk 2")
|
||||
@@ -488,7 +488,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
block search:
|
||||
while result != nil:
|
||||
sysAssert chunkUnused(result), "getBigChunk 3"
|
||||
if result.size == size:
|
||||
if result.size == size:
|
||||
listRemove(a.freeChunksList, result)
|
||||
break search
|
||||
elif result.size > size:
|
||||
@@ -497,7 +497,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
break search
|
||||
result = result.next
|
||||
sysAssert result != a.freeChunksList, "getBigChunk 4"
|
||||
if size < InitialMemoryRequest:
|
||||
if size < InitialMemoryRequest:
|
||||
result = requestOsChunks(a, InitialMemoryRequest)
|
||||
splitChunk(a, result, size)
|
||||
else:
|
||||
@@ -507,7 +507,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
incl(a, a.chunkStarts, pageIndex(result))
|
||||
dec(a.freeMem, size)
|
||||
|
||||
proc getSmallChunk(a: var TMemRegion): PSmallChunk =
|
||||
proc getSmallChunk(a: var TMemRegion): PSmallChunk =
|
||||
var res = getBigChunk(a, PageSize)
|
||||
sysAssert res.prev == nil, "getSmallChunk 1"
|
||||
sysAssert res.next == nil, "getSmallChunk 2"
|
||||
@@ -521,15 +521,15 @@ proc allocInv(a: TMemRegion): bool =
|
||||
for s in low(a.freeSmallChunks)..high(a.freeSmallChunks):
|
||||
var c = a.freeSmallChunks[s]
|
||||
while c != nil:
|
||||
if c.next == c:
|
||||
if c.next == c:
|
||||
echo "[SYSASSERT] c.next == c"
|
||||
return false
|
||||
if c.size != s * MemAlign:
|
||||
if c.size != s * MemAlign:
|
||||
echo "[SYSASSERT] c.size != s * MemAlign"
|
||||
return false
|
||||
var it = c.freeList
|
||||
while it != nil:
|
||||
if it.zeroField != 0:
|
||||
if it.zeroField != 0:
|
||||
echo "[SYSASSERT] it.zeroField != 0"
|
||||
c_printf("%ld %p\n", it.zeroField, it)
|
||||
return false
|
||||
@@ -544,11 +544,11 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
||||
var size = roundup(requestedSize, MemAlign)
|
||||
sysAssert(size >= requestedSize, "insufficient allocated size!")
|
||||
#c_fprintf(c_stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
|
||||
if size <= SmallChunkSize-smallChunkOverhead():
|
||||
if size <= SmallChunkSize-smallChunkOverhead():
|
||||
# allocate a small block: for small chunks, we use only its next pointer
|
||||
var s = size div MemAlign
|
||||
var c = a.freeSmallChunks[s]
|
||||
if c == nil:
|
||||
if c == nil:
|
||||
c = getSmallChunk(a)
|
||||
c.freeList = nil
|
||||
sysAssert c.size == PageSize, "rawAlloc 3"
|
||||
@@ -567,7 +567,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
||||
# c_fprintf(c_stdout, "csize: %lld; size %lld\n", c.size, size)
|
||||
sysAssert c.size == size, "rawAlloc 6"
|
||||
if c.freeList == nil:
|
||||
sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize,
|
||||
sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize,
|
||||
"rawAlloc 7")
|
||||
result = cast[pointer](cast[ByteAddress](addr(c.data)) +% c.acc)
|
||||
inc(c.acc, size)
|
||||
@@ -621,9 +621,9 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
|
||||
f.zeroField = 0
|
||||
f.next = c.freeList
|
||||
c.freeList = f
|
||||
when overwriteFree:
|
||||
when overwriteFree:
|
||||
# set to 0xff to check for usage after free bugs:
|
||||
c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32,
|
||||
c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32,
|
||||
s -% sizeof(TFreeCell))
|
||||
# check if it is not in the freeSmallChunks[s] list:
|
||||
if c.free < s:
|
||||
@@ -649,13 +649,13 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
|
||||
sysAssert(allocInv(a), "rawDealloc: end")
|
||||
when logAlloc: cprintf("rawDealloc: %p\n", p)
|
||||
|
||||
proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
|
||||
proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
|
||||
if isAccessible(a, p):
|
||||
var c = pageAddr(p)
|
||||
if not chunkUnused(c):
|
||||
if isSmallChunk(c):
|
||||
var c = cast[PSmallChunk](c)
|
||||
var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
|
||||
var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
|
||||
smallChunkOverhead()
|
||||
result = (c.acc >% offset) and (offset %% c.size == 0) and
|
||||
(cast[ptr TFreeCell](p).zeroField >% 1)
|
||||
@@ -673,12 +673,12 @@ proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
|
||||
if not chunkUnused(c):
|
||||
if isSmallChunk(c):
|
||||
var c = cast[PSmallChunk](c)
|
||||
var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
|
||||
var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
|
||||
smallChunkOverhead()
|
||||
if c.acc >% offset:
|
||||
sysAssert(cast[ByteAddress](addr(c.data)) +% offset ==
|
||||
cast[ByteAddress](p), "offset is not what you think it is")
|
||||
var d = cast[ptr TFreeCell](cast[ByteAddress](addr(c.data)) +%
|
||||
var d = cast[ptr TFreeCell](cast[ByteAddress](addr(c.data)) +%
|
||||
offset -% (offset %% c.size))
|
||||
if d.zeroField >% 1:
|
||||
result = d
|
||||
@@ -711,13 +711,13 @@ proc ptrSize(p: pointer): int =
|
||||
if not isSmallChunk(c):
|
||||
dec result, bigChunkOverhead()
|
||||
|
||||
proc alloc(allocator: var TMemRegion, size: int): pointer =
|
||||
proc alloc(allocator: var TMemRegion, size: Natural): pointer =
|
||||
result = rawAlloc(allocator, size+sizeof(TFreeCell))
|
||||
cast[ptr TFreeCell](result).zeroField = 1 # mark it as used
|
||||
sysAssert(not isAllocatedPtr(allocator, result), "alloc")
|
||||
result = cast[pointer](cast[ByteAddress](result) +% sizeof(TFreeCell))
|
||||
|
||||
proc alloc0(allocator: var TMemRegion, size: int): pointer =
|
||||
proc alloc0(allocator: var TMemRegion, size: Natural): pointer =
|
||||
result = alloc(allocator, size)
|
||||
zeroMem(result, size)
|
||||
|
||||
@@ -730,7 +730,7 @@ proc dealloc(allocator: var TMemRegion, p: pointer) =
|
||||
rawDealloc(allocator, x)
|
||||
sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3")
|
||||
|
||||
proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
|
||||
proc realloc(allocator: var TMemRegion, p: pointer, newsize: Natural): pointer =
|
||||
if newsize > 0:
|
||||
result = alloc0(allocator, newsize)
|
||||
if p != nil:
|
||||
@@ -758,7 +758,7 @@ proc deallocOsPages(a: var TMemRegion) =
|
||||
|
||||
proc getFreeMem(a: TMemRegion): int {.inline.} = result = a.freeMem
|
||||
proc getTotalMem(a: TMemRegion): int {.inline.} = result = a.currMem
|
||||
proc getOccupiedMem(a: TMemRegion): int {.inline.} =
|
||||
proc getOccupiedMem(a: TMemRegion): int {.inline.} =
|
||||
result = a.currMem - a.freeMem
|
||||
|
||||
# ---------------------- thread memory region -------------------------------
|
||||
@@ -774,16 +774,16 @@ template instantiateForRegion(allocator: expr) =
|
||||
|
||||
proc deallocOsPages = deallocOsPages(allocator)
|
||||
|
||||
proc alloc(size: int): pointer =
|
||||
proc alloc(size: Natural): pointer =
|
||||
result = alloc(allocator, size)
|
||||
|
||||
proc alloc0(size: int): pointer =
|
||||
proc alloc0(size: Natural): pointer =
|
||||
result = alloc0(allocator, size)
|
||||
|
||||
proc dealloc(p: pointer) =
|
||||
dealloc(allocator, p)
|
||||
|
||||
proc realloc(p: pointer, newsize: int): pointer =
|
||||
proc realloc(p: pointer, newsize: Natural): pointer =
|
||||
result = realloc(allocator, p, newSize)
|
||||
|
||||
when false:
|
||||
@@ -794,7 +794,7 @@ template instantiateForRegion(allocator: expr) =
|
||||
inc(result, it.size)
|
||||
it = it.next
|
||||
|
||||
proc getFreeMem(): int =
|
||||
proc getFreeMem(): int =
|
||||
result = allocator.freeMem
|
||||
#sysAssert(result == countFreeMem())
|
||||
|
||||
@@ -807,7 +807,7 @@ template instantiateForRegion(allocator: expr) =
|
||||
var heapLock: TSysLock
|
||||
initSysLock(heapLock)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
proc allocShared(size: Natural): pointer =
|
||||
when hasThreadSupport:
|
||||
acquireSys(heapLock)
|
||||
result = alloc(sharedHeap, size)
|
||||
@@ -815,20 +815,20 @@ template instantiateForRegion(allocator: expr) =
|
||||
else:
|
||||
result = alloc(size)
|
||||
|
||||
proc allocShared0(size: int): pointer =
|
||||
proc allocShared0(size: Natural): pointer =
|
||||
result = allocShared(size)
|
||||
zeroMem(result, size)
|
||||
|
||||
proc deallocShared(p: pointer) =
|
||||
when hasThreadSupport:
|
||||
when hasThreadSupport:
|
||||
acquireSys(heapLock)
|
||||
dealloc(sharedHeap, p)
|
||||
releaseSys(heapLock)
|
||||
else:
|
||||
dealloc(p)
|
||||
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
when hasThreadSupport:
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer =
|
||||
when hasThreadSupport:
|
||||
acquireSys(heapLock)
|
||||
result = realloc(sharedHeap, p, newsize)
|
||||
releaseSys(heapLock)
|
||||
|
||||
@@ -109,24 +109,24 @@ when defined(boehmgc):
|
||||
|
||||
when not defined(useNimRtl):
|
||||
|
||||
proc alloc(size: int): pointer =
|
||||
proc alloc(size: Natural): pointer =
|
||||
result = boehmAlloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc alloc0(size: int): pointer =
|
||||
proc alloc0(size: Natural): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc realloc(p: pointer, newsize: int): pointer =
|
||||
proc realloc(p: pointer, newsize: Natural): pointer =
|
||||
result = boehmRealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc dealloc(p: pointer) = boehmDealloc(p)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
proc allocShared(size: Natural): pointer =
|
||||
result = boehmAlloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc allocShared0(size: int): pointer =
|
||||
proc allocShared0(size: Natural): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer =
|
||||
result = boehmRealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc deallocShared(p: pointer) = boehmDealloc(p)
|
||||
@@ -196,24 +196,24 @@ when defined(boehmgc):
|
||||
elif defined(nogc) and defined(useMalloc):
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc alloc(size: int): pointer =
|
||||
proc alloc(size: Natural): pointer =
|
||||
result = cmalloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc alloc0(size: int): pointer =
|
||||
proc alloc0(size: Natural): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc realloc(p: pointer, newsize: int): pointer =
|
||||
proc realloc(p: pointer, newsize: Natural): pointer =
|
||||
result = crealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc dealloc(p: pointer) = cfree(p)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
proc allocShared(size: Natural): pointer =
|
||||
result = cmalloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc allocShared0(size: int): pointer =
|
||||
proc allocShared0(size: Natural): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer =
|
||||
result = crealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc deallocShared(p: pointer) = cfree(p)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# of the standard library!
|
||||
|
||||
|
||||
proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>",
|
||||
proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>",
|
||||
tags: [WriteIOEffect].}
|
||||
proc fgets(c: cstring, n: int, f: File): cstring {.
|
||||
importc: "fgets", header: "<stdio.h>", tags: [ReadIOEffect].}
|
||||
@@ -26,7 +26,7 @@ proc ungetc(c: cint, f: File) {.importc: "ungetc", header: "<stdio.h>",
|
||||
tags: [].}
|
||||
proc putc(c: char, stream: File) {.importc: "putc", header: "<stdio.h>",
|
||||
tags: [WriteIOEffect].}
|
||||
proc fprintf(f: File, frmt: cstring) {.importc: "fprintf",
|
||||
proc fprintf(f: File, frmt: cstring) {.importc: "fprintf",
|
||||
header: "<stdio.h>", varargs, tags: [WriteIOEffect].}
|
||||
proc strlen(c: cstring): int {.
|
||||
importc: "strlen", header: "<string.h>", tags: [].}
|
||||
@@ -88,18 +88,18 @@ proc readLine(f: File): TaintedString =
|
||||
result = TaintedString(newStringOfCap(80))
|
||||
if not readLine(f, result): raiseEIO("EOF reached")
|
||||
|
||||
proc write(f: File, i: int) =
|
||||
proc write(f: File, i: int) =
|
||||
when sizeof(int) == 8:
|
||||
fprintf(f, "%lld", i)
|
||||
else:
|
||||
fprintf(f, "%ld", i)
|
||||
|
||||
proc write(f: File, i: BiggestInt) =
|
||||
proc write(f: File, i: BiggestInt) =
|
||||
when sizeof(BiggestInt) == 8:
|
||||
fprintf(f, "%lld", i)
|
||||
else:
|
||||
fprintf(f, "%ld", i)
|
||||
|
||||
|
||||
proc write(f: File, b: bool) =
|
||||
if b: write(f, "true")
|
||||
else: write(f, "false")
|
||||
@@ -110,7 +110,7 @@ proc write(f: File, c: char) = putc(c, f)
|
||||
proc write(f: File, a: varargs[string, `$`]) =
|
||||
for x in items(a): write(f, x)
|
||||
|
||||
proc readAllBuffer(file: File): string =
|
||||
proc readAllBuffer(file: File): string =
|
||||
# This proc is for File we want to read but don't know how many
|
||||
# bytes we need to read before the buffer is empty.
|
||||
result = ""
|
||||
@@ -123,8 +123,8 @@ proc readAllBuffer(file: File): string =
|
||||
buffer.setLen(bytesRead)
|
||||
result.add(buffer)
|
||||
break
|
||||
|
||||
proc rawFileSize(file: File): int =
|
||||
|
||||
proc rawFileSize(file: File): int =
|
||||
# this does not raise an error opposed to `getFileSize`
|
||||
var oldPos = ftell(file)
|
||||
discard fseek(file, 0, 2) # seek the end of the file
|
||||
@@ -141,8 +141,8 @@ proc readAllFile(file: File, len: int): string =
|
||||
proc readAllFile(file: File): string =
|
||||
var len = rawFileSize(file)
|
||||
result = readAllFile(file, len)
|
||||
|
||||
proc readAll(file: File): TaintedString =
|
||||
|
||||
proc readAll(file: File): TaintedString =
|
||||
# Separate handling needed because we need to buffer when we
|
||||
# don't know the overall length of the File.
|
||||
let len = if file != stdin: rawFileSize(file) else: -1
|
||||
@@ -150,7 +150,7 @@ proc readAll(file: File): TaintedString =
|
||||
result = readAllFile(file, len).TaintedString
|
||||
else:
|
||||
result = readAllBuffer(file).TaintedString
|
||||
|
||||
|
||||
proc readFile(filename: string): TaintedString =
|
||||
var f = open(filename)
|
||||
try:
|
||||
@@ -229,7 +229,7 @@ proc open(f: var File, filename: string,
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
|
||||
proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
|
||||
proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
|
||||
var p: pointer = freopen(filename, FormatOpen[mode], f)
|
||||
result = p != nil
|
||||
|
||||
@@ -243,23 +243,23 @@ proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool =
|
||||
proc fwrite(buf: pointer, size, n: int, f: File): int {.
|
||||
importc: "fwrite", noDecl.}
|
||||
|
||||
proc readBuffer(f: File, buffer: pointer, len: int): int =
|
||||
proc readBuffer(f: File, buffer: pointer, len: Natural): int =
|
||||
result = fread(buffer, 1, len, f)
|
||||
|
||||
proc readBytes(f: File, a: var openArray[int8|uint8], start, len: int): int =
|
||||
proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
proc readChars(f: File, a: var openArray[char], start, len: int): int =
|
||||
proc readChars(f: File, a: var openArray[char], start, len: Natural): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
{.push stackTrace:off, profiler:off.}
|
||||
proc writeBytes(f: File, a: openArray[int8|uint8], start, len: int): int =
|
||||
proc writeBytes(f: File, a: openArray[int8|uint8], start, len: Natural): int =
|
||||
var x = cast[ptr array[0..1000_000_000, int8]](a)
|
||||
result = writeBuffer(f, addr(x[start]), len)
|
||||
proc writeChars(f: File, a: openArray[char], start, len: int): int =
|
||||
proc writeChars(f: File, a: openArray[char], start, len: Natural): int =
|
||||
var x = cast[ptr array[0..1000_000_000, int8]](a)
|
||||
result = writeBuffer(f, addr(x[start]), len)
|
||||
proc writeBuffer(f: File, buffer: pointer, len: int): int =
|
||||
proc writeBuffer(f: File, buffer: pointer, len: Natural): int =
|
||||
result = fwrite(buffer, 1, len, f)
|
||||
|
||||
proc write(f: File, s: string) =
|
||||
|
||||
Reference in New Issue
Block a user