fixes merge conflict

This commit is contained in:
Andreas Rumpf 2018-05-26 19:09:02 +02:00
commit 12bd1c494c
16 changed files with 235 additions and 213 deletions

View file

@ -13,6 +13,7 @@
import
strutils
from algorithm import binarySearch
type
TokenClass* = enum
@ -365,32 +366,10 @@ proc generalStrLit(g: var GeneralTokenizer, position: int): int =
result = pos
proc isKeyword(x: openArray[string], y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmp(x[mid], y)
if c < 0:
a = mid + 1
elif c > 0:
b = mid - 1
else:
return mid
result = - 1
binarySearch(x, y)
proc isKeywordIgnoreCase(x: openArray[string], y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmpIgnoreCase(x[mid], y)
if c < 0:
a = mid + 1
elif c > 0:
b = mid - 1
else:
return mid
result = - 1
binarySearch(x, y, cmpIgnoreCase)
type
TokenizerFlag = enum

View file

@ -208,6 +208,7 @@ proc nextSplitPoint*(s: string, start: int): int =
dec(result) # last valid index
proc esc*(target: OutputTarget, s: string, splitAfter = -1): string =
## Escapes the HTML.
result = ""
if splitAfter >= 0:
var partLen = 0
@ -769,43 +770,45 @@ proc renderTocEntries*(d: var RstGenerator, j: var int, lvl: int,
result.add(tmp)
proc renderImage(d: PDoc, n: PRstNode, result: var string) =
template valid(s): bool =
s.len > 0 and allCharsInSet(s, {'.','/',':','%','_','\\','\128'..'\xFF'} +
Digits + Letters + WhiteSpace)
let
arg = getArgument(n)
isObject = arg.toLowerAscii().endsWith(".svg")
var
options = ""
content = ""
var s = getFieldValue(n, "scale")
if s.valid: dispA(d.target, options, if isObject: "" else: " scale=\"$1\"",
" scale=$1", [strip(s)])
s = getFieldValue(n, "height")
if s.valid: dispA(d.target, options, " height=\"$1\"", " height=$1", [strip(s)])
var s = esc(d.target, getFieldValue(n, "scale").strip())
if s.len > 0:
dispA(d.target, options, " scale=\"$1\"", " scale=$1", [s])
s = getFieldValue(n, "width")
if s.valid: dispA(d.target, options, " width=\"$1\"", " width=$1", [strip(s)])
s = esc(d.target, getFieldValue(n, "height").strip())
if s.len > 0:
dispA(d.target, options, " height=\"$1\"", " height=$1", [s])
s = getFieldValue(n, "alt")
if s.valid:
# <object> displays its content if it cannot render the image
if isObject: dispA(d.target, content, "$1", "", [strip(s)])
else: dispA(d.target, options, " alt=\"$1\"", "", [strip(s)])
s = esc(d.target, getFieldValue(n, "width").strip())
if s.len > 0:
dispA(d.target, options, " width=\"$1\"", " width=$1", [s])
s = getFieldValue(n, "align")
if s.valid: dispA(d.target, options, " align=\"$1\"", "", [strip(s)])
s = esc(d.target, getFieldValue(n, "alt").strip())
if s.len > 0:
dispA(d.target, options, " alt=\"$1\"", "", [s])
s = esc(d.target, getFieldValue(n, "align").strip())
if s.len > 0:
dispA(d.target, options, " align=\"$1\"", "", [s])
if options.len > 0: options = dispF(d.target, "$1", "[$1]", [options])
if arg.valid:
let htmlOut = if isObject:
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
else:
"<img src=\"$1\"$2 />"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[arg, options])
var htmlOut = ""
if arg.endsWith(".mp4") or arg.endsWith(".ogg") or
arg.endsWith(".webm"):
htmlOut = """
<video src="$1"$2 autoPlay='true' loop='true' muted='true'>
Sorry, your browser doesn't support embedded videos
</video>
"""
else:
htmlOut = "<img src=\"$1\"$2/>"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[esc(d.target, arg), options])
if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
proc renderSmiley(d: PDoc, n: PRstNode, result: var string) =
@ -881,7 +884,8 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
inc d.listingCounter
let id = $d.listingCounter
if not params.numberLines:
result = (d.config.getOrDefault"doc.listing_start" % [id, $params.lang],
result = (d.config.getOrDefault"doc.listing_start" %
[id, sourceLanguageToStr[params.lang]],
d.config.getOrDefault"doc.listing_end" % id)
return
@ -894,7 +898,8 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
line.inc
codeLines.dec
result.beginTable.add("</pre></td><td>" & (
d.config.getOrDefault"doc.listing_start" % [id, $params.lang]))
d.config.getOrDefault"doc.listing_start" %
[id, sourceLanguageToStr[params.lang]]))
result.endTable = (d.config.getOrDefault"doc.listing_end" % id) &
"</td></tr></tbody></table>" & (
d.config.getOrDefault"doc.listing_button" % id)
@ -944,7 +949,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
proc renderContainer(d: PDoc, n: PRstNode, result: var string) =
var tmp = ""
renderRstToOut(d, n.sons[2], tmp)
var arg = strip(getArgument(n))
var arg = esc(d.target, strip(getArgument(n)))
if arg == "":
dispA(d.target, result, "<div>$1</div>", "$1", [tmp])
else:

View file

@ -84,17 +84,27 @@ proc binarySearch*[T, K](a: openArray[T], key: K,
if (len and (len - 1)) == 0:
# when `len` is a power of 2, a faster shr can be used.
var step = len shr 1
var cmpRes: int
while step > 0:
let i = result or step
if cmp(a[i], key) < 1:
cmpRes = cmp(a[i], key)
if cmpRes == 0:
return i
if cmpRes < 1:
result = i
step = step shr 1
if cmp(a[result], key) != 0: result = -1
else:
var b = len
var cmpRes: int
while result < b:
var mid = (result + b) shr 1
if cmp(a[mid], key) < 0:
cmpRes = cmp(a[mid], key)
if cmpRes == 0:
return mid
if cmpRes < 0:
result = mid + 1
else:
b = mid

View file

@ -10,6 +10,7 @@
## the ``graphics`` module.
import strutils
from algorithm import binarySearch
type
Color* = distinct int ## a color stored as RGB
@ -371,37 +372,28 @@ proc `$`*(c: Color): string =
## converts a color into its textual representation. Example: ``#00FF00``.
result = '#' & toHex(int(c), 6)
proc binaryStrSearch(x: openArray[tuple[name: string, col: Color]],
y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmp(x[mid].name, y)
if c < 0: a = mid + 1
elif c > 0: b = mid - 1
else: return mid
result = - 1
proc colorNameCmp(x: tuple[name: string, col: Color], y: string): int =
result = cmpIgnoreCase(x.name, y)
proc parseColor*(name: string): Color =
## parses `name` to a color value. If no valid color could be
## parsed ``EInvalidValue`` is raised.
## parsed ``EInvalidValue`` is raised. Case insensitive.
if name[0] == '#':
result = Color(parseHexInt(name))
else:
var idx = binaryStrSearch(colorNames, name)
var idx = binarySearch(colorNames, name, colorNameCmp)
if idx < 0: raise newException(ValueError, "unknown color: " & name)
result = colorNames[idx][1]
proc isColor*(name: string): bool =
## returns true if `name` is a known color name or a hexadecimal color
## prefixed with ``#``.
## prefixed with ``#``. Case insensitive.
if name[0] == '#':
for i in 1 .. name.len-1:
if name[i] notin {'0'..'9', 'a'..'f', 'A'..'F'}: return false
result = true
else:
result = binaryStrSearch(colorNames, name) >= 0
result = binarySearch(colorNames, name, colorNameCmp) >= 0
proc rgb*(r, g, b: range[0..255]): Color =
## constructs a color from RGB values.

View file

@ -362,15 +362,13 @@ when not defined(ssl):
type SSLContext = ref object
var defaultSSLContext {.threadvar.}: SSLContext
when defined(ssl):
defaultSSLContext = newContext(verifyMode = CVerifyNone)
template contextOrDefault(ctx: SSLContext): SSLContext =
var result = ctx
if ctx == nil:
if defaultSSLContext == nil:
defaultSSLContext = newContext(verifyMode = CVerifyNone)
proc getDefaultSSL(): SSLContext =
result = defaultSslContext
when defined(ssl):
if result == nil:
defaultSSLContext = newContext(verifyMode = CVerifyNone)
result = defaultSSLContext
result
doAssert result != nil, "failure to initialize the SSL context"
proc newProxy*(url: string, auth = ""): Proxy =
## Constructs a new ``TProxy`` object.
@ -480,9 +478,9 @@ proc format(p: MultipartData): tuple[contentType, body: string] =
result.body.add("--" & bound & "--\c\L")
proc request*(url: string, httpMethod: string, extraHeaders = "",
body = "", sslContext = defaultSSLContext, timeout = -1,
body = "", sslContext = getDefaultSSL(), timeout = -1,
userAgent = defUserAgent, proxy: Proxy = nil): Response
{.deprecated.} =
{.deprecated: "use HttpClient.request instead".} =
## | Requests ``url`` with the custom method string specified by the
## | ``httpMethod`` parameter.
## | Extra headers can be specified and must be separated by ``\c\L``
@ -580,7 +578,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
result = parseResponse(s, httpMethod != "HEAD", timeout)
proc request*(url: string, httpMethod = HttpGET, extraHeaders = "",
body = "", sslContext = defaultSSLContext, timeout = -1,
body = "", sslContext = getDefaultSSL(), timeout = -1,
userAgent = defUserAgent, proxy: Proxy = nil): Response
{.deprecated.} =
## | Requests ``url`` with the specified ``httpMethod``.
@ -611,7 +609,7 @@ proc getNewLocation(lastURL: string, headers: HttpHeaders): string =
result = $parsed
proc get*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil): Response {.deprecated.} =
## | GETs the ``url`` and returns a ``Response`` object
@ -632,7 +630,7 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
lastURL = redirectTo
proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil): string {.deprecated.} =
## | GETs the body and returns it as a string.
@ -651,7 +649,7 @@ proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
proc post*(url: string, extraHeaders = "", body = "",
maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil,
multipart: MultipartData = nil): Response {.deprecated.} =
@ -694,7 +692,7 @@ proc post*(url: string, extraHeaders = "", body = "",
proc postContent*(url: string, extraHeaders = "", body = "",
maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil,
multipart: MultipartData = nil): string
@ -717,7 +715,7 @@ proc postContent*(url: string, extraHeaders = "", body = "",
return r.body
proc downloadFile*(url: string, outputFilename: string,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil) {.deprecated.} =
## | Downloads ``url`` and saves it to ``outputFilename``
@ -817,7 +815,7 @@ type
HttpClient* = HttpClientBase[Socket]
proc newHttpClient*(userAgent = defUserAgent,
maxRedirects = 5, sslContext = defaultSslContext, proxy: Proxy = nil,
maxRedirects = 5, sslContext = getDefaultSSL(), proxy: Proxy = nil,
timeout = -1): HttpClient =
## Creates a new HttpClient instance.
##
@ -844,7 +842,7 @@ proc newHttpClient*(userAgent = defUserAgent,
result.bodyStream = newStringStream()
result.getBody = true
when defined(ssl):
result.sslContext = contextOrDefault(sslContext)
result.sslContext = sslContext
type
AsyncHttpClient* = HttpClientBase[AsyncSocket]
@ -852,7 +850,7 @@ type
{.deprecated: [PAsyncHttpClient: AsyncHttpClient].}
proc newAsyncHttpClient*(userAgent = defUserAgent,
maxRedirects = 5, sslContext = defaultSslContext,
maxRedirects = 5, sslContext = getDefaultSSL(),
proxy: Proxy = nil): AsyncHttpClient =
## Creates a new AsyncHttpClient instance.
##
@ -876,7 +874,7 @@ proc newAsyncHttpClient*(userAgent = defUserAgent,
result.bodyStream = newFutureStream[string]("newAsyncHttpClient")
result.getBody = true
when defined(ssl):
result.sslContext = contextOrDefault(sslContext)
result.sslContext = sslContext
proc close*(client: HttpClient | AsyncHttpClient) =
## Closes any connections held by the HTTP client.

View file

@ -1010,14 +1010,18 @@ proc replace*(s: string, sub: Peg, cb: proc(
inc(m)
add(result, substr(s, i))
proc transformFile*(infile, outfile: string,
subs: varargs[tuple[pattern: Peg, repl: string]]) {.
rtl, extern: "npegs$1".} =
## reads in the file `infile`, performs a parallel replacement (calls
## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
## error occurs. This is supposed to be used for quick scripting.
var x = readFile(infile).string
writeFile(outfile, x.parallelReplace(subs))
when not defined(js):
proc transformFile*(infile, outfile: string,
subs: varargs[tuple[pattern: Peg, repl: string]]) {.
rtl, extern: "npegs$1".} =
## reads in the file `infile`, performs a parallel replacement (calls
## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
## error occurs. This is supposed to be used for quick scripting.
##
## **Note**: this proc does not exist while using the JS backend.
var x = readFile(infile).string
writeFile(outfile, x.parallelReplace(subs))
iterator split*(s: string, sep: Peg): string =
## Splits the string `s` into substrings.
@ -1121,7 +1125,7 @@ proc handleCR(L: var PegLexer, pos: int): int =
assert(L.buf[pos] == '\c')
inc(L.lineNumber)
result = pos+1
if L.buf[result] == '\L': inc(result)
if result < L.buf.len and L.buf[result] == '\L': inc(result)
L.lineStart = result
proc handleLF(L: var PegLexer, pos: int): int =
@ -1217,12 +1221,13 @@ proc getEscapedChar(c: var PegLexer, tok: var Token) =
proc skip(c: var PegLexer) =
var pos = c.bufpos
var buf = c.buf
while true:
while pos < c.buf.len:
case buf[pos]
of ' ', '\t':
inc(pos)
of '#':
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
while (pos < c.buf.len) and
not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
of '\c':
pos = handleCR(c, pos)
buf = c.buf
@ -1238,7 +1243,7 @@ proc getString(c: var PegLexer, tok: var Token) =
var pos = c.bufpos + 1
var buf = c.buf
var quote = buf[pos-1]
while true:
while pos < c.buf.len:
case buf[pos]
of '\\':
c.bufpos = pos
@ -1261,7 +1266,7 @@ proc getDollar(c: var PegLexer, tok: var Token) =
if buf[pos] in {'0'..'9'}:
tok.kind = tkBackref
tok.index = 0
while buf[pos] in {'0'..'9'}:
while pos < c.buf.len and buf[pos] in {'0'..'9'}:
tok.index = tok.index * 10 + ord(buf[pos]) - ord('0')
inc(pos)
else:
@ -1277,11 +1282,11 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
if buf[pos] == '^':
inc(pos)
caret = true
while true:
while pos < c.buf.len:
var ch: char
case buf[pos]
of ']':
inc(pos)
if pos < c.buf.len: inc(pos)
break
of '\\':
c.bufpos = pos
@ -1296,11 +1301,14 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
inc(pos)
incl(tok.charset, ch)
if buf[pos] == '-':
if buf[pos+1] == ']':
if pos+1 < c.buf.len and buf[pos+1] == ']':
incl(tok.charset, '-')
inc(pos)
else:
inc(pos)
if pos+1 < c.buf.len:
inc(pos)
else:
break
var ch2: char
case buf[pos]
of '\\':
@ -1312,8 +1320,11 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
tok.kind = tkInvalid
break
else:
ch2 = buf[pos]
inc(pos)
if pos+1 < c.buf.len:
ch2 = buf[pos]
inc(pos)
else:
break
for i in ord(ch)+1 .. ord(ch2):
incl(tok.charset, chr(i))
c.bufpos = pos
@ -1322,15 +1333,15 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
proc getSymbol(c: var PegLexer, tok: var Token) =
var pos = c.bufpos
var buf = c.buf
while true:
while pos < c.buf.len:
add(tok.literal, buf[pos])
inc(pos)
if buf[pos] notin strutils.IdentChars: break
if pos < buf.len and buf[pos] notin strutils.IdentChars: break
c.bufpos = pos
tok.kind = tkIdentifier
proc getBuiltin(c: var PegLexer, tok: var Token) =
if c.buf[c.bufpos+1] in strutils.Letters:
if c.bufpos+1 < c.buf.len and c.buf[c.bufpos+1] in strutils.Letters:
inc(c.bufpos)
getSymbol(c, tok)
tok.kind = tkBuiltin
@ -1343,10 +1354,12 @@ proc getTok(c: var PegLexer, tok: var Token) =
tok.modifier = modNone
setLen(tok.literal, 0)
skip(c)
case c.buf[c.bufpos]
of '{':
inc(c.bufpos)
if c.buf[c.bufpos] == '@' and c.buf[c.bufpos+1] == '}':
if c.buf[c.bufpos] == '@' and c.bufpos+2 < c.buf.len and
c.buf[c.bufpos+1] == '}':
tok.kind = tkCurlyAt
inc(c.bufpos, 2)
add(tok.literal, "{@}")
@ -1379,13 +1392,11 @@ proc getTok(c: var PegLexer, tok: var Token) =
getBuiltin(c, tok)
of '\'', '"': getString(c, tok)
of '$': getDollar(c, tok)
of '\0':
tok.kind = tkEof
tok.literal = "[EOF]"
of 'a'..'z', 'A'..'Z', '\128'..'\255':
getSymbol(c, tok)
if c.buf[c.bufpos] in {'\'', '"'} or
c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
c.buf[c.bufpos] == '$' and c.bufpos+1 < c.buf.len and
c.buf[c.bufpos+1] in {'0'..'9'}:
case tok.literal
of "i": tok.modifier = modIgnoreCase
of "y": tok.modifier = modIgnoreStyle
@ -1406,7 +1417,7 @@ proc getTok(c: var PegLexer, tok: var Token) =
inc(c.bufpos)
add(tok.literal, '+')
of '<':
if c.buf[c.bufpos+1] == '-':
if c.bufpos+2 < c.buf.len and c.buf[c.bufpos+1] == '-':
inc(c.bufpos, 2)
tok.kind = tkArrow
add(tok.literal, "<-")
@ -1441,14 +1452,17 @@ proc getTok(c: var PegLexer, tok: var Token) =
inc(c.bufpos)
add(tok.literal, '^')
else:
if c.bufpos >= c.buf.len:
tok.kind = tkEof
tok.literal = "[EOF]"
add(tok.literal, c.buf[c.bufpos])
inc(c.bufpos)
proc arrowIsNextTok(c: PegLexer): bool =
# the only look ahead we need
var pos = c.bufpos
while c.buf[pos] in {'\t', ' '}: inc(pos)
result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
while pos < c.buf.len and c.buf[pos] in {'\t', ' '}: inc(pos)
result = c.buf[pos] == '<' and (pos+1 < c.buf.len) and c.buf[pos+1] == '-'
# ----------------------------- parser ----------------------------------------
@ -1471,7 +1485,7 @@ proc pegError(p: PegParser, msg: string, line = -1, col = -1) =
proc getTok(p: var PegParser) =
getTok(p, p.tok)
if p.tok.kind == tkInvalid: pegError(p, "invalid token")
if p.tok.kind == tkInvalid: pegError(p, "'" & p.tok.literal & "' is invalid token")
proc eat(p: var PegParser, kind: TokKind) =
if p.tok.kind == kind: getTok(p)

View file

@ -86,18 +86,20 @@ proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen)
proc readAll*(s: Stream): string =
## Reads all available data.
const bufferSize = 1000
result = newString(bufferSize)
var r = 0
while true:
let readBytes = readData(s, addr(result[r]), bufferSize)
if readBytes < bufferSize:
setLen(result, r+readBytes)
break
inc r, bufferSize
setLen(result, r+bufferSize)
when not defined(js):
proc readAll*(s: Stream): string =
## Reads all available data.
const bufferSize = 1024
var buffer {.noinit.}: array[bufferSize, char]
while true:
let readBytes = readData(s, addr(buffer[0]), bufferSize)
if readBytes == 0:
break
let prevLen = result.len
result.setLen(prevLen + readBytes)
copyMem(addr(result[prevLen]), addr(buffer[0]), readBytes)
if readBytes < bufferSize:
break
proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size
@ -131,7 +133,7 @@ proc write*(s: Stream, x: string) =
when nimvm:
writeData(s, cstring(x), x.len)
else:
if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
if x.len > 0: writeData(s, cstring(x), x.len)
proc writeLine*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed
@ -251,14 +253,14 @@ proc readStr*(s: Stream, length: int): TaintedString =
## reads a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred.
result = newString(length).TaintedString
var L = readData(s, addr(string(result)[0]), length)
var L = readData(s, cstring(result), length)
if L != length: setLen(result.string, L)
proc peekStr*(s: Stream, length: int): TaintedString =
## peeks a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred.
result = newString(length).TaintedString
var L = peekData(s, addr(string(result)[0]), length)
var L = peekData(s, cstring(result), length)
if L != length: setLen(result.string, L)
proc readLine*(s: Stream, line: var TaintedString): bool =

View file

@ -9,7 +9,7 @@
## A simple XML tree. More efficient and simpler than the DOM.
import macros, strtabs
import macros, strtabs, strutils
type
XmlNode* = ref XmlNodeObj ## an XML tree consists of ``XmlNode``'s.
@ -217,8 +217,9 @@ proc escape*(s: string): string =
result = newStringOfCap(s.len)
addEscaped(result, s)
proc addIndent(result: var string, indent: int) =
result.add("\n")
proc addIndent(result: var string, indent: int, addNewLines: bool) =
if addNewLines:
result.add("\n")
for i in 1..indent: result.add(' ')
proc noWhitespace(n: XmlNode): bool =
@ -227,7 +228,8 @@ proc noWhitespace(n: XmlNode): bool =
for i in 0..n.len-1:
if n[i].kind in {xnText, xnEntity}: return true
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
addNewLines=true) =
## adds the textual representation of `n` to `result`.
proc addEscapedAttr(result: var string, s: string) =
@ -260,14 +262,15 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
# for mixed leaves, we cannot output whitespace for readability,
# because this would be wrong. For example: ``a<b>b</b>`` is
# different from ``a <b>b</b>``.
for i in 0..n.len-1: result.add(n[i], indent+indWidth, indWidth)
for i in 0..n.len-1:
result.add(n[i], indent+indWidth, indWidth, addNewLines)
else:
for i in 0..n.len-1:
result.addIndent(indent+indWidth)
result.add(n[i], indent+indWidth, indWidth)
result.addIndent(indent)
result.addIndent(indent+indWidth, addNewLines)
result.add(n[i], indent+indWidth, indWidth, addNewLines)
result.addIndent(indent, addNewLines)
else:
result.add(n[0], indent+indWidth, indWidth)
result.add(n[0], indent+indWidth, indWidth, addNewLines)
result.add("</")
result.add(n.fTag)
result.add(">")
@ -316,7 +319,10 @@ proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
var elements = newNimNode(nnkBracket, a)
for i in 1..a.len-1:
if a[i].kind == nnkExprEqExpr:
attrs.add(toStrLit(a[i][0]))
# In order to support attributes like `data-lang` we have to
# replace whitespace because `toStrLit` gives `data - lang`.
let attrName = toStrLit(a[i][0]).strVal.replace(" ", "")
attrs.add(newStrLitNode(attrName))
attrs.add(a[i][1])
#echo repr(attrs)
else:

View file

@ -32,8 +32,6 @@ type
PRawChannel = ptr RawChannel
LoadStoreMode = enum mStore, mLoad
Channel* {.gcsafe.}[TMsg] = RawChannel ## a channel for thread communication
{.deprecated: [TRawChannel: RawChannel, TLoadStoreMode: LoadStoreMode,
TChannel: Channel].}
const ChannelDeadMask = -2

View file

@ -144,7 +144,7 @@ proc allocSlowPath(r: var MemRegion; size: int) =
r.tail = fresh
r.remaining = s - sizeof(BaseChunk)
proc alloc(r: var MemRegion; size: int): pointer =
proc allocFast(r: var MemRegion; size: int): pointer =
if size <= MaxSmallObject:
var it = r.freeLists[size div MemAlign]
if it != nil:
@ -270,7 +270,7 @@ proc isOnHeap*(r: MemRegion; p: pointer): bool =
it = it.next
proc rawNewObj(r: var MemRegion, typ: PNimType, size: int): pointer =
var res = cast[ptr ObjHeader](alloc(r, size + sizeof(ObjHeader)))
var res = cast[ptr ObjHeader](allocFast(r, size + sizeof(ObjHeader)))
res.typ = typ
if typ.finalizer != nil:
res.nextFinal = r.head.head
@ -278,7 +278,7 @@ proc rawNewObj(r: var MemRegion, typ: PNimType, size: int): pointer =
result = res +! sizeof(ObjHeader)
proc rawNewSeq(r: var MemRegion, typ: PNimType, size: int): pointer =
var res = cast[ptr SeqHeader](alloc(r, size + sizeof(SeqHeader)))
var res = cast[ptr SeqHeader](allocFast(r, size + sizeof(SeqHeader)))
res.typ = typ
res.region = addr(r)
result = res +! sizeof(SeqHeader)
@ -351,6 +351,11 @@ proc alloc0(r: var MemRegion; size: Natural): pointer =
# but incorrect in general. XXX
result = alloc0(size)
proc alloc(r: var MemRegion; size: Natural): pointer =
# ignore the region. That is correct for the channels module
# but incorrect in general. XXX
result = alloc(size)
proc dealloc(r: var MemRegion; p: pointer) = dealloc(p)
proc allocShared(size: Natural): pointer =
@ -390,3 +395,6 @@ proc getTotalMem*(r: MemRegion): int =
result = r.totalSize
proc setStackBottom(theStackBottom: pointer) = discard
proc nimGCref(x: pointer) {.compilerProc.} = discard
proc nimGCunref(x: pointer) {.compilerProc.} = discard

View file

@ -576,18 +576,3 @@ proc nimBoolToStr(x: bool): string {.compilerRtl.} =
proc nimCharToStr(x: char): string {.compilerRtl.} =
result = newString(1)
result[0] = x
proc binaryStrSearch(x: openArray[string], y: string): int {.compilerproc.} =
var
a = 0
b = len(x)
while a < b:
var mid = (a + b) div 2
if x[mid] < y:
a = mid + 1
else:
b = mid
if a < len(x) and x[a] == y:
result = a
else:
result = -1