Merge branch 'devel' of github.com:Araq/Nim into patch2
This commit is contained in:
commit
f852988d11
87 changed files with 4950 additions and 4334 deletions
|
|
@ -36,25 +36,25 @@ const
|
|||
type
|
||||
RegexFlag* = enum ## options for regular expressions
|
||||
reIgnoreCase = 0, ## do caseless matching
|
||||
reMultiLine = 1, ## ``^`` and ``$`` match newlines within data
|
||||
reMultiLine = 1, ## ``^`` and ``$`` match newlines within data
|
||||
reDotAll = 2, ## ``.`` matches anything including NL
|
||||
reExtended = 3, ## ignore whitespace and ``#`` comments
|
||||
reStudy = 4 ## study the expression (may be omitted if the
|
||||
## expression will be used only once)
|
||||
|
||||
RegexDesc = object
|
||||
|
||||
RegexDesc = object
|
||||
h: PPcre
|
||||
e: ptr TExtra
|
||||
|
||||
|
||||
Regex* = ref RegexDesc ## a compiled regular expression
|
||||
|
||||
|
||||
RegexError* = object of ValueError
|
||||
## is raised if the pattern is no valid regular expression.
|
||||
|
||||
{.deprecated: [TRegexFlag: RegexFlag, TRegexDesc: RegexDesc, TRegex: Regex,
|
||||
EInvalidRegEx: RegexError].}
|
||||
|
||||
proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} =
|
||||
proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} =
|
||||
var e: ref RegexError
|
||||
new(e)
|
||||
e.msg = msg
|
||||
|
|
@ -68,10 +68,10 @@ proc rawCompile(pattern: string, flags: cint): PPcre =
|
|||
if result == nil:
|
||||
raiseInvalidRegex($msg & "\n" & pattern & "\n" & spaces(offset) & "^\n")
|
||||
|
||||
proc finalizeRegEx(x: Regex) =
|
||||
proc finalizeRegEx(x: Regex) =
|
||||
# XXX This is a hack, but PCRE does not export its "free" function properly.
|
||||
# Sigh. The hack relies on PCRE's implementation (see ``pcre_get.c``).
|
||||
# Fortunately the implementation is unlikely to change.
|
||||
# Fortunately the implementation is unlikely to change.
|
||||
pcre.free_substring(cast[cstring](x.h))
|
||||
if not isNil(x.e):
|
||||
pcre.free_substring(cast[cstring](x.e))
|
||||
|
|
@ -101,10 +101,10 @@ proc matchOrFind(s: string, pattern: Regex, matches: var openArray[string],
|
|||
if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1)
|
||||
else: matches[i-1] = nil
|
||||
return rawMatches[1] - rawMatches[0]
|
||||
|
||||
|
||||
proc findBounds*(s: string, pattern: Regex, matches: var openArray[string],
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position and end position of `pattern` in `s`
|
||||
## returns the starting position and end position of `pattern` in `s`
|
||||
## and the captured
|
||||
## substrings in the array `matches`. If it does not match, nothing
|
||||
## is written into `matches` and ``(-1,0)`` is returned.
|
||||
|
|
@ -120,12 +120,12 @@ proc findBounds*(s: string, pattern: Regex, matches: var openArray[string],
|
|||
if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1)
|
||||
else: matches[i-1] = nil
|
||||
return (rawMatches[0].int, rawMatches[1].int - 1)
|
||||
|
||||
proc findBounds*(s: string, pattern: Regex,
|
||||
|
||||
proc findBounds*(s: string, pattern: Regex,
|
||||
matches: var openArray[tuple[first, last: int]],
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position and end position of ``pattern`` in ``s``
|
||||
## and the captured substrings in the array `matches`.
|
||||
## returns the starting position and end position of ``pattern`` in ``s``
|
||||
## and the captured substrings in the array `matches`.
|
||||
## If it does not match, nothing is written into `matches` and
|
||||
## ``(-1,0)`` is returned.
|
||||
var
|
||||
|
|
@ -141,7 +141,7 @@ proc findBounds*(s: string, pattern: Regex,
|
|||
else: matches[i-1] = (-1,0)
|
||||
return (rawMatches[0].int, rawMatches[1].int - 1)
|
||||
|
||||
proc findBounds*(s: string, pattern: Regex,
|
||||
proc findBounds*(s: string, pattern: Regex,
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position of `pattern` in `s`. If it does not
|
||||
## match, ``(-1,0)`` is returned.
|
||||
|
|
@ -152,7 +152,7 @@ proc findBounds*(s: string, pattern: Regex,
|
|||
cast[ptr cint](rawMatches), 3)
|
||||
if res < 0'i32: return (int(res), 0)
|
||||
return (int(rawMatches[0]), int(rawMatches[1]-1))
|
||||
|
||||
|
||||
proc matchOrFind(s: string, pattern: Regex, start, flags: cint): cint =
|
||||
var
|
||||
rtarray = initRtArray[cint](3)
|
||||
|
|
@ -172,7 +172,7 @@ proc matchLen*(s: string, pattern: Regex, matches: var openArray[string],
|
|||
proc matchLen*(s: string, pattern: Regex, start = 0): int =
|
||||
## the same as ``match``, but it returns the length of the match,
|
||||
## if there is no match, -1 is returned. Note that a match length
|
||||
## of zero can happen.
|
||||
## of zero can happen.
|
||||
return matchOrFind(s, pattern, start.cint, pcre.ANCHORED)
|
||||
|
||||
proc match*(s: string, pattern: Regex, start = 0): bool =
|
||||
|
|
@ -216,7 +216,7 @@ proc find*(s: string, pattern: Regex, start = 0): int =
|
|||
if res < 0'i32: return res
|
||||
return rawMatches[0]
|
||||
|
||||
iterator findAll*(s: string, pattern: Regex, start = 0): string =
|
||||
iterator findAll*(s: string, pattern: Regex, start = 0): string =
|
||||
## Yields all matching *substrings* of `s` that match `pattern`.
|
||||
##
|
||||
## Note that since this is an iterator you should not modify the string you
|
||||
|
|
@ -231,10 +231,11 @@ iterator findAll*(s: string, pattern: Regex, start = 0): string =
|
|||
if res < 0'i32: break
|
||||
let a = rawMatches[0]
|
||||
let b = rawMatches[1]
|
||||
if a == b and a == i: break
|
||||
yield substr(s, int(a), int(b)-1)
|
||||
i = b
|
||||
|
||||
proc findAll*(s: string, pattern: Regex, start = 0): seq[string] =
|
||||
proc findAll*(s: string, pattern: Regex, start = 0): seq[string] =
|
||||
## returns all matching *substrings* of `s` that match `pattern`.
|
||||
## If it does not match, @[] is returned.
|
||||
accumulateResult(findAll(s, pattern, start))
|
||||
|
|
@ -242,13 +243,13 @@ proc findAll*(s: string, pattern: Regex, start = 0): seq[string] =
|
|||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template `=~` *(s: string, pattern: Regex): expr =
|
||||
## This calls ``match`` with an implicit declared ``matches`` array that
|
||||
## can be used in the scope of the ``=~`` call:
|
||||
##
|
||||
template `=~` *(s: string, pattern: Regex): expr =
|
||||
## This calls ``match`` with an implicit declared ``matches`` array that
|
||||
## can be used in the scope of the ``=~`` call:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## if line =~ re"\s*(\w+)\s*\=\s*(\w+)":
|
||||
## if line =~ re"\s*(\w+)\s*\=\s*(\w+)":
|
||||
## # matches a key=value pair:
|
||||
## echo("Key: ", matches[0])
|
||||
## echo("Value: ", matches[1])
|
||||
|
|
@ -260,9 +261,9 @@ template `=~` *(s: string, pattern: Regex): expr =
|
|||
## else:
|
||||
## echo("syntax error")
|
||||
##
|
||||
bind MaxSubPatterns
|
||||
bind MaxSubpatterns
|
||||
when not declaredInScope(matches):
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
var matches {.inject.}: array[MaxSubpatterns, string]
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
|
@ -286,7 +287,7 @@ proc endsWith*(s: string, suffix: Regex): bool =
|
|||
if matchLen(s, suffix, i) == s.len - i: return true
|
||||
|
||||
proc replace*(s: string, sub: Regex, by = ""): string =
|
||||
## Replaces `sub` in `s` by the string `by`. Captures cannot be
|
||||
## Replaces `sub` in `s` by the string `by`. Captures cannot be
|
||||
## accessed in `by`. Examples:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
|
|
@ -306,7 +307,7 @@ proc replace*(s: string, sub: Regex, by = ""): string =
|
|||
add(result, by)
|
||||
prev = match.last + 1
|
||||
add(result, substr(s, prev))
|
||||
|
||||
|
||||
proc replacef*(s: string, sub: Regex, by: string): string =
|
||||
## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
|
||||
## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
|
||||
|
|
@ -320,7 +321,7 @@ proc replacef*(s: string, sub: Regex, by: string): string =
|
|||
##
|
||||
## "var1<-keykey; val2<-key2key2"
|
||||
result = ""
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
var caps: array[MaxSubpatterns, string]
|
||||
var prev = 0
|
||||
while true:
|
||||
var match = findBounds(s, sub, caps, prev)
|
||||
|
|
@ -338,7 +339,7 @@ proc parallelReplace*(s: string, subs: openArray[
|
|||
## applied in parallel.
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
var caps: array[MaxSubpatterns, string]
|
||||
while i < s.len:
|
||||
block searchSubs:
|
||||
for j in 0..high(subs):
|
||||
|
|
@ -359,7 +360,7 @@ proc transformFile*(infile, outfile: string,
|
|||
## error occurs. This is supposed to be used for quick scripting.
|
||||
var x = readFile(infile).string
|
||||
writeFile(outfile, x.parallelReplace(subs))
|
||||
|
||||
|
||||
iterator split*(s: string, sep: Regex): string =
|
||||
## Splits the string `s` into substrings.
|
||||
##
|
||||
|
|
@ -373,41 +374,44 @@ iterator split*(s: string, sep: Regex): string =
|
|||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ""
|
||||
## "this"
|
||||
## "is"
|
||||
## "an"
|
||||
## "example"
|
||||
## ""
|
||||
##
|
||||
var
|
||||
first = 0
|
||||
last = 0
|
||||
first = -1
|
||||
last = -1
|
||||
while last < len(s):
|
||||
var x = matchLen(s, sep, last)
|
||||
if x > 0: inc(last, x)
|
||||
first = last
|
||||
if x == 0: inc(last)
|
||||
while last < len(s):
|
||||
inc(last)
|
||||
x = matchLen(s, sep, last)
|
||||
if x > 0: break
|
||||
if first < last:
|
||||
if x >= 0: break
|
||||
inc(last)
|
||||
if first <= last:
|
||||
yield substr(s, first, last-1)
|
||||
|
||||
proc split*(s: string, sep: Regex): seq[string] =
|
||||
## Splits the string `s` into substrings.
|
||||
accumulateResult(split(s, sep))
|
||||
|
||||
proc escapeRe*(s: string): string =
|
||||
## escapes `s` so that it is matched verbatim when used as a regular
|
||||
|
||||
proc escapeRe*(s: string): string =
|
||||
## escapes `s` so that it is matched verbatim when used as a regular
|
||||
## expression.
|
||||
result = ""
|
||||
for c in items(s):
|
||||
case c
|
||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_':
|
||||
result.add(c)
|
||||
else:
|
||||
else:
|
||||
result.add("\\x")
|
||||
result.add(toHex(ord(c), 2))
|
||||
|
||||
|
||||
const ## common regular expressions
|
||||
reIdentifier* = r"\b[a-zA-Z_]+[a-zA-Z_0-9]*\b" ## describes an identifier
|
||||
reNatural* = r"\b\d+\b" ## describes a natural number
|
||||
|
|
@ -430,7 +434,7 @@ const ## common regular expressions
|
|||
when isMainModule:
|
||||
assert match("(a b c)", re"\( .* \)")
|
||||
assert match("WHiLe", re("while", {reIgnoreCase}))
|
||||
|
||||
|
||||
assert "0158787".match(re"\d+")
|
||||
assert "ABC 0232".match(re"\w+\s+\d+")
|
||||
assert "ABC".match(re"\d+ | \w+")
|
||||
|
|
@ -439,21 +443,21 @@ when isMainModule:
|
|||
|
||||
var pattern = re"[a-z0-9]+\s*=\s*[a-z0-9]+"
|
||||
assert matchLen("key1= cal9", pattern) == 11
|
||||
|
||||
|
||||
assert find("_____abc_______", re"abc") == 5
|
||||
|
||||
var matches: array[0..5, string]
|
||||
if match("abcdefg", re"c(d)ef(g)", matches, 2):
|
||||
|
||||
var matches: array[6, string]
|
||||
if match("abcdefg", re"c(d)ef(g)", matches, 2):
|
||||
assert matches[0] == "d"
|
||||
assert matches[1] == "g"
|
||||
else:
|
||||
assert false
|
||||
|
||||
|
||||
if "abc" =~ re"(a)bcxyz|(\w+)":
|
||||
assert matches[1] == "abc"
|
||||
else:
|
||||
assert false
|
||||
|
||||
|
||||
if "abc" =~ re"(cba)?.*":
|
||||
assert matches[0] == nil
|
||||
else: assert false
|
||||
|
|
@ -461,7 +465,7 @@ when isMainModule:
|
|||
if "abc" =~ re"().*":
|
||||
assert matches[0] == ""
|
||||
else: assert false
|
||||
|
||||
|
||||
assert "var1=key; var2=key2".endsWith(re"\w+=\w+")
|
||||
assert("var1=key; var2=key2".replacef(re"(\w+)=(\w+)", "$1<-$2$2") ==
|
||||
"var1<-keykey; var2<-key2key2")
|
||||
|
|
@ -471,7 +475,12 @@ when isMainModule:
|
|||
var accum: seq[string] = @[]
|
||||
for word in split("00232this02939is39an22example111", re"\d+"):
|
||||
accum.add(word)
|
||||
assert(accum == @["this", "is", "an", "example"])
|
||||
assert(accum == @["", "this", "is", "an", "example", ""])
|
||||
|
||||
accum = @[]
|
||||
for word in split("AAA : : BBB", re"\s*:\s*"):
|
||||
accum.add(word)
|
||||
assert(accum == @["AAA", "", "BBB"])
|
||||
|
||||
for x in findAll("abcdef", re"^{.}", 3):
|
||||
assert x == "d"
|
||||
|
|
@ -484,7 +493,7 @@ when isMainModule:
|
|||
assert("XYZ".match(re"^\d*") == true)
|
||||
|
||||
block:
|
||||
var matches: array[0..15, string]
|
||||
var matches: array[16, string]
|
||||
if match("abcdefghijklmnop", re"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)(o)(p)", matches):
|
||||
for i in 0..matches.high:
|
||||
assert matches[i] == $chr(i + 'a'.ord)
|
||||
|
|
|
|||
293
lib/js/dom.nim
293
lib/js/dom.nim
|
|
@ -36,8 +36,11 @@ type
|
|||
onsubmit*: proc (event: ref TEvent) {.nimcall.}
|
||||
onunload*: proc (event: ref TEvent) {.nimcall.}
|
||||
|
||||
TWindow* {.importc.} = object of TEventHandlers
|
||||
document*: ref TDocument
|
||||
addEventListener*: proc(ev: cstring, cb: proc(ev: ref TEvent), useCapture: bool = false) {.nimcall.}
|
||||
|
||||
Window* = ref WindowObj
|
||||
WindowObj {.importc.} = object of TEventHandlers
|
||||
document*: Document
|
||||
event*: ref TEvent
|
||||
history*: ref THistory
|
||||
location*: ref TLocation
|
||||
|
|
@ -55,7 +58,6 @@ type
|
|||
status*: cstring
|
||||
toolbar*: ref TToolBar
|
||||
|
||||
addEventListener*: proc(ev: cstring, cb: proc(ev: ref TEvent) ) {.nimcall.}
|
||||
alert*: proc (msg: cstring) {.nimcall.}
|
||||
back*: proc () {.nimcall.}
|
||||
blur*: proc () {.nimcall.}
|
||||
|
|
@ -66,7 +68,7 @@ type
|
|||
confirm*: proc (msg: cstring): bool {.nimcall.}
|
||||
disableExternalCapture*: proc () {.nimcall.}
|
||||
enableExternalCapture*: proc () {.nimcall.}
|
||||
find*: proc (text: cstring, caseSensitive = false,
|
||||
find*: proc (text: cstring, caseSensitive = false,
|
||||
backwards = false) {.nimcall.}
|
||||
focus*: proc () {.nimcall.}
|
||||
forward*: proc () {.nimcall.}
|
||||
|
|
@ -75,7 +77,7 @@ type
|
|||
moveBy*: proc (x, y: int) {.nimcall.}
|
||||
moveTo*: proc (x, y: int) {.nimcall.}
|
||||
open*: proc (uri, windowname: cstring,
|
||||
properties: cstring = nil): ref TWindow {.nimcall.}
|
||||
properties: cstring = nil): Window {.nimcall.}
|
||||
print*: proc () {.nimcall.}
|
||||
prompt*: proc (text, default: cstring): cstring {.nimcall.}
|
||||
releaseEvents*: proc (eventMask: int) {.nimcall.}
|
||||
|
|
@ -89,115 +91,8 @@ type
|
|||
stop*: proc () {.nimcall.}
|
||||
frames*: seq[TFrame]
|
||||
|
||||
TFrame* {.importc.} = object of TWindow
|
||||
|
||||
TDocument* {.importc.} = object of TEventHandlers
|
||||
addEventListener*: proc(ev: cstring, cb: proc(ev: ref TEvent) ) {.nimcall.}
|
||||
alinkColor*: cstring
|
||||
bgColor*: cstring
|
||||
charset*: cstring
|
||||
cookie*: cstring
|
||||
defaultCharset*: cstring
|
||||
fgColor*: cstring
|
||||
lastModified*: cstring
|
||||
linkColor*: cstring
|
||||
referrer*: cstring
|
||||
title*: cstring
|
||||
URL*: cstring
|
||||
vlinkColor*: cstring
|
||||
captureEvents*: proc (eventMask: int) {.nimcall.}
|
||||
createAttribute*: proc (identifier: cstring): ref TNode {.nimcall.}
|
||||
createElement*: proc (identifier: cstring): ref TNode {.nimcall.}
|
||||
createTextNode*: proc (identifier: cstring): ref TNode {.nimcall.}
|
||||
getElementById*: proc (id: cstring): ref TNode {.nimcall.}
|
||||
getElementsByName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
|
||||
getElementsByTagName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
|
||||
getElementsByClassName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
|
||||
getSelection*: proc (): cstring {.nimcall.}
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
open*: proc () {.nimcall.}
|
||||
releaseEvents*: proc (eventMask: int) {.nimcall.}
|
||||
routeEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
write*: proc (text: cstring) {.nimcall.}
|
||||
writeln*: proc (text: cstring) {.nimcall.}
|
||||
anchors*: seq[ref TAnchor]
|
||||
forms*: seq[ref TForm]
|
||||
images*: seq[ref TImage]
|
||||
applets*: seq[ref TApplet]
|
||||
embeds*: seq[ref TEmbed]
|
||||
links*: seq[ref TLink]
|
||||
|
||||
TLink* {.importc.} = object of RootObj
|
||||
name*: cstring
|
||||
target*: cstring
|
||||
text*: cstring
|
||||
x*: int
|
||||
y*: int
|
||||
|
||||
TEmbed* {.importc.} = object of RootObj
|
||||
height*: int
|
||||
hspace*: int
|
||||
name*: cstring
|
||||
src*: cstring
|
||||
width*: int
|
||||
`type`*: cstring
|
||||
vspace*: int
|
||||
play*: proc () {.nimcall.}
|
||||
stop*: proc () {.nimcall.}
|
||||
|
||||
TAnchor* {.importc.} = object of RootObj
|
||||
name*: cstring
|
||||
text*: cstring
|
||||
x*, y*: int
|
||||
|
||||
TApplet* {.importc.} = object of RootObj
|
||||
|
||||
TElement* {.importc.} = object of TEventHandlers
|
||||
checked*: bool
|
||||
defaultChecked*: bool
|
||||
defaultValue*: cstring
|
||||
disabled*: bool
|
||||
form*: ref TForm
|
||||
name*: cstring
|
||||
readOnly*: bool
|
||||
`type`*: cstring
|
||||
value*: cstring
|
||||
blur*: proc () {.nimcall.}
|
||||
click*: proc () {.nimcall.}
|
||||
focus*: proc () {.nimcall.}
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
select*: proc () {.nimcall.}
|
||||
options*: seq[ref TOption]
|
||||
|
||||
TOption* {.importc.} = object of RootObj
|
||||
defaultSelected*: bool
|
||||
selected*: bool
|
||||
selectedIndex*: int
|
||||
text*: cstring
|
||||
value*: cstring
|
||||
|
||||
TForm* {.importc.} = object of TEventHandlers
|
||||
action*: cstring
|
||||
encoding*: cstring
|
||||
`method`*: cstring
|
||||
name*: cstring
|
||||
target*: cstring
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
reset*: proc () {.nimcall.}
|
||||
submit*: proc () {.nimcall.}
|
||||
elements*: seq[ref TElement]
|
||||
|
||||
TImage* {.importc.} = object of TEventHandlers
|
||||
border*: int
|
||||
complete*: bool
|
||||
height*: int
|
||||
hspace*: int
|
||||
lowsrc*: cstring
|
||||
name*: cstring
|
||||
src*: cstring
|
||||
vspace*: int
|
||||
width*: int
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
Frame* = ref FrameObj
|
||||
FrameObj {.importc.} = object of WindowObj
|
||||
|
||||
ClassList* {.importc.} = object of RootObj
|
||||
add*: proc (class: cstring) {.nimcall.}
|
||||
|
|
@ -218,43 +113,151 @@ type
|
|||
DocumentTypeNode,
|
||||
DocumentFragmentNode,
|
||||
NotationNode
|
||||
TNode* {.importc.} = object of RootObj
|
||||
attributes*: seq[ref TNode]
|
||||
childNodes*: seq[ref TNode]
|
||||
children*: seq[ref TNode]
|
||||
classList*: ref Classlist
|
||||
|
||||
Node* = ref NodeObj
|
||||
NodeObj {.importc.} = object of TEventHandlers
|
||||
attributes*: seq[Node]
|
||||
childNodes*: seq[Node]
|
||||
children*: seq[Node]
|
||||
data*: cstring
|
||||
firstChild*: ref TNode
|
||||
lastChild*: ref TNode
|
||||
nextSibling*: ref TNode
|
||||
firstChild*: Node
|
||||
lastChild*: Node
|
||||
nextSibling*: Node
|
||||
nodeName*: cstring
|
||||
nodeType*: TNodeType
|
||||
nodeValue*: cstring
|
||||
parentNode*: ref TNode
|
||||
previousSibling*: ref TNode
|
||||
appendChild*: proc (child: ref TNode) {.nimcall.}
|
||||
parentNode*: Node
|
||||
previousSibling*: Node
|
||||
appendChild*: proc (child: Node) {.nimcall.}
|
||||
appendData*: proc (data: cstring) {.nimcall.}
|
||||
cloneNode*: proc (copyContent: bool): ref TNode {.nimcall.}
|
||||
cloneNode*: proc (copyContent: bool): Node {.nimcall.}
|
||||
deleteData*: proc (start, len: int) {.nimcall.}
|
||||
getAttribute*: proc (attr: cstring): cstring {.nimcall.}
|
||||
getAttributeNode*: proc (attr: cstring): ref TNode {.nimcall.}
|
||||
getElementsByTagName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
|
||||
getElementsByClassName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
|
||||
getAttributeNode*: proc (attr: cstring): Node {.nimcall.}
|
||||
hasChildNodes*: proc (): bool {.nimcall.}
|
||||
innerHTML*: cstring
|
||||
insertBefore*: proc (newNode, before: ref TNode) {.nimcall.}
|
||||
insertBefore*: proc (newNode, before: Node) {.nimcall.}
|
||||
insertData*: proc (position: int, data: cstring) {.nimcall.}
|
||||
addEventListener*: proc(ev: cstring, cb: proc(ev: ref TEvent)) {.nimcall.}
|
||||
removeAttribute*: proc (attr: cstring) {.nimcall.}
|
||||
removeAttributeNode*: proc (attr: ref TNode) {.nimcall.}
|
||||
removeChild*: proc (child: ref TNode) {.nimcall.}
|
||||
replaceChild*: proc (newNode, oldNode: ref TNode) {.nimcall.}
|
||||
removeAttributeNode*: proc (attr: Node) {.nimcall.}
|
||||
removeChild*: proc (child: Node) {.nimcall.}
|
||||
replaceChild*: proc (newNode, oldNode: Node) {.nimcall.}
|
||||
replaceData*: proc (start, len: int, text: cstring) {.nimcall.}
|
||||
scrollIntoView*: proc () {.nimcall.}
|
||||
setAttribute*: proc (name, value: cstring) {.nimcall.}
|
||||
setAttributeNode*: proc (attr: ref TNode) {.nimcall.}
|
||||
setAttributeNode*: proc (attr: Node) {.nimcall.}
|
||||
style*: ref TStyle
|
||||
|
||||
Document* = ref DocumentObj
|
||||
DocumentObj {.importc.} = object of NodeObj
|
||||
alinkColor*: cstring
|
||||
bgColor*: cstring
|
||||
charset*: cstring
|
||||
cookie*: cstring
|
||||
defaultCharset*: cstring
|
||||
fgColor*: cstring
|
||||
lastModified*: cstring
|
||||
linkColor*: cstring
|
||||
referrer*: cstring
|
||||
title*: cstring
|
||||
URL*: cstring
|
||||
vlinkColor*: cstring
|
||||
captureEvents*: proc (eventMask: int) {.nimcall.}
|
||||
createAttribute*: proc (identifier: cstring): Node {.nimcall.}
|
||||
createElement*: proc (identifier: cstring): Element {.nimcall.}
|
||||
createTextNode*: proc (identifier: cstring): Node {.nimcall.}
|
||||
getElementById*: proc (id: cstring): Element {.nimcall.}
|
||||
getElementsByName*: proc (name: cstring): seq[Element] {.nimcall.}
|
||||
getElementsByTagName*: proc (name: cstring): seq[Element] {.nimcall.}
|
||||
getElementsByClassName*: proc (name: cstring): seq[Element] {.nimcall.}
|
||||
getSelection*: proc (): cstring {.nimcall.}
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
open*: proc () {.nimcall.}
|
||||
releaseEvents*: proc (eventMask: int) {.nimcall.}
|
||||
routeEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
write*: proc (text: cstring) {.nimcall.}
|
||||
writeln*: proc (text: cstring) {.nimcall.}
|
||||
anchors*: seq[AnchorElement]
|
||||
forms*: seq[FormElement]
|
||||
images*: seq[ImageElement]
|
||||
applets*: seq[ref TApplet]
|
||||
embeds*: seq[EmbedElement]
|
||||
links*: seq[LinkElement]
|
||||
|
||||
Element* = ref ElementObj
|
||||
ElementObj {.importc.} = object of NodeObj
|
||||
classList*: ref Classlist
|
||||
checked*: bool
|
||||
defaultChecked*: bool
|
||||
defaultValue*: cstring
|
||||
disabled*: bool
|
||||
form*: FormElement
|
||||
name*: cstring
|
||||
readOnly*: bool
|
||||
blur*: proc () {.nimcall.}
|
||||
click*: proc () {.nimcall.}
|
||||
focus*: proc () {.nimcall.}
|
||||
handleEvent*: proc (event: ref TEvent) {.nimcall.}
|
||||
select*: proc () {.nimcall.}
|
||||
options*: seq[OptionElement]
|
||||
getElementsByTagName*: proc (name: cstring): seq[Element] {.nimcall.}
|
||||
getElementsByClassName*: proc (name: cstring): seq[Element] {.nimcall.}
|
||||
|
||||
LinkElement* = ref LinkObj
|
||||
LinkObj {.importc.} = object of ElementObj
|
||||
target*: cstring
|
||||
text*: cstring
|
||||
x*: int
|
||||
y*: int
|
||||
|
||||
EmbedElement* = ref EmbedObj
|
||||
EmbedObj {.importc.} = object of ElementObj
|
||||
height*: int
|
||||
hspace*: int
|
||||
src*: cstring
|
||||
width*: int
|
||||
`type`*: cstring
|
||||
vspace*: int
|
||||
play*: proc () {.nimcall.}
|
||||
stop*: proc () {.nimcall.}
|
||||
|
||||
AnchorElement* = ref AnchorObj
|
||||
AnchorObj {.importc.} = object of ElementObj
|
||||
text*: cstring
|
||||
x*, y*: int
|
||||
|
||||
TApplet* {.importc.} = object of RootObj
|
||||
|
||||
OptionElement* = ref OptionObj
|
||||
OptionObj {.importc.} = object of ElementObj
|
||||
defaultSelected*: bool
|
||||
selected*: bool
|
||||
selectedIndex*: int
|
||||
text*: cstring
|
||||
value*: cstring
|
||||
|
||||
FormElement* = ref FormObj
|
||||
FormObj {.importc.} = object of ElementObj
|
||||
action*: cstring
|
||||
encoding*: cstring
|
||||
`method`*: cstring
|
||||
target*: cstring
|
||||
reset*: proc () {.nimcall.}
|
||||
submit*: proc () {.nimcall.}
|
||||
elements*: seq[Element]
|
||||
|
||||
ImageElement* = ref ImageObj
|
||||
ImageObj {.importc.} = object of ElementObj
|
||||
border*: int
|
||||
complete*: bool
|
||||
height*: int
|
||||
hspace*: int
|
||||
lowsrc*: cstring
|
||||
src*: cstring
|
||||
vspace*: int
|
||||
width*: int
|
||||
|
||||
|
||||
TStyle* {.importc.} = object of RootObj
|
||||
background*: cstring
|
||||
backgroundAttachment*: cstring
|
||||
|
|
@ -350,7 +353,7 @@ type
|
|||
setAttribute*: proc (attr, value: cstring, caseSensitive=false) {.nimcall.}
|
||||
|
||||
TEvent* {.importc.} = object of RootObj
|
||||
target*: ref TNode
|
||||
target*: Node
|
||||
altKey*, ctrlKey*, shiftKey*: bool
|
||||
button*: int
|
||||
clientX*, clientY*: int
|
||||
|
|
@ -448,8 +451,8 @@ type
|
|||
TInterval* {.importc.} = object of RootObj
|
||||
|
||||
var
|
||||
window* {.importc, nodecl.}: ref TWindow
|
||||
document* {.importc, nodecl.}: ref TDocument
|
||||
window* {.importc, nodecl.}: Window
|
||||
document* {.importc, nodecl.}: Document
|
||||
navigator* {.importc, nodecl.}: ref TNavigator
|
||||
screen* {.importc, nodecl.}: ref TScreen
|
||||
|
||||
|
|
@ -466,3 +469,17 @@ proc isNaN*(x: BiggestFloat): bool {.importc, nodecl.}
|
|||
proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.}
|
||||
proc parseInt*(s: cstring): int {.importc, nodecl.}
|
||||
proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.}
|
||||
|
||||
|
||||
type
|
||||
TWindow* {.deprecated.} = WindowObj
|
||||
TFrame* {.deprecated.} = FrameObj
|
||||
TNode* {.deprecated.} = NodeObj
|
||||
TDocument* {.deprecated.} = DocumentObj
|
||||
TElement* {.deprecated.} = ElementObj
|
||||
TLink* {.deprecated.} = LinkObj
|
||||
TEmbed* {.deprecated.} = EmbedObj
|
||||
TAnchor* {.deprecated.} = AnchorObj
|
||||
TOption* {.deprecated.} = OptionObj
|
||||
TForm* {.deprecated.} = FormObj
|
||||
TImage* {.deprecated.} = ImageObj
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,7 @@ type
|
|||
rnField, # a field item
|
||||
rnFieldName, # consisting of a field name ...
|
||||
rnFieldBody, # ... and a field body
|
||||
rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString,
|
||||
rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString,
|
||||
rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock,
|
||||
rnLineBlock, # the | thingie
|
||||
rnLineBlockItem, # sons of the | thing
|
||||
|
|
@ -50,7 +50,7 @@ type
|
|||
# * `file#id <file#id>'_
|
||||
rnSubstitutionDef, # a definition of a substitution
|
||||
rnGeneralRole, # Inline markup:
|
||||
rnSub, rnSup, rnIdx,
|
||||
rnSub, rnSup, rnIdx,
|
||||
rnEmphasis, # "*"
|
||||
rnStrongEmphasis, # "**"
|
||||
rnTripleEmphasis, # "***"
|
||||
|
|
@ -71,25 +71,25 @@ type
|
|||
level*: int ## valid for some node kinds
|
||||
sons*: TRstNodeSeq ## the node's sons
|
||||
|
||||
proc len*(n: PRstNode): int =
|
||||
proc len*(n: PRstNode): int =
|
||||
result = len(n.sons)
|
||||
|
||||
proc newRstNode*(kind: TRstNodeKind): PRstNode =
|
||||
proc newRstNode*(kind: TRstNodeKind): PRstNode =
|
||||
new(result)
|
||||
result.sons = @[]
|
||||
result.kind = kind
|
||||
|
||||
proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode =
|
||||
proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode =
|
||||
result = newRstNode(kind)
|
||||
result.text = s
|
||||
|
||||
proc lastSon*(n: PRstNode): PRstNode =
|
||||
proc lastSon*(n: PRstNode): PRstNode =
|
||||
result = n.sons[len(n.sons)-1]
|
||||
|
||||
proc add*(father, son: PRstNode) =
|
||||
add(father.sons, son)
|
||||
|
||||
proc addIfNotNil*(father, son: PRstNode) =
|
||||
proc addIfNotNil*(father, son: PRstNode) =
|
||||
if son != nil: add(father, son)
|
||||
|
||||
|
||||
|
|
@ -98,26 +98,27 @@ type
|
|||
indent: int
|
||||
verbatim: int
|
||||
|
||||
proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string)
|
||||
proc renderRstToRst(d: var TRenderContext, n: PRstNode,
|
||||
result: var string) {.gcsafe.}
|
||||
|
||||
proc renderRstSons(d: var TRenderContext, n: PRstNode, result: var string) =
|
||||
for i in countup(0, len(n) - 1):
|
||||
proc renderRstSons(d: var TRenderContext, n: PRstNode, result: var string) =
|
||||
for i in countup(0, len(n) - 1):
|
||||
renderRstToRst(d, n.sons[i], result)
|
||||
|
||||
|
||||
proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
||||
# this is needed for the index generation; it may also be useful for
|
||||
# debugging, but most code is already debugged...
|
||||
const
|
||||
const
|
||||
lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
|
||||
if n == nil: return
|
||||
var ind = spaces(d.indent)
|
||||
case n.kind
|
||||
of rnInner:
|
||||
of rnInner:
|
||||
renderRstSons(d, n, result)
|
||||
of rnHeadline:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
|
||||
|
||||
let oldLen = result.len
|
||||
renderRstSons(d, n, result)
|
||||
let headlineLen = result.len - oldLen
|
||||
|
|
@ -131,16 +132,16 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
|
||||
var headline = ""
|
||||
renderRstSons(d, n, headline)
|
||||
|
||||
|
||||
let lvl = repeat(lvlToChar[n.level], headline.len - d.indent)
|
||||
result.add(lvl)
|
||||
result.add("\n")
|
||||
result.add(headline)
|
||||
|
||||
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add(lvl)
|
||||
of rnTransition:
|
||||
of rnTransition:
|
||||
result.add("\n\n")
|
||||
result.add(ind)
|
||||
result.add repeat('-', 78-d.indent)
|
||||
|
|
@ -149,11 +150,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add("\n\n")
|
||||
result.add(ind)
|
||||
renderRstSons(d, n, result)
|
||||
of rnBulletItem:
|
||||
of rnBulletItem:
|
||||
inc(d.indent, 2)
|
||||
var tmp = ""
|
||||
renderRstSons(d, n, tmp)
|
||||
if tmp.len > 0:
|
||||
if tmp.len > 0:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add("* ")
|
||||
|
|
@ -163,22 +164,22 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
inc(d.indent, 4)
|
||||
var tmp = ""
|
||||
renderRstSons(d, n, tmp)
|
||||
if tmp.len > 0:
|
||||
if tmp.len > 0:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add("(#) ")
|
||||
result.add(tmp)
|
||||
dec(d.indent, 4)
|
||||
of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName,
|
||||
rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList:
|
||||
of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName,
|
||||
rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList:
|
||||
renderRstSons(d, n, result)
|
||||
of rnDefName:
|
||||
of rnDefName:
|
||||
result.add("\n\n")
|
||||
result.add(ind)
|
||||
renderRstSons(d, n, result)
|
||||
of rnDefBody:
|
||||
inc(d.indent, 2)
|
||||
if n.sons[0].kind != rnBulletList:
|
||||
if n.sons[0].kind != rnBulletList:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add(" ")
|
||||
|
|
@ -187,10 +188,10 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
of rnField:
|
||||
var tmp = ""
|
||||
renderRstToRst(d, n.sons[0], tmp)
|
||||
|
||||
|
||||
var L = max(tmp.len + 3, 30)
|
||||
inc(d.indent, L)
|
||||
|
||||
|
||||
result.add "\n"
|
||||
result.add ind
|
||||
result.add ':'
|
||||
|
|
@ -198,9 +199,9 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add ':'
|
||||
result.add spaces(L - tmp.len - 2)
|
||||
renderRstToRst(d, n.sons[1], result)
|
||||
|
||||
|
||||
dec(d.indent, L)
|
||||
of rnLineBlockItem:
|
||||
of rnLineBlockItem:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add("| ")
|
||||
|
|
@ -209,11 +210,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
inc(d.indent, 2)
|
||||
renderRstSons(d, n, result)
|
||||
dec(d.indent, 2)
|
||||
of rnRef:
|
||||
of rnRef:
|
||||
result.add("`")
|
||||
renderRstSons(d, n, result)
|
||||
result.add("`_")
|
||||
of rnHyperlink:
|
||||
of rnHyperlink:
|
||||
result.add('`')
|
||||
renderRstToRst(d, n.sons[0], result)
|
||||
result.add(" <")
|
||||
|
|
@ -225,23 +226,23 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add("`:")
|
||||
renderRstToRst(d, n.sons[1],result)
|
||||
result.add(':')
|
||||
of rnSub:
|
||||
of rnSub:
|
||||
result.add('`')
|
||||
renderRstSons(d, n, result)
|
||||
result.add("`:sub:")
|
||||
of rnSup:
|
||||
of rnSup:
|
||||
result.add('`')
|
||||
renderRstSons(d, n, result)
|
||||
result.add("`:sup:")
|
||||
of rnIdx:
|
||||
of rnIdx:
|
||||
result.add('`')
|
||||
renderRstSons(d, n, result)
|
||||
result.add("`:idx:")
|
||||
of rnEmphasis:
|
||||
of rnEmphasis:
|
||||
result.add("*")
|
||||
renderRstSons(d, n, result)
|
||||
result.add("*")
|
||||
of rnStrongEmphasis:
|
||||
of rnStrongEmphasis:
|
||||
result.add("**")
|
||||
renderRstSons(d, n, result)
|
||||
result.add("**")
|
||||
|
|
@ -249,11 +250,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add("***")
|
||||
renderRstSons(d, n, result)
|
||||
result.add("***")
|
||||
of rnInterpretedText:
|
||||
of rnInterpretedText:
|
||||
result.add('`')
|
||||
renderRstSons(d, n, result)
|
||||
result.add('`')
|
||||
of rnInlineLiteral:
|
||||
of rnInlineLiteral:
|
||||
inc(d.verbatim)
|
||||
result.add("``")
|
||||
renderRstSons(d, n, result)
|
||||
|
|
@ -266,11 +267,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add("\\\\") # XXX: escape more special characters!
|
||||
else:
|
||||
result.add(n.text)
|
||||
of rnIndex:
|
||||
of rnIndex:
|
||||
result.add("\n\n")
|
||||
result.add(ind)
|
||||
result.add(".. index::\n")
|
||||
|
||||
|
||||
inc(d.indent, 3)
|
||||
if n.sons[2] != nil: renderRstSons(d, n.sons[2], result)
|
||||
dec(d.indent, 3)
|
||||
|
|
@ -280,7 +281,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
result.add(".. contents::")
|
||||
else:
|
||||
result.add("Error: cannot render: " & $n.kind)
|
||||
|
||||
|
||||
proc renderRstToRst*(n: PRstNode, result: var string) =
|
||||
## renders `n` into its string representation and appends to `result`.
|
||||
var d: TRenderContext
|
||||
|
|
@ -302,7 +303,7 @@ proc renderRstToJsonNode(node: PRstNode): JsonNode =
|
|||
|
||||
proc renderRstToJson*(node: PRstNode): string =
|
||||
## Writes the given RST node as JSON that is in the form
|
||||
## ::
|
||||
## ::
|
||||
## {
|
||||
## "kind":string node.kind,
|
||||
## "text":optional string node.text,
|
||||
|
|
|
|||
|
|
@ -95,10 +95,11 @@ type
|
|||
header: "<dirent.h>", final, pure.} = object ## dirent_t struct
|
||||
d_ino*: Tino ## File serial number.
|
||||
when defined(linux) or defined(macosx) or defined(bsd):
|
||||
d_off*: TOff ## Not an offset. Value that ``telldir()`` would return.
|
||||
d_reclen*: cshort ## Length of this record. (not POSIX)
|
||||
d_type*: int8 ## Type of file; not supported by all filesystem types.
|
||||
## (not POSIX)
|
||||
when defined(linux) or defined(bsd):
|
||||
d_off*: TOff ## Not an offset. Value that ``telldir()`` would return.
|
||||
d_name*: array [0..255, char] ## Name of entry.
|
||||
|
||||
Tflock* {.importc: "struct flock", final, pure,
|
||||
|
|
@ -1579,8 +1580,11 @@ else:
|
|||
|
||||
when defined(macosx):
|
||||
# We can't use the NOSIGNAL flag in the ``send`` function, it has no effect
|
||||
var
|
||||
# Instead we should use SO_NOSIGPIPE in setsockopt
|
||||
const
|
||||
MSG_NOSIGNAL* = 0'i32
|
||||
var
|
||||
SO_NOSIGPIPE* {.importc, header: "<sys/socket.h>".}: cint
|
||||
else:
|
||||
var
|
||||
MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -841,6 +841,8 @@ else:
|
|||
proc newAsyncRawSocket*(domain: cint, typ: cint, protocol: cint): TAsyncFD =
|
||||
result = newRawSocket(domain, typ, protocol).TAsyncFD
|
||||
result.SocketHandle.setBlocking(false)
|
||||
when defined(macosx):
|
||||
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
|
||||
register(result)
|
||||
|
||||
proc newAsyncRawSocket*(domain: Domain = AF_INET,
|
||||
|
|
@ -848,6 +850,8 @@ else:
|
|||
protocol: Protocol = IPPROTO_TCP): TAsyncFD =
|
||||
result = newRawSocket(domain, typ, protocol).TAsyncFD
|
||||
result.SocketHandle.setBlocking(false)
|
||||
when defined(macosx):
|
||||
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
|
||||
register(result)
|
||||
|
||||
proc closeSocket*(sock: TAsyncFD) =
|
||||
|
|
@ -959,7 +963,6 @@ else:
|
|||
result = true
|
||||
let res = recv(sock.SocketHandle, addr readBuffer[0], size.cint,
|
||||
flags.toOSFlags())
|
||||
#echo("recv cb res: ", res)
|
||||
if res < 0:
|
||||
let lastError = osLastError()
|
||||
if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}:
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
## copy; use ``assign`` to get a deep copy.
|
||||
|
||||
import
|
||||
os, hashes, math
|
||||
hashes, math
|
||||
|
||||
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
|
||||
|
|
@ -798,177 +798,178 @@ proc `==`*[A](s, t: OrderedSet[A]): bool =
|
|||
g = nxg
|
||||
result = compared == s.counter
|
||||
|
||||
proc testModule() =
|
||||
## Internal micro test to validate docstrings and such.
|
||||
block isValidTest:
|
||||
var options: HashSet[string]
|
||||
proc savePreferences(options: HashSet[string]) =
|
||||
assert options.isValid, "Pass an initialized set!"
|
||||
options = initSet[string]()
|
||||
options.savePreferences
|
||||
when isMainModule and not defined(release):
|
||||
proc testModule() =
|
||||
## Internal micro test to validate docstrings and such.
|
||||
block isValidTest:
|
||||
var options: HashSet[string]
|
||||
proc savePreferences(options: HashSet[string]) =
|
||||
assert options.isValid, "Pass an initialized set!"
|
||||
options = initSet[string]()
|
||||
options.savePreferences
|
||||
|
||||
block lenTest:
|
||||
var values: HashSet[int]
|
||||
assert(not values.isValid)
|
||||
assert values.len == 0
|
||||
assert values.card == 0
|
||||
block lenTest:
|
||||
var values: HashSet[int]
|
||||
assert(not values.isValid)
|
||||
assert values.len == 0
|
||||
assert values.card == 0
|
||||
|
||||
block setIterator:
|
||||
type pair = tuple[a, b: int]
|
||||
var a, b = initSet[pair]()
|
||||
a.incl((2, 3))
|
||||
a.incl((3, 2))
|
||||
a.incl((2, 3))
|
||||
for x, y in a.items:
|
||||
b.incl((x - 2, y + 1))
|
||||
assert a.len == b.card
|
||||
assert a.len == 2
|
||||
#echo b
|
||||
block setIterator:
|
||||
type pair = tuple[a, b: int]
|
||||
var a, b = initSet[pair]()
|
||||
a.incl((2, 3))
|
||||
a.incl((3, 2))
|
||||
a.incl((2, 3))
|
||||
for x, y in a.items:
|
||||
b.incl((x - 2, y + 1))
|
||||
assert a.len == b.card
|
||||
assert a.len == 2
|
||||
#echo b
|
||||
|
||||
block setContains:
|
||||
var values = initSet[int]()
|
||||
assert(not values.contains(2))
|
||||
values.incl(2)
|
||||
assert values.contains(2)
|
||||
values.excl(2)
|
||||
assert(not values.contains(2))
|
||||
block setContains:
|
||||
var values = initSet[int]()
|
||||
assert(not values.contains(2))
|
||||
values.incl(2)
|
||||
assert values.contains(2)
|
||||
values.excl(2)
|
||||
assert(not values.contains(2))
|
||||
|
||||
values.incl(4)
|
||||
var others = toSet([6, 7])
|
||||
values.incl(others)
|
||||
assert values.len == 3
|
||||
values.incl(4)
|
||||
var others = toSet([6, 7])
|
||||
values.incl(others)
|
||||
assert values.len == 3
|
||||
|
||||
values.init
|
||||
assert values.containsOrIncl(2) == false
|
||||
assert values.containsOrIncl(2) == true
|
||||
var
|
||||
a = toSet([1, 2])
|
||||
b = toSet([1])
|
||||
b.incl(2)
|
||||
assert a == b
|
||||
values.init
|
||||
assert values.containsOrIncl(2) == false
|
||||
assert values.containsOrIncl(2) == true
|
||||
var
|
||||
a = toSet([1, 2])
|
||||
b = toSet([1])
|
||||
b.incl(2)
|
||||
assert a == b
|
||||
|
||||
block exclusions:
|
||||
var s = toSet([2, 3, 6, 7])
|
||||
s.excl(2)
|
||||
s.excl(2)
|
||||
assert s.len == 3
|
||||
block exclusions:
|
||||
var s = toSet([2, 3, 6, 7])
|
||||
s.excl(2)
|
||||
s.excl(2)
|
||||
assert s.len == 3
|
||||
|
||||
var
|
||||
numbers = toSet([1, 2, 3, 4, 5])
|
||||
even = toSet([2, 4, 6, 8])
|
||||
numbers.excl(even)
|
||||
#echo numbers
|
||||
# --> {1, 3, 5}
|
||||
var
|
||||
numbers = toSet([1, 2, 3, 4, 5])
|
||||
even = toSet([2, 4, 6, 8])
|
||||
numbers.excl(even)
|
||||
#echo numbers
|
||||
# --> {1, 3, 5}
|
||||
|
||||
block toSeqAndString:
|
||||
var a = toSet([2, 4, 5])
|
||||
var b = initSet[int]()
|
||||
for x in [2, 4, 5]: b.incl(x)
|
||||
assert($a == $b)
|
||||
#echo a
|
||||
#echo toSet(["no", "esc'aping", "is \" provided"])
|
||||
block toSeqAndString:
|
||||
var a = toSet([2, 4, 5])
|
||||
var b = initSet[int]()
|
||||
for x in [2, 4, 5]: b.incl(x)
|
||||
assert($a == $b)
|
||||
#echo a
|
||||
#echo toSet(["no", "esc'aping", "is \" provided"])
|
||||
|
||||
#block orderedToSeqAndString:
|
||||
# echo toOrderedSet([2, 4, 5])
|
||||
# echo toOrderedSet(["no", "esc'aping", "is \" provided"])
|
||||
#block orderedToSeqAndString:
|
||||
# echo toOrderedSet([2, 4, 5])
|
||||
# echo toOrderedSet(["no", "esc'aping", "is \" provided"])
|
||||
|
||||
block setOperations:
|
||||
var
|
||||
a = toSet(["a", "b"])
|
||||
b = toSet(["b", "c"])
|
||||
c = union(a, b)
|
||||
assert c == toSet(["a", "b", "c"])
|
||||
var d = intersection(a, b)
|
||||
assert d == toSet(["b"])
|
||||
var e = difference(a, b)
|
||||
assert e == toSet(["a"])
|
||||
var f = symmetricDifference(a, b)
|
||||
assert f == toSet(["a", "c"])
|
||||
assert d < a and d < b
|
||||
assert((a < a) == false)
|
||||
assert d <= a and d <= b
|
||||
assert((a <= a))
|
||||
# Alias test.
|
||||
assert a + b == toSet(["a", "b", "c"])
|
||||
assert a * b == toSet(["b"])
|
||||
assert a - b == toSet(["a"])
|
||||
assert a -+- b == toSet(["a", "c"])
|
||||
assert disjoint(a, b) == false
|
||||
assert disjoint(a, b - a) == true
|
||||
block setOperations:
|
||||
var
|
||||
a = toSet(["a", "b"])
|
||||
b = toSet(["b", "c"])
|
||||
c = union(a, b)
|
||||
assert c == toSet(["a", "b", "c"])
|
||||
var d = intersection(a, b)
|
||||
assert d == toSet(["b"])
|
||||
var e = difference(a, b)
|
||||
assert e == toSet(["a"])
|
||||
var f = symmetricDifference(a, b)
|
||||
assert f == toSet(["a", "c"])
|
||||
assert d < a and d < b
|
||||
assert((a < a) == false)
|
||||
assert d <= a and d <= b
|
||||
assert((a <= a))
|
||||
# Alias test.
|
||||
assert a + b == toSet(["a", "b", "c"])
|
||||
assert a * b == toSet(["b"])
|
||||
assert a - b == toSet(["a"])
|
||||
assert a -+- b == toSet(["a", "c"])
|
||||
assert disjoint(a, b) == false
|
||||
assert disjoint(a, b - a) == true
|
||||
|
||||
block mapSet:
|
||||
var a = toSet([1, 2, 3])
|
||||
var b = a.map(proc (x: int): string = $x)
|
||||
assert b == toSet(["1", "2", "3"])
|
||||
block mapSet:
|
||||
var a = toSet([1, 2, 3])
|
||||
var b = a.map(proc (x: int): string = $x)
|
||||
assert b == toSet(["1", "2", "3"])
|
||||
|
||||
block isValidTest:
|
||||
var cards: OrderedSet[string]
|
||||
proc saveTarotCards(cards: OrderedSet[string]) =
|
||||
assert cards.isValid, "Pass an initialized set!"
|
||||
cards = initOrderedSet[string]()
|
||||
cards.saveTarotCards
|
||||
block isValidTest:
|
||||
var cards: OrderedSet[string]
|
||||
proc saveTarotCards(cards: OrderedSet[string]) =
|
||||
assert cards.isValid, "Pass an initialized set!"
|
||||
cards = initOrderedSet[string]()
|
||||
cards.saveTarotCards
|
||||
|
||||
block lenTest:
|
||||
var values: OrderedSet[int]
|
||||
assert(not values.isValid)
|
||||
assert values.len == 0
|
||||
assert values.card == 0
|
||||
block lenTest:
|
||||
var values: OrderedSet[int]
|
||||
assert(not values.isValid)
|
||||
assert values.len == 0
|
||||
assert values.card == 0
|
||||
|
||||
block setIterator:
|
||||
type pair = tuple[a, b: int]
|
||||
var a, b = initOrderedSet[pair]()
|
||||
a.incl((2, 3))
|
||||
a.incl((3, 2))
|
||||
a.incl((2, 3))
|
||||
for x, y in a.items:
|
||||
b.incl((x - 2, y + 1))
|
||||
assert a.len == b.card
|
||||
assert a.len == 2
|
||||
block setIterator:
|
||||
type pair = tuple[a, b: int]
|
||||
var a, b = initOrderedSet[pair]()
|
||||
a.incl((2, 3))
|
||||
a.incl((3, 2))
|
||||
a.incl((2, 3))
|
||||
for x, y in a.items:
|
||||
b.incl((x - 2, y + 1))
|
||||
assert a.len == b.card
|
||||
assert a.len == 2
|
||||
|
||||
#block orderedSetIterator:
|
||||
# var a = initOrderedSet[int]()
|
||||
# for value in [9, 2, 1, 5, 1, 8, 4, 2]:
|
||||
# a.incl(value)
|
||||
# for value in a.items:
|
||||
# echo "Got ", value
|
||||
#block orderedSetIterator:
|
||||
# var a = initOrderedSet[int]()
|
||||
# for value in [9, 2, 1, 5, 1, 8, 4, 2]:
|
||||
# a.incl(value)
|
||||
# for value in a.items:
|
||||
# echo "Got ", value
|
||||
|
||||
block setContains:
|
||||
var values = initOrderedSet[int]()
|
||||
assert(not values.contains(2))
|
||||
values.incl(2)
|
||||
assert values.contains(2)
|
||||
block setContains:
|
||||
var values = initOrderedSet[int]()
|
||||
assert(not values.contains(2))
|
||||
values.incl(2)
|
||||
assert values.contains(2)
|
||||
|
||||
block toSeqAndString:
|
||||
var a = toOrderedSet([2, 4, 5])
|
||||
var b = initOrderedSet[int]()
|
||||
for x in [2, 4, 5]: b.incl(x)
|
||||
assert($a == $b)
|
||||
assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
|
||||
block toSeqAndString:
|
||||
var a = toOrderedSet([2, 4, 5])
|
||||
var b = initOrderedSet[int]()
|
||||
for x in [2, 4, 5]: b.incl(x)
|
||||
assert($a == $b)
|
||||
assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
|
||||
|
||||
block initBlocks:
|
||||
var a: OrderedSet[int]
|
||||
a.init(4)
|
||||
a.incl(2)
|
||||
a.init
|
||||
assert a.len == 0 and a.isValid
|
||||
a = initOrderedSet[int](4)
|
||||
a.incl(2)
|
||||
assert a.len == 1
|
||||
block initBlocks:
|
||||
var a: OrderedSet[int]
|
||||
a.init(4)
|
||||
a.incl(2)
|
||||
a.init
|
||||
assert a.len == 0 and a.isValid
|
||||
a = initOrderedSet[int](4)
|
||||
a.incl(2)
|
||||
assert a.len == 1
|
||||
|
||||
var b: HashSet[int]
|
||||
b.init(4)
|
||||
b.incl(2)
|
||||
b.init
|
||||
assert b.len == 0 and b.isValid
|
||||
b = initSet[int](4)
|
||||
b.incl(2)
|
||||
assert b.len == 1
|
||||
var b: HashSet[int]
|
||||
b.init(4)
|
||||
b.incl(2)
|
||||
b.init
|
||||
assert b.len == 0 and b.isValid
|
||||
b = initSet[int](4)
|
||||
b.incl(2)
|
||||
assert b.len == 1
|
||||
|
||||
for i in 0 .. 32:
|
||||
var s = rightSize(i)
|
||||
if s <= i or mustRehash(s, i):
|
||||
echo "performance issue: rightSize() will not elide enlarge() at ", i
|
||||
for i in 0 .. 32:
|
||||
var s = rightSize(i)
|
||||
if s <= i or mustRehash(s, i):
|
||||
echo "performance issue: rightSize() will not elide enlarge() at ", i
|
||||
|
||||
echo "Micro tests run successfully."
|
||||
echo "Micro tests run successfully."
|
||||
|
||||
when isMainModule and not defined(release): testModule()
|
||||
testModule()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -605,6 +605,49 @@ proc newJArray*(): JsonNode =
|
|||
result.kind = JArray
|
||||
result.elems = @[]
|
||||
|
||||
proc getStr*(n: JsonNode, default: string = ""): string =
|
||||
## Retrieves the string value of a `JString JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JString``.
|
||||
if n.kind != JString: return default
|
||||
else: return n.str
|
||||
|
||||
proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt =
|
||||
## Retrieves the int value of a `JInt JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JInt``.
|
||||
if n.kind != JInt: return default
|
||||
else: return n.num
|
||||
|
||||
proc getFNum*(n: JsonNode, default: float = 0.0): float =
|
||||
## Retrieves the float value of a `JFloat JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JFloat``.
|
||||
if n.kind != JFloat: return default
|
||||
else: return n.fnum
|
||||
|
||||
proc getBVal*(n: JsonNode, default: bool = false): bool =
|
||||
## Retrieves the bool value of a `JBool JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JBool``.
|
||||
if n.kind != JBool: return default
|
||||
else: return n.bval
|
||||
|
||||
proc getFields*(n: JsonNode,
|
||||
default: seq[tuple[key: string, val: JsonNode]] = @[]):
|
||||
seq[tuple[key: string, val: JsonNode]] =
|
||||
## Retrieves the key, value pairs of a `JObject JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JObject``.
|
||||
if n.kind != JObject: return default
|
||||
else: return n.fields
|
||||
|
||||
proc getElems*(n: JsonNode, default: seq[JsonNode] = @[]): seq[JsonNode] =
|
||||
## Retrieves the int value of a `JArray JsonNode`.
|
||||
##
|
||||
## Returns ``default`` if ``n`` is not a ``JArray``.
|
||||
if n.kind != JArray: return default
|
||||
else: return n.elems
|
||||
|
||||
proc `%`*(s: string): JsonNode =
|
||||
## Generic constructor for JSON data. Creates a new `JString JsonNode`.
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ proc randomize*(seed: int) {.benign.}
|
|||
## Note: Does nothing for the JavaScript target,
|
||||
## as JavaScript does not support this.
|
||||
|
||||
{.push noSideEffect.}
|
||||
when not defined(JS):
|
||||
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
|
||||
## computes the square root of `x`.
|
||||
|
|
@ -273,6 +274,8 @@ else:
|
|||
var y = exp(2.0*x)
|
||||
return (y-1.0)/(y+1.0)
|
||||
|
||||
{.pop.}
|
||||
|
||||
proc `mod`*(x, y: float): float =
|
||||
result = if y == 0.0: x else: x - y * (x/y).floor
|
||||
|
||||
|
|
@ -370,3 +373,7 @@ when isMainModule and not defined(JS):
|
|||
for i in 0..SIZE-1:
|
||||
assert buf[i] == random(high(int)), "non deterministic random seeding"
|
||||
echo "random values equal after reseeding"
|
||||
|
||||
# Check for no side effect annotation
|
||||
proc mySqrt(num: float): float {.noSideEffect.} =
|
||||
return sqrt(num)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ proc startProcess*(command: string,
|
|||
## `env` is the environment that will be passed to the process.
|
||||
## If ``env == nil`` the environment is inherited of
|
||||
## the parent process. `options` are additional flags that may be passed
|
||||
## to `startProcess`. See the documentation of ``TProcessOption`` for the
|
||||
## to `startProcess`. See the documentation of ``ProcessOption`` for the
|
||||
## meaning of these flags. You need to `close` the process when done.
|
||||
##
|
||||
## Note that you can't pass any `args` if you use the option
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
## a denominator `den`, both of type int. The denominator can not be 0.
|
||||
|
||||
import math
|
||||
import hashes
|
||||
|
||||
type Rational*[T] = object
|
||||
## a rational number, consisting of a numerator and denominator
|
||||
|
|
@ -32,7 +33,7 @@ proc `$`*[T](x: Rational[T]): string =
|
|||
## Turn a rational number into a string.
|
||||
result = $x.num & "/" & $x.den
|
||||
|
||||
proc toRational*[T](x: SomeInteger): Rational[T] =
|
||||
proc toRational*[T](x: T): Rational[T] =
|
||||
## Convert some integer `x` to a rational number.
|
||||
result.num = x
|
||||
result.den = 1
|
||||
|
|
@ -188,7 +189,7 @@ proc `/=`*[T](x: var Rational[T], y: T) =
|
|||
x.den *= y
|
||||
reduce(x)
|
||||
|
||||
proc cmp*(x, y: Rational): int =
|
||||
proc cmp*(x, y: Rational): int {.procvar.} =
|
||||
## Compares two rationals.
|
||||
(x - y).num
|
||||
|
||||
|
|
@ -205,6 +206,17 @@ proc abs*[T](x: Rational[T]): Rational[T] =
|
|||
result.num = abs x.num
|
||||
result.den = abs x.den
|
||||
|
||||
proc hash*[T](x: Rational[T]): THash =
|
||||
## Computes hash for rational `x`
|
||||
# reduce first so that hash(x) == hash(y) for x == y
|
||||
var copy = x
|
||||
reduce(copy)
|
||||
|
||||
var h: THash = 0
|
||||
h = h !& hash(copy.num)
|
||||
h = h !& hash(copy.den)
|
||||
result = !$h
|
||||
|
||||
when isMainModule:
|
||||
var
|
||||
z = Rational[int](num: 0, den: 1)
|
||||
|
|
@ -242,11 +254,13 @@ when isMainModule:
|
|||
assert( not(o > o) )
|
||||
assert( cmp(o, o) == 0 )
|
||||
assert( cmp(z, z) == 0 )
|
||||
assert( hash(o) == hash(o) )
|
||||
|
||||
assert( a == b )
|
||||
assert( a >= b )
|
||||
assert( not(b > a) )
|
||||
assert( cmp(a, b) == 0 )
|
||||
assert( hash(a) == hash(b) )
|
||||
|
||||
var x = 1//3
|
||||
|
||||
|
|
@ -270,6 +284,6 @@ when isMainModule:
|
|||
y /= 9
|
||||
assert( y == 13//27 )
|
||||
|
||||
assert toRational[int, int](5) == 5//1
|
||||
assert toRational(5) == 5//1
|
||||
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
||||
assert toInt(z) == 0
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ export
|
|||
SO_KEEPALIVE, SO_OOBINLINE, SO_REUSEADDR,
|
||||
MSG_PEEK
|
||||
|
||||
when defined(macosx):
|
||||
export SO_NOSIGPIPE
|
||||
|
||||
type
|
||||
Port* = distinct uint16 ## port type
|
||||
|
||||
|
|
@ -428,10 +431,6 @@ proc selectWrite*(writefds: var seq[SocketHandle],
|
|||
|
||||
pruneSocketSet(writefds, (wr))
|
||||
|
||||
# We ignore signal SIGPIPE on Darwin
|
||||
when defined(macosx):
|
||||
signal(SIGPIPE, SIG_IGN)
|
||||
|
||||
when defined(Windows):
|
||||
var wsa: WSAData
|
||||
if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
|
|||
## the rope's length
|
||||
if a == nil: result = 0
|
||||
else: result = a.length
|
||||
|
||||
|
||||
proc newRope(): Rope = new(result)
|
||||
proc newRope(data: string): Rope =
|
||||
proc newRope(data: string): Rope =
|
||||
new(result)
|
||||
result.length = len(data)
|
||||
result.data = data
|
||||
|
|
@ -65,18 +65,18 @@ var
|
|||
|
||||
when countCacheMisses:
|
||||
var misses, hits: int
|
||||
|
||||
proc splay(s: string, tree: Rope, cmpres: var int): Rope =
|
||||
|
||||
proc splay(s: string, tree: Rope, cmpres: var int): Rope =
|
||||
var c: int
|
||||
var t = tree
|
||||
N.left = nil
|
||||
N.right = nil # reset to nil
|
||||
var le = N
|
||||
var r = N
|
||||
while true:
|
||||
while true:
|
||||
c = cmp(s, t.data)
|
||||
if c < 0:
|
||||
if (t.left != nil) and (s < t.left.data):
|
||||
if c < 0:
|
||||
if (t.left != nil) and (s < t.left.data):
|
||||
var y = t.left
|
||||
t.left = y.right
|
||||
y.right = t
|
||||
|
|
@ -85,8 +85,8 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
|
|||
r.left = t
|
||||
r = t
|
||||
t = t.left
|
||||
elif c > 0:
|
||||
if (t.right != nil) and (s > t.right.data):
|
||||
elif c > 0:
|
||||
if (t.right != nil) and (s > t.right.data):
|
||||
var y = t.right
|
||||
t.right = y.left
|
||||
y.left = t
|
||||
|
|
@ -95,8 +95,8 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
|
|||
le.right = t
|
||||
le = t
|
||||
t = t.right
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
cmpres = c
|
||||
le.right = t.left
|
||||
r.left = t.right
|
||||
|
|
@ -104,50 +104,50 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
|
|||
t.right = N.left
|
||||
result = t
|
||||
|
||||
proc insertInCache(s: string, tree: Rope): Rope =
|
||||
proc insertInCache(s: string, tree: Rope): Rope =
|
||||
var t = tree
|
||||
if t == nil:
|
||||
if t == nil:
|
||||
result = newRope(s)
|
||||
when countCacheMisses: inc(misses)
|
||||
return
|
||||
var cmp: int
|
||||
t = splay(s, t, cmp)
|
||||
if cmp == 0:
|
||||
if cmp == 0:
|
||||
# We get here if it's already in the Tree
|
||||
# Don't add it again
|
||||
result = t
|
||||
when countCacheMisses: inc(hits)
|
||||
else:
|
||||
else:
|
||||
when countCacheMisses: inc(misses)
|
||||
result = newRope(s)
|
||||
if cmp < 0:
|
||||
if cmp < 0:
|
||||
result.left = t.left
|
||||
result.right = t
|
||||
t.left = nil
|
||||
else:
|
||||
else:
|
||||
# i > t.item:
|
||||
result.right = t.right
|
||||
result.left = t
|
||||
t.right = nil
|
||||
|
||||
proc rope*(s: string): Rope {.rtl, extern: "nro$1Str".} =
|
||||
## Converts a string to a rope.
|
||||
if s.len == 0:
|
||||
## Converts a string to a rope.
|
||||
if s.len == 0:
|
||||
result = nil
|
||||
elif cacheEnabled:
|
||||
elif cacheEnabled:
|
||||
result = insertInCache(s, cache)
|
||||
cache = result
|
||||
else:
|
||||
else:
|
||||
result = newRope(s)
|
||||
|
||||
proc rope*(i: BiggestInt): Rope {.rtl, extern: "nro$1BiggestInt".} =
|
||||
## Converts an int to a rope.
|
||||
|
||||
proc rope*(i: BiggestInt): Rope {.rtl, extern: "nro$1BiggestInt".} =
|
||||
## Converts an int to a rope.
|
||||
result = rope($i)
|
||||
|
||||
proc rope*(f: BiggestFloat): Rope {.rtl, extern: "nro$1BiggestFloat".} =
|
||||
## Converts a float to a rope.
|
||||
## Converts a float to a rope.
|
||||
result = rope($f)
|
||||
|
||||
|
||||
proc enableCache*() {.rtl, extern: "nro$1".} =
|
||||
## Enables the caching of leaves. This reduces the memory footprint at
|
||||
## the cost of runtime efficiency.
|
||||
|
|
@ -160,9 +160,9 @@ proc disableCache*() {.rtl, extern: "nro$1".} =
|
|||
|
||||
proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
|
||||
## the concatenation operator for ropes.
|
||||
if a == nil:
|
||||
if a == nil:
|
||||
result = b
|
||||
elif b == nil:
|
||||
elif b == nil:
|
||||
result = a
|
||||
else:
|
||||
result = newRope()
|
||||
|
|
@ -177,16 +177,16 @@ proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
|
|||
else:
|
||||
result.left = a
|
||||
result.right = b
|
||||
|
||||
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
||||
|
||||
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
||||
## the concatenation operator for ropes.
|
||||
result = a & rope(b)
|
||||
|
||||
proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} =
|
||||
|
||||
proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} =
|
||||
## the concatenation operator for ropes.
|
||||
result = rope(a) & b
|
||||
|
||||
proc `&`*(a: openArray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} =
|
||||
|
||||
proc `&`*(a: openArray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} =
|
||||
## the concatenation operator for an openarray of ropes.
|
||||
for i in countup(0, high(a)): result = result & a[i]
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ iterator leaves*(r: Rope): string =
|
|||
## iterates over any leaf string in the rope `r`.
|
||||
if r != nil:
|
||||
var stack = @[r]
|
||||
while stack.len > 0:
|
||||
while stack.len > 0:
|
||||
var it = stack.pop
|
||||
while isConc(it):
|
||||
stack.add(it.right)
|
||||
|
|
@ -227,7 +227,7 @@ iterator leaves*(r: Rope): string =
|
|||
assert(it != nil)
|
||||
assert(it.data != nil)
|
||||
yield it.data
|
||||
|
||||
|
||||
iterator items*(r: Rope): char =
|
||||
## iterates over any character in the rope `r`.
|
||||
for s in leaves(r):
|
||||
|
|
@ -237,7 +237,7 @@ proc write*(f: File, r: Rope) {.rtl, extern: "nro$1".} =
|
|||
## writes a rope to a file.
|
||||
for s in leaves(r): write(f, s)
|
||||
|
||||
proc `$`*(r: Rope): string {.rtl, extern: "nroToString".}=
|
||||
proc `$`*(r: Rope): string {.rtl, extern: "nroToString".}=
|
||||
## converts a rope back to a string.
|
||||
result = newString(r.len)
|
||||
setLen(result, 0)
|
||||
|
|
@ -251,25 +251,25 @@ when false:
|
|||
new(result)
|
||||
result.length = -idx
|
||||
|
||||
proc compileFrmt(frmt: string): Rope =
|
||||
proc compileFrmt(frmt: string): Rope =
|
||||
var i = 0
|
||||
var length = len(frmt)
|
||||
result = nil
|
||||
var num = 0
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
inc(i)
|
||||
case frmt[i]
|
||||
of '$':
|
||||
of '$':
|
||||
add(result, "$")
|
||||
inc(i)
|
||||
of '#':
|
||||
of '#':
|
||||
inc(i)
|
||||
add(result, compiledArg(num+1))
|
||||
inc(num)
|
||||
of '0'..'9':
|
||||
of '0'..'9':
|
||||
var j = 0
|
||||
while true:
|
||||
while true:
|
||||
j = j * 10 + ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
if frmt[i] notin {'0'..'9'}: break
|
||||
|
|
@ -285,13 +285,13 @@ when false:
|
|||
add(s, compiledArg(j))
|
||||
else: raise newException(EInvalidValue, "invalid format string")
|
||||
var start = i
|
||||
while i < length:
|
||||
while i < length:
|
||||
if frmt[i] != '$': inc(i)
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
add(result, substr(frmt, start, i-1))
|
||||
|
||||
proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
|
||||
|
||||
proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
|
||||
rtl, extern: "nroFormat".} =
|
||||
## `%` substitution operator for ropes. Does not support the ``$identifier``
|
||||
## nor ``${identifier}`` notations.
|
||||
|
|
@ -299,23 +299,23 @@ proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
|
|||
var length = len(frmt)
|
||||
result = nil
|
||||
var num = 0
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
inc(i)
|
||||
case frmt[i]
|
||||
of '$':
|
||||
of '$':
|
||||
add(result, "$")
|
||||
inc(i)
|
||||
of '#':
|
||||
of '#':
|
||||
inc(i)
|
||||
add(result, args[num])
|
||||
inc(num)
|
||||
of '0'..'9':
|
||||
of '0'..'9':
|
||||
var j = 0
|
||||
while true:
|
||||
while true:
|
||||
j = j * 10 + ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
if frmt[i] notin {'0'..'9'}: break
|
||||
if frmt[i] notin {'0'..'9'}: break
|
||||
add(result, args[j-1])
|
||||
of '{':
|
||||
inc(i)
|
||||
|
|
@ -325,13 +325,14 @@ proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
|
|||
inc(i)
|
||||
if frmt[i] == '}': inc(i)
|
||||
else: raise newException(ValueError, "invalid format string")
|
||||
|
||||
add(result, args[j-1])
|
||||
else: raise newException(ValueError, "invalid format string")
|
||||
var start = i
|
||||
while i < length:
|
||||
while i < length:
|
||||
if frmt[i] != '$': inc(i)
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
add(result, substr(frmt, start, i - 1))
|
||||
|
||||
proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
|
||||
|
|
@ -339,29 +340,46 @@ proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
|
|||
## shortcut for ``add(c, frmt % args)``.
|
||||
add(c, frmt % args)
|
||||
|
||||
const
|
||||
bufSize = 1024 # 1 KB is reasonable
|
||||
|
||||
proc equalsFile*(r: Rope, f: File): bool {.rtl, extern: "nro$1File".} =
|
||||
## returns true if the contents of the file `f` equal `r`.
|
||||
var bufSize = 1024 # reasonable start value
|
||||
var buf = alloc(bufSize)
|
||||
for s in leaves(r):
|
||||
if s.len > bufSize:
|
||||
bufSize = max(bufSize * 2, s.len)
|
||||
buf = realloc(buf, bufSize)
|
||||
var readBytes = readBuffer(f, buf, s.len)
|
||||
result = readBytes == s.len and equalMem(buf, cstring(s), s.len)
|
||||
if not result: break
|
||||
if result:
|
||||
result = readBuffer(f, buf, 1) == 0 # really at the end of file?
|
||||
dealloc(buf)
|
||||
var
|
||||
buf: array[bufSize, char]
|
||||
bpos = buf.len
|
||||
blen = buf.len
|
||||
|
||||
proc equalsFile*(r: Rope, f: string): bool {.rtl, extern: "nro$1Str".} =
|
||||
for s in leaves(r):
|
||||
var spos = 0
|
||||
let slen = s.len
|
||||
while spos < slen:
|
||||
if bpos == blen:
|
||||
# Read more data
|
||||
bpos = 0
|
||||
blen = readBuffer(f, addr(buf[0]), buf.len)
|
||||
if blen == 0: # no more data in file
|
||||
result = false
|
||||
return
|
||||
let n = min(blen - bpos, slen - spos)
|
||||
# TODO There's gotta be a better way of comparing here...
|
||||
if not equalMem(addr(buf[bpos]),
|
||||
cast[pointer](cast[int](cstring(s))+spos), n):
|
||||
result = false
|
||||
return
|
||||
spos += n
|
||||
bpos += n
|
||||
|
||||
result = readBuffer(f, addr(buf[0]), 1) == 0 # check that we've read all
|
||||
|
||||
proc equalsFile*(r: Rope, filename: string): bool {.rtl, extern: "nro$1Str".} =
|
||||
## returns true if the contents of the file `f` equal `r`. If `f` does not
|
||||
## exist, false is returned.
|
||||
var bin: File
|
||||
result = open(bin, f)
|
||||
var f: File
|
||||
result = open(f, filename)
|
||||
if result:
|
||||
result = equalsFile(r, bin)
|
||||
close(bin)
|
||||
result = equalsFile(r, f)
|
||||
close(f)
|
||||
|
||||
new(N) # init dummy node for splay algorithm
|
||||
|
||||
|
|
|
|||
|
|
@ -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
131
lib/system.nim
131
lib/system.nim
|
|
@ -76,6 +76,10 @@ type
|
|||
void* {.magic: "VoidType".} ## meta type to denote the absence of any type
|
||||
auto* = expr
|
||||
any* = distinct auto
|
||||
untyped* {.magic: Expr.} ## meta type to denote an expression that
|
||||
## is not resolved (for templates)
|
||||
typed* {.magic: Stmt.} ## meta type to denote an expression that
|
||||
## is resolved (for templates)
|
||||
|
||||
SomeSignedInt* = int|int8|int16|int32|int64
|
||||
## type class matching all signed integer types
|
||||
|
|
@ -173,12 +177,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 +511,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 +551,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 +569,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
|
||||
|
|
@ -704,6 +708,7 @@ proc `div` *(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
|
|||
proc `div` *(x, y: int64): int64 {.magic: "DivI64", noSideEffect.}
|
||||
## computes the integer division. This is roughly the same as
|
||||
## ``floor(x/y)``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## 1 div 2 == 0
|
||||
## 2 div 2 == 1
|
||||
|
|
@ -723,6 +728,7 @@ proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
|
|||
proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
|
||||
proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.}
|
||||
## computes the `shift right` operation of `x` and `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## 0b0001_0000'i8 shr 2 == 0b0100_0000'i8
|
||||
## 0b1000_0000'i8 shr 2 == 0b0000_0000'i8
|
||||
|
|
@ -937,7 +943,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.
|
||||
|
|
@ -945,14 +951,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
|
||||
|
|
@ -960,7 +966,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
|
||||
|
|
@ -1150,21 +1156,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)
|
||||
|
|
@ -1310,19 +1316,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
|
||||
|
|
@ -1330,7 +1336,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
|
||||
|
|
@ -1338,7 +1344,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
|
||||
|
|
@ -1353,7 +1359,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
|
||||
|
|
@ -1368,8 +1374,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**
|
||||
|
|
@ -1396,7 +1402,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
|
||||
|
|
@ -1410,7 +1416,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)``.
|
||||
|
|
@ -1423,8 +1429,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**
|
||||
|
|
@ -2487,37 +2493,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
|
||||
|
|
@ -2539,7 +2545,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)
|
||||
|
|
@ -2809,14 +2815,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"
|
||||
|
|
@ -3028,8 +3034,8 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
|
|||
## result = a[pos]
|
||||
##
|
||||
## when isMainModule:
|
||||
## testException(EInvalidIndex, tester(30))
|
||||
## testException(EInvalidIndex, tester(1))
|
||||
## testException(IndexError, tester(30))
|
||||
## testException(IndexError, tester(1))
|
||||
## # --> Test failure at example.nim:20 with 'tester(1)'
|
||||
|
||||
template currentSourcePath*: string = instantiationInfo(-1, true).filename
|
||||
|
|
@ -3038,13 +3044,12 @@ template currentSourcePath*: string = instantiationInfo(-1, true).filename
|
|||
proc raiseAssert*(msg: string) {.noinline.} =
|
||||
sysFatal(AssertionError, msg)
|
||||
|
||||
when true:
|
||||
proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
|
||||
# trick the compiler to not list ``EAssertionFailed`` when called
|
||||
# by ``assert``.
|
||||
type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
|
||||
tags: [].}
|
||||
THide(raiseAssert)(msg)
|
||||
proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
|
||||
# trick the compiler to not list ``AssertionError`` when called
|
||||
# by ``assert``.
|
||||
type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
|
||||
tags: [].}
|
||||
THide(raiseAssert)(msg)
|
||||
|
||||
template assert*(cond: bool, msg = "") =
|
||||
## Raises ``AssertionError`` with `msg` if `cond` is false. Note
|
||||
|
|
@ -3109,24 +3114,18 @@ when not defined(nimhygiene):
|
|||
|
||||
template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
|
||||
## Sets an assertion failure handler that will intercept any assert
|
||||
## statements following `onFailedAssert` in the current lexical scope.
|
||||
## Can be defined multiple times in a single function.
|
||||
## statements following `onFailedAssert` in the current module scope.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## # module-wide policy to change the failed assert
|
||||
## # exception type in order to include a lineinfo
|
||||
## onFailedAssert(msg):
|
||||
## var e = new(TMyError)
|
||||
## e.msg = msg
|
||||
## e.lineinfo = instantiationInfo(-2)
|
||||
## raise e
|
||||
##
|
||||
## proc example(x: int): TErrorCode =
|
||||
## onFailedAssert(msg):
|
||||
## log msg
|
||||
## return E_FAIL
|
||||
##
|
||||
## assert(...)
|
||||
##
|
||||
## onFailedAssert(msg):
|
||||
## raise newException(EMyException, msg)
|
||||
##
|
||||
## assert(...)
|
||||
##
|
||||
template failedAssertImpl(msgIMPL: string): stmt {.dirty, immediate.} =
|
||||
template failedAssertImpl(msgIMPL: string): stmt {.dirty.} =
|
||||
let msg = msgIMPL
|
||||
code
|
||||
|
||||
|
|
@ -3162,7 +3161,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
|
||||
|
|
@ -539,16 +539,16 @@ proc allocInv(a: TMemRegion): bool =
|
|||
|
||||
proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
||||
sysAssert(allocInv(a), "rawAlloc: begin")
|
||||
sysAssert(roundup(65, 8) == 72, "rawAlloc 1")
|
||||
sysAssert requestedSize >= sizeof(TFreeCell), "rawAlloc 2"
|
||||
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
|
||||
sysAssert(requestedSize >= sizeof(TFreeCell), "rawAlloc: requested size too small")
|
||||
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,11 +26,30 @@ 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: [].}
|
||||
|
||||
when defined(posix):
|
||||
proc getc_unlocked(stream: File): cint {.importc: "getc_unlocked",
|
||||
header: "<stdio.h>", tags: [ReadIOEffect].}
|
||||
|
||||
proc flockfile(stream: File) {.importc: "flockfile", header: "<stdio.h>",
|
||||
tags: [ReadIOEffect].}
|
||||
|
||||
proc funlockfile(stream: File) {.importc: "funlockfile", header: "<stdio.h>",
|
||||
tags: [ReadIOEffect].}
|
||||
elif false:
|
||||
# doesn't work on Windows yet:
|
||||
proc getc_unlocked(stream: File): cint {.importc: "_fgetc_nolock",
|
||||
header: "<stdio.h>", tags: [ReadIOEffect].}
|
||||
|
||||
proc flockfile(stream: File) {.importc: "_lock_file", header: "<stdio.h>",
|
||||
tags: [ReadIOEffect].}
|
||||
|
||||
proc funlockfile(stream: File) {.importc: "_unlock_file", header: "<stdio.h>",
|
||||
tags: [ReadIOEffect].}
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: pointer, size, n: int, f: File): int {.
|
||||
|
|
@ -67,39 +86,57 @@ const
|
|||
proc raiseEIO(msg: string) {.noinline, noreturn.} =
|
||||
sysFatal(IOError, msg)
|
||||
|
||||
proc readLine(f: File, line: var TaintedString): bool =
|
||||
# of course this could be optimized a bit; but IO is slow anyway...
|
||||
# and it was difficult to get this CORRECT with Ansi C's methods
|
||||
setLen(line.string, 0) # reuse the buffer!
|
||||
while true:
|
||||
var c = fgetc(f)
|
||||
if c < 0'i32:
|
||||
if line.len > 0: break
|
||||
else: return false
|
||||
if c == 10'i32: break # LF
|
||||
if c == 13'i32: # CR
|
||||
c = fgetc(f) # is the next char LF?
|
||||
if c != 10'i32: ungetc(c, f) # no, put the character back
|
||||
break
|
||||
add line.string, chr(int(c))
|
||||
result = true
|
||||
when declared(getc_unlocked):
|
||||
proc readLine(f: File, line: var TaintedString): bool =
|
||||
setLen(line.string, 0) # reuse the buffer!
|
||||
flockfile(f)
|
||||
while true:
|
||||
var c = getc_unlocked(f)
|
||||
if c < 0'i32:
|
||||
if line.len > 0: break
|
||||
else: return false
|
||||
if c == 10'i32: break # LF
|
||||
if c == 13'i32: # CR
|
||||
c = getc_unlocked(f) # is the next char LF?
|
||||
if c != 10'i32: ungetc(c, f) # no, put the character back
|
||||
break
|
||||
add line.string, chr(int(c))
|
||||
result = true
|
||||
funlockfile(f)
|
||||
else:
|
||||
proc readLine(f: File, line: var TaintedString): bool =
|
||||
# of course this could be optimized a bit; but IO is slow anyway...
|
||||
# and it was difficult to get this CORRECT with Ansi C's methods
|
||||
setLen(line.string, 0) # reuse the buffer!
|
||||
while true:
|
||||
var c = fgetc(f)
|
||||
if c < 0'i32:
|
||||
if line.len > 0: break
|
||||
else: return false
|
||||
if c == 10'i32: break # LF
|
||||
if c == 13'i32: # CR
|
||||
c = fgetc(f) # is the next char LF?
|
||||
if c != 10'i32: ungetc(c, f) # no, put the character back
|
||||
break
|
||||
add line.string, chr(int(c))
|
||||
result = true
|
||||
|
||||
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 +147,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 +160,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 +178,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 +187,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 +266,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 +280,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) =
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
## Unicode version.
|
||||
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
{.push gcsafe.}
|
||||
type
|
||||
WideChar* = uint16
|
||||
PWideChar* = ptr uint16
|
||||
|
|
@ -23481,7 +23481,7 @@ proc ListView_EnsureVisible(hwndLV: HWND, i, fPartialOK: int32): LRESULT =
|
|||
MAKELPARAM(fPartialOK, 0))
|
||||
|
||||
proc ListView_FindItem(wnd: HWND, iStart: int32, lvfi: var LV_FINDINFO): int32 =
|
||||
result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart),
|
||||
result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart),
|
||||
cast[LPARAM](addr(lvfi))).int32
|
||||
|
||||
proc ListView_GetBkColor(wnd: HWND): LRESULT =
|
||||
|
|
@ -23615,9 +23615,9 @@ proc ListView_SetTextBkColor(wnd: HWND, clrTextBk: COLORREF): LRESULT =
|
|||
proc ListView_SetTextColor(wnd: HWND, clrText: COLORREF): LRESULT =
|
||||
result = SendMessage(wnd, LVM_SETTEXTCOLOR, 0, LPARAM(clrText))
|
||||
|
||||
proc ListView_SortItems(hwndLV: HWND, pfnCompare: PFNLVCOMPARE,
|
||||
proc ListView_SortItems(hwndLV: HWND, pfnCompare: PFNLVCOMPARE,
|
||||
lPrm: LPARAM): LRESULT =
|
||||
result = SendMessage(hwndLV, LVM_SORTITEMS, WPARAM(lPrm),
|
||||
result = SendMessage(hwndLV, LVM_SORTITEMS, WPARAM(lPrm),
|
||||
cast[LPARAM](pfnCompare))
|
||||
|
||||
proc ListView_Update(hwndLV: HWND, i: int32): LRESULT =
|
||||
|
|
@ -23924,3 +23924,5 @@ proc LOCALE_NEUTRAL(): DWORD =
|
|||
|
||||
proc LOCALE_INVARIANT(): DWORD =
|
||||
result = MAKELCID(MAKELANGID(toU16(LANG_INVARIANT), SUBLANG_NEUTRAL), SORT_DEFAULT)
|
||||
|
||||
{.pop.}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#
|
||||
# Binding for the IUP GUI toolkit
|
||||
# (c) 2012 Andreas Rumpf
|
||||
# (c) 2012 Andreas Rumpf
|
||||
# C header files translated by hand
|
||||
# Licence of IUP follows:
|
||||
|
||||
|
||||
# ****************************************************************************
|
||||
# Copyright (C) 1994-2009 Tecgraf, PUC-Rio.
|
||||
#
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
|
|
@ -30,12 +30,12 @@
|
|||
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
when defined(windows):
|
||||
const dllname = "iup(30|27|26|25|24).dll"
|
||||
when defined(windows):
|
||||
const dllname = "iup(|30|27|26|25|24).dll"
|
||||
elif defined(macosx):
|
||||
const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).dylib"
|
||||
else:
|
||||
const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).so.1"
|
||||
const dllname = "libiup(|3.0|2.7|2.6|2.5|2.4).dylib"
|
||||
else:
|
||||
const dllname = "libiup(|3.0|2.7|2.6|2.5|2.4).so(|.1)"
|
||||
|
||||
const
|
||||
IUP_NAME* = "IUP - Portable User Interface"
|
||||
|
|
@ -67,8 +67,8 @@ proc alarm*(title, msg, b1, b2, b3: cstring): cint {.
|
|||
importc: "IupAlarm", dynlib: dllname, cdecl.}
|
||||
proc scanf*(format: cstring): cint {.
|
||||
importc: "IupScanf", dynlib: dllname, cdecl, varargs.}
|
||||
proc listDialog*(theType: cint, title: cstring, size: cint,
|
||||
list: cstringArray, op, maxCol, maxLin: cint,
|
||||
proc listDialog*(theType: cint, title: cstring, size: cint,
|
||||
list: cstringArray, op, maxCol, maxLin: cint,
|
||||
marks: ptr cint): cint {.
|
||||
importc: "IupListDialog", dynlib: dllname, cdecl.}
|
||||
proc getText*(title, text: cstring): cint {.
|
||||
|
|
@ -77,14 +77,14 @@ proc getColor*(x, y: cint, r, g, b: var byte): cint {.
|
|||
importc: "IupGetColor", dynlib: dllname, cdecl.}
|
||||
|
||||
type
|
||||
Iparamcb* = proc (dialog: PIhandle, paramIndex: cint,
|
||||
Iparamcb* = proc (dialog: PIhandle, paramIndex: cint,
|
||||
userData: pointer): cint {.cdecl.}
|
||||
|
||||
proc getParam*(title: cstring, action: Iparamcb, userData: pointer,
|
||||
proc getParam*(title: cstring, action: Iparamcb, userData: pointer,
|
||||
format: cstring): cint {.
|
||||
importc: "IupGetParam", cdecl, varargs, dynlib: dllname.}
|
||||
proc getParamv*(title: cstring, action: Iparamcb, userData: pointer,
|
||||
format: cstring, paramCount, paramExtra: cint,
|
||||
proc getParamv*(title: cstring, action: Iparamcb, userData: pointer,
|
||||
format: cstring, paramCount, paramExtra: cint,
|
||||
paramData: pointer): cint {.
|
||||
importc: "IupGetParamv", cdecl, dynlib: dllname.}
|
||||
|
||||
|
|
@ -96,11 +96,11 @@ proc open*(argc: ptr cint, argv: ptr cstringArray): cint {.
|
|||
proc close*() {.importc: "IupClose", cdecl, dynlib: dllname.}
|
||||
proc imageLibOpen*() {.importc: "IupImageLibOpen", cdecl, dynlib: dllname.}
|
||||
|
||||
proc mainLoop*(): cint {.importc: "IupMainLoop", cdecl, dynlib: dllname,
|
||||
proc mainLoop*(): cint {.importc: "IupMainLoop", cdecl, dynlib: dllname,
|
||||
discardable.}
|
||||
proc loopStep*(): cint {.importc: "IupLoopStep", cdecl, dynlib: dllname,
|
||||
discardable.}
|
||||
proc mainLoopLevel*(): cint {.importc: "IupMainLoopLevel", cdecl,
|
||||
proc mainLoopLevel*(): cint {.importc: "IupMainLoopLevel", cdecl,
|
||||
dynlib: dllname, discardable.}
|
||||
proc flush*() {.importc: "IupFlush", cdecl, dynlib: dllname.}
|
||||
proc exitLoop*() {.importc: "IupExitLoop", cdecl, dynlib: dllname.}
|
||||
|
|
@ -204,7 +204,7 @@ proc getCallback*(ih: PIhandle, name: cstring): Icallback {.
|
|||
importc: "IupGetCallback", cdecl, dynlib: dllname.}
|
||||
proc setCallback*(ih: PIhandle, name: cstring, fn: Icallback): Icallback {.
|
||||
importc: "IupSetCallback", cdecl, dynlib: dllname, discardable.}
|
||||
|
||||
|
||||
proc setCallbacks*(ih: PIhandle, name: cstring, fn: Icallback): PIhandle {.
|
||||
importc: "IupSetCallbacks", cdecl, dynlib: dllname, varargs, discardable.}
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ proc getClassName*(ih: PIhandle): cstring {.
|
|||
importc: "IupGetClassName", cdecl, dynlib: dllname.}
|
||||
proc getClassType*(ih: PIhandle): cstring {.
|
||||
importc: "IupGetClassType", cdecl, dynlib: dllname.}
|
||||
proc getClassAttributes*(classname: cstring, names: cstringArray,
|
||||
proc getClassAttributes*(classname: cstring, names: cstringArray,
|
||||
n: cint): cint {.
|
||||
importc: "IupGetClassAttributes", cdecl, dynlib: dllname.}
|
||||
proc saveClassAttributes*(ih: PIhandle) {.
|
||||
|
|
@ -378,12 +378,12 @@ const
|
|||
IUP_CONTINUE* = cint(-4)
|
||||
|
||||
# IupPopup and IupShowXY Parameter Values
|
||||
IUP_CENTER* = cint(0xFFFF)
|
||||
IUP_LEFT* = cint(0xFFFE)
|
||||
IUP_RIGHT* = cint(0xFFFD)
|
||||
IUP_MOUSEPOS* = cint(0xFFFC)
|
||||
IUP_CURRENT* = cint(0xFFFB)
|
||||
IUP_CENTERPARENT* = cint(0xFFFA)
|
||||
IUP_CENTER* = cint(0xFFFF)
|
||||
IUP_LEFT* = cint(0xFFFE)
|
||||
IUP_RIGHT* = cint(0xFFFD)
|
||||
IUP_MOUSEPOS* = cint(0xFFFC)
|
||||
IUP_CURRENT* = cint(0xFFFB)
|
||||
IUP_CENTERPARENT* = cint(0xFFFA)
|
||||
IUP_TOP* = IUP_LEFT
|
||||
IUP_BOTTOM* = IUP_RIGHT
|
||||
|
||||
|
|
@ -397,10 +397,10 @@ const
|
|||
# SCROLL_CB Callback Values
|
||||
IUP_SBUP* = cint(0)
|
||||
IUP_SBDN* = cint(1)
|
||||
IUP_SBPGUP* = cint(2)
|
||||
IUP_SBPGUP* = cint(2)
|
||||
IUP_SBPGDN* = cint(3)
|
||||
IUP_SBPOSV* = cint(4)
|
||||
IUP_SBDRAGV* = cint(5)
|
||||
IUP_SBDRAGV* = cint(5)
|
||||
IUP_SBLEFT* = cint(6)
|
||||
IUP_SBRIGHT* = cint(7)
|
||||
IUP_SBPGLEFT* = cint(8)
|
||||
|
|
@ -433,12 +433,12 @@ const
|
|||
IUP_MASK_EFLOAT* = "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?"
|
||||
IUP_MASK_INT* = "[+/-]?/d+"
|
||||
IUP_MASK_UINT* = "/d+"
|
||||
|
||||
|
||||
# from 32 to 126, all character sets are equal,
|
||||
# the key code i the same as the character code.
|
||||
const
|
||||
K_SP* = cint(ord(' '))
|
||||
K_exclam* = cint(ord('!'))
|
||||
K_exclam* = cint(ord('!'))
|
||||
K_quotedbl* = cint(ord('\"'))
|
||||
K_numbersign* = cint(ord('#'))
|
||||
K_dollar* = cint(ord('$'))
|
||||
|
|
@ -467,51 +467,51 @@ const
|
|||
K_semicolon* = cint(ord(';'))
|
||||
K_less* = cint(ord('<'))
|
||||
K_equal* = cint(ord('='))
|
||||
K_greater* = cint(ord('>'))
|
||||
K_question* = cint(ord('?'))
|
||||
K_at* = cint(ord('@'))
|
||||
K_upperA* = cint(ord('A'))
|
||||
K_upperB* = cint(ord('B'))
|
||||
K_upperC* = cint(ord('C'))
|
||||
K_upperD* = cint(ord('D'))
|
||||
K_upperE* = cint(ord('E'))
|
||||
K_upperF* = cint(ord('F'))
|
||||
K_upperG* = cint(ord('G'))
|
||||
K_upperH* = cint(ord('H'))
|
||||
K_upperI* = cint(ord('I'))
|
||||
K_upperJ* = cint(ord('J'))
|
||||
K_upperK* = cint(ord('K'))
|
||||
K_upperL* = cint(ord('L'))
|
||||
K_upperM* = cint(ord('M'))
|
||||
K_upperN* = cint(ord('N'))
|
||||
K_upperO* = cint(ord('O'))
|
||||
K_upperP* = cint(ord('P'))
|
||||
K_upperQ* = cint(ord('Q'))
|
||||
K_upperR* = cint(ord('R'))
|
||||
K_upperS* = cint(ord('S'))
|
||||
K_upperT* = cint(ord('T'))
|
||||
K_upperU* = cint(ord('U'))
|
||||
K_upperV* = cint(ord('V'))
|
||||
K_upperW* = cint(ord('W'))
|
||||
K_upperX* = cint(ord('X'))
|
||||
K_upperY* = cint(ord('Y'))
|
||||
K_upperZ* = cint(ord('Z'))
|
||||
K_bracketleft* = cint(ord('['))
|
||||
K_backslash* = cint(ord('\\'))
|
||||
K_bracketright* = cint(ord(']'))
|
||||
K_circum* = cint(ord('^'))
|
||||
K_underscore* = cint(ord('_'))
|
||||
K_grave* = cint(ord('`'))
|
||||
K_lowera* = cint(ord('a'))
|
||||
K_lowerb* = cint(ord('b'))
|
||||
K_lowerc* = cint(ord('c'))
|
||||
K_lowerd* = cint(ord('d'))
|
||||
K_lowere* = cint(ord('e'))
|
||||
K_lowerf* = cint(ord('f'))
|
||||
K_greater* = cint(ord('>'))
|
||||
K_question* = cint(ord('?'))
|
||||
K_at* = cint(ord('@'))
|
||||
K_upperA* = cint(ord('A'))
|
||||
K_upperB* = cint(ord('B'))
|
||||
K_upperC* = cint(ord('C'))
|
||||
K_upperD* = cint(ord('D'))
|
||||
K_upperE* = cint(ord('E'))
|
||||
K_upperF* = cint(ord('F'))
|
||||
K_upperG* = cint(ord('G'))
|
||||
K_upperH* = cint(ord('H'))
|
||||
K_upperI* = cint(ord('I'))
|
||||
K_upperJ* = cint(ord('J'))
|
||||
K_upperK* = cint(ord('K'))
|
||||
K_upperL* = cint(ord('L'))
|
||||
K_upperM* = cint(ord('M'))
|
||||
K_upperN* = cint(ord('N'))
|
||||
K_upperO* = cint(ord('O'))
|
||||
K_upperP* = cint(ord('P'))
|
||||
K_upperQ* = cint(ord('Q'))
|
||||
K_upperR* = cint(ord('R'))
|
||||
K_upperS* = cint(ord('S'))
|
||||
K_upperT* = cint(ord('T'))
|
||||
K_upperU* = cint(ord('U'))
|
||||
K_upperV* = cint(ord('V'))
|
||||
K_upperW* = cint(ord('W'))
|
||||
K_upperX* = cint(ord('X'))
|
||||
K_upperY* = cint(ord('Y'))
|
||||
K_upperZ* = cint(ord('Z'))
|
||||
K_bracketleft* = cint(ord('['))
|
||||
K_backslash* = cint(ord('\\'))
|
||||
K_bracketright* = cint(ord(']'))
|
||||
K_circum* = cint(ord('^'))
|
||||
K_underscore* = cint(ord('_'))
|
||||
K_grave* = cint(ord('`'))
|
||||
K_lowera* = cint(ord('a'))
|
||||
K_lowerb* = cint(ord('b'))
|
||||
K_lowerc* = cint(ord('c'))
|
||||
K_lowerd* = cint(ord('d'))
|
||||
K_lowere* = cint(ord('e'))
|
||||
K_lowerf* = cint(ord('f'))
|
||||
K_lowerg* = cint(ord('g'))
|
||||
K_lowerh* = cint(ord('h'))
|
||||
K_loweri* = cint(ord('i'))
|
||||
K_lowerj* = cint(ord('j'))
|
||||
K_lowerh* = cint(ord('h'))
|
||||
K_loweri* = cint(ord('i'))
|
||||
K_lowerj* = cint(ord('j'))
|
||||
K_lowerk* = cint(ord('k'))
|
||||
K_lowerl* = cint(ord('l'))
|
||||
K_lowerm* = cint(ord('m'))
|
||||
|
|
@ -553,19 +553,19 @@ proc isAltXkey*(c: cint): bool = return c > 768 and c < 1024
|
|||
proc isSysXkey*(c: cint): bool = return c > 1024 and c < 1280
|
||||
|
||||
proc iUPxCODE*(c: cint): cint = return c + cint(128) # Normal (must be above 128)
|
||||
proc iUPsxCODE*(c: cint): cint =
|
||||
proc iUPsxCODE*(c: cint): cint =
|
||||
return c + cint(256)
|
||||
# Shift (must have range to include the standard keys and the normal
|
||||
# Shift (must have range to include the standard keys and the normal
|
||||
# extended keys, so must be above 256
|
||||
|
||||
proc iUPcxCODE*(c: cint): cint = return c + cint(512) # Ctrl
|
||||
proc iUPmxCODE*(c: cint): cint = return c + cint(768) # Alt
|
||||
proc iUPyxCODE*(c: cint): cint = return c + cint(1024) # Sys (Win or Apple)
|
||||
proc iUPyxCODE*(c: cint): cint = return c + cint(1024) # Sys (Win or Apple)
|
||||
|
||||
const
|
||||
IUP_NUMMAXCODES* = 1280 ## 5*256=1280 Normal+Shift+Ctrl+Alt+Sys
|
||||
|
||||
K_HOME* = iUPxCODE(1)
|
||||
K_HOME* = iUPxCODE(1)
|
||||
K_UP* = iUPxCODE(2)
|
||||
K_PGUP* = iUPxCODE(3)
|
||||
K_LEFT* = iUPxCODE(4)
|
||||
|
|
@ -574,8 +574,8 @@ const
|
|||
K_END* = iUPxCODE(7)
|
||||
K_DOWN* = iUPxCODE(8)
|
||||
K_PGDN* = iUPxCODE(9)
|
||||
K_INS* = iUPxCODE(10)
|
||||
K_DEL* = iUPxCODE(11)
|
||||
K_INS* = iUPxCODE(10)
|
||||
K_DEL* = iUPxCODE(11)
|
||||
K_PAUSE* = iUPxCODE(12)
|
||||
K_ESC* = iUPxCODE(13)
|
||||
K_ccedilla* = iUPxCODE(14)
|
||||
|
|
@ -728,13 +728,13 @@ const
|
|||
K_yPrint* = iUPyxCODE(K_Print)
|
||||
K_yMenu* = iUPyxCODE(K_Menu)
|
||||
|
||||
K_sPlus* = iUPsxCODE(K_plus)
|
||||
K_sComma* = iUPsxCODE(K_comma)
|
||||
K_sMinus* = iUPsxCODE(K_minus)
|
||||
K_sPeriod* = iUPsxCODE(K_period)
|
||||
K_sSlash* = iUPsxCODE(K_slash)
|
||||
K_sPlus* = iUPsxCODE(K_plus)
|
||||
K_sComma* = iUPsxCODE(K_comma)
|
||||
K_sMinus* = iUPsxCODE(K_minus)
|
||||
K_sPeriod* = iUPsxCODE(K_period)
|
||||
K_sSlash* = iUPsxCODE(K_slash)
|
||||
K_sAsterisk* = iUPsxCODE(K_asterisk)
|
||||
|
||||
|
||||
K_cupperA* = iUPcxCODE(K_upperA)
|
||||
K_cupperB* = iUPcxCODE(K_upperB)
|
||||
K_cupperC* = iUPcxCODE(K_upperC)
|
||||
|
|
@ -767,16 +767,16 @@ const
|
|||
K_c4* = iUPcxCODE(K_4)
|
||||
K_c5* = iUPcxCODE(K_5)
|
||||
K_c6* = iUPcxCODE(K_6)
|
||||
K_c7* = iUPcxCODE(K_7)
|
||||
K_c8* = iUPcxCODE(K_8)
|
||||
K_c7* = iUPcxCODE(K_7)
|
||||
K_c8* = iUPcxCODE(K_8)
|
||||
K_c9* = iUPcxCODE(K_9)
|
||||
K_c0* = iUPcxCODE(K_0)
|
||||
K_cPlus* = iUPcxCODE(K_plus)
|
||||
K_cComma* = iUPcxCODE(K_comma)
|
||||
K_cMinus* = iUPcxCODE(K_minus)
|
||||
K_cPeriod* = iUPcxCODE(K_period)
|
||||
K_cSlash* = iUPcxCODE(K_slash)
|
||||
K_cSemicolon* = iUPcxCODE(K_semicolon)
|
||||
K_cPlus* = iUPcxCODE(K_plus)
|
||||
K_cComma* = iUPcxCODE(K_comma)
|
||||
K_cMinus* = iUPcxCODE(K_minus)
|
||||
K_cPeriod* = iUPcxCODE(K_period)
|
||||
K_cSlash* = iUPcxCODE(K_slash)
|
||||
K_cSemicolon* = iUPcxCODE(K_semicolon)
|
||||
K_cEqual* = iUPcxCODE(K_equal)
|
||||
K_cBracketleft* = iUPcxCODE(K_bracketleft)
|
||||
K_cBracketright* = iUPcxCODE(K_bracketright)
|
||||
|
|
@ -815,16 +815,16 @@ const
|
|||
K_m4* = iUPmxCODE(K_4)
|
||||
K_m5* = iUPmxCODE(K_5)
|
||||
K_m6* = iUPmxCODE(K_6)
|
||||
K_m7* = iUPmxCODE(K_7)
|
||||
K_m8* = iUPmxCODE(K_8)
|
||||
K_m7* = iUPmxCODE(K_7)
|
||||
K_m8* = iUPmxCODE(K_8)
|
||||
K_m9* = iUPmxCODE(K_9)
|
||||
K_m0* = iUPmxCODE(K_0)
|
||||
K_mPlus* = iUPmxCODE(K_plus)
|
||||
K_mComma* = iUPmxCODE(K_comma)
|
||||
K_mMinus* = iUPmxCODE(K_minus)
|
||||
K_mPeriod* = iUPmxCODE(K_period)
|
||||
K_mSlash* = iUPmxCODE(K_slash)
|
||||
K_mSemicolon* = iUPmxCODE(K_semicolon)
|
||||
K_mPlus* = iUPmxCODE(K_plus)
|
||||
K_mComma* = iUPmxCODE(K_comma)
|
||||
K_mMinus* = iUPmxCODE(K_minus)
|
||||
K_mPeriod* = iUPmxCODE(K_period)
|
||||
K_mSlash* = iUPmxCODE(K_slash)
|
||||
K_mSemicolon* = iUPmxCODE(K_semicolon)
|
||||
K_mEqual* = iUPmxCODE(K_equal)
|
||||
K_mBracketleft* = iUPmxCODE(K_bracketleft)
|
||||
K_mBracketright* = iUPmxCODE(K_bracketright)
|
||||
|
|
@ -863,16 +863,16 @@ const
|
|||
K_y4* = iUPyxCODE(K_4)
|
||||
K_y5* = iUPyxCODE(K_5)
|
||||
K_y6* = iUPyxCODE(K_6)
|
||||
K_y7* = iUPyxCODE(K_7)
|
||||
K_y8* = iUPyxCODE(K_8)
|
||||
K_y7* = iUPyxCODE(K_7)
|
||||
K_y8* = iUPyxCODE(K_8)
|
||||
K_y9* = iUPyxCODE(K_9)
|
||||
K_y0* = iUPyxCODE(K_0)
|
||||
K_yPlus* = iUPyxCODE(K_plus)
|
||||
K_yComma* = iUPyxCODE(K_comma)
|
||||
K_yMinus* = iUPyxCODE(K_minus)
|
||||
K_yPeriod* = iUPyxCODE(K_period)
|
||||
K_ySlash* = iUPyxCODE(K_slash)
|
||||
K_ySemicolon* = iUPyxCODE(K_semicolon)
|
||||
K_yMinus* = iUPyxCODE(K_minus)
|
||||
K_yPeriod* = iUPyxCODE(K_period)
|
||||
K_ySlash* = iUPyxCODE(K_slash)
|
||||
K_ySemicolon* = iUPyxCODE(K_semicolon)
|
||||
K_yEqual* = iUPyxCODE(K_equal)
|
||||
K_yBracketleft* = iUPyxCODE(K_bracketleft)
|
||||
K_yBracketright* = iUPyxCODE(K_bracketright)
|
||||
|
|
@ -893,11 +893,11 @@ proc dial*(theType: cstring): PIhandle {.cdecl, importc: "IupDial", dynlib: dlln
|
|||
proc matrix*(action: cstring): PIhandle {.cdecl, importc: "IupMatrix", dynlib: dllname.}
|
||||
|
||||
# IupMatrix utilities
|
||||
proc matSetAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
proc matSetAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
value: cstring) {.
|
||||
cdecl, importc: "IupMatSetAttribute", dynlib: dllname.}
|
||||
proc matStoreAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
value: cstring) {.cdecl,
|
||||
proc matStoreAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
value: cstring) {.cdecl,
|
||||
importc: "IupMatStoreAttribute", dynlib: dllname.}
|
||||
proc matGetAttribute*(ih: PIhandle, name: cstring, lin, col: cint): cstring {.
|
||||
cdecl, importc: "IupMatGetAttribute", dynlib: dllname.}
|
||||
|
|
@ -905,9 +905,9 @@ proc matGetInt*(ih: PIhandle, name: cstring, lin, col: cint): cint {.
|
|||
cdecl, importc: "IupMatGetInt", dynlib: dllname.}
|
||||
proc matGetFloat*(ih: PIhandle, name: cstring, lin, col: cint): cfloat {.
|
||||
cdecl, importc: "IupMatGetFloat", dynlib: dllname.}
|
||||
proc matSetfAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
format: cstring) {.cdecl,
|
||||
importc: "IupMatSetfAttribute",
|
||||
proc matSetfAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
|
||||
format: cstring) {.cdecl,
|
||||
importc: "IupMatSetfAttribute",
|
||||
dynlib: dllname, varargs.}
|
||||
|
||||
# Used by IupColorbar
|
||||
|
|
@ -931,10 +931,10 @@ proc pPlotAddStr*(ih: PIhandle, x: cstring, y: cfloat) {.
|
|||
proc pPlotEnd*(ih: PIhandle): cint {.
|
||||
cdecl, importc: "IupPPlotEnd", dynlib: dllname.}
|
||||
|
||||
proc pPlotInsertStr*(ih: PIhandle, index, sampleIndex: cint, x: cstring,
|
||||
y: cfloat) {.cdecl, importc: "IupPPlotInsertStr",
|
||||
proc pPlotInsertStr*(ih: PIhandle, index, sampleIndex: cint, x: cstring,
|
||||
y: cfloat) {.cdecl, importc: "IupPPlotInsertStr",
|
||||
dynlib: dllname.}
|
||||
proc pPlotInsert*(ih: PIhandle, index, sampleIndex: cint,
|
||||
proc pPlotInsert*(ih: PIhandle, index, sampleIndex: cint,
|
||||
x, y: cfloat) {.
|
||||
cdecl, importc: "IupPPlotInsert", dynlib: dllname.}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue