diff options
author | Andreas Rumpf <andreas@andreas-desktop> | 2010-02-02 19:20:16 +0100 |
---|---|---|
committer | Andreas Rumpf <andreas@andreas-desktop> | 2010-02-02 19:20:16 +0100 |
commit | 6ecbed72840bd080623299ed6b6d3ef8a2e0033d (patch) | |
tree | 577ce46a9a8d265a6df7fc6492b1e9e2d8651591 | |
parent | e22c73fd893447cc59dd854e9680626ed7da01b2 (diff) | |
download | Nim-6ecbed72840bd080623299ed6b6d3ef8a2e0033d.tar.gz |
added system.del; delete; insert
-rwxr-xr-x | lib/devel/httpclient.nim | 95 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/pure/parseutils.nim | 0 | ||||
-rwxr-xr-x | lib/pure/parsexml.nim | 4 | ||||
-rwxr-xr-x | lib/system.nim | 25 | ||||
-rwxr-xr-x | rod/astalgo.nim | 3 |
5 files changed, 93 insertions, 34 deletions
diff --git a/lib/devel/httpclient.nim b/lib/devel/httpclient.nim index d600fcb59..83b7e8984 100755 --- a/lib/devel/httpclient.nim +++ b/lib/devel/httpclient.nim @@ -17,7 +17,7 @@ type TResponse* = tuple[ version: string, status: string, headers: seq[THeader], body: string] - THeader* = tuple[htype: string, hvalue: string] + THeader* = tuple[htype, hvalue: string] EInvalidProtocol* = object of EBase ## exception that is raised when server ## does not conform to the implemented @@ -54,20 +54,49 @@ proc getHeaderValue*(headers: seq[THeader], name: string): string = return headers[i].hvalue return "" -proc parseChunks(data: var string, start: int, s: TSocket): string = +proc charAt(d: var string, i: var int, s: TSocket): char {.inline.} = + result = d[i] + while result == '\0': + d = s.recv() + i = 0 + result = d[i] + +proc parseChunks(d: var string, start: int, s: TSocket): string = # get chunks: var i = start result = "" while true: var chunkSize = 0 - var j = parseHex(data, chunkSize, i) - if j <= 0: break - inc(i, j) - while data[i] notin {'\C', '\L', '\0'}: inc(i) - if data[i] == '\C': inc(i) - if data[i] == '\L': inc(i) - if chunkSize <= 0: break - var x = copy(data, i, i+chunkSize-1) + var digitFound = false + echo "number: ", copy(d, i, i + 10) + while true: + case d[i] + of '0'..'9': + digitFound = true + chunkSize = chunkSize shl 4 or (ord(d[i]) - ord('0')) + of 'a'..'f': + digitFound = true + chunkSize = chunkSize shl 4 or (ord(d[i]) - ord('a') + 10) + of 'A'..'F': + digitFound = true + chunkSize = chunkSize shl 4 or (ord(d[i]) - ord('A') + 10) + of '\0': + d = s.recv() + i = -1 + else: break + inc(i) + + echo "chunksize: ", chunkSize + if chunkSize <= 0: + echo copy(d, i) + assert digitFound + break + while charAt(d, i, s) notin {'\C', '\L', '\0'}: inc(i) + if charAt(d, i, s) == '\C': inc(i) + if charAt(d, i, s) == '\L': inc(i) + else: httpError("CR-LF after chunksize expected") + + var x = copy(d, i, i+chunkSize-1) var size = x.len result.add(x) @@ -82,18 +111,17 @@ proc parseChunks(data: var string, start: int, s: TSocket): string = dec(missing, bytesRead) # next chunk: - data = s.recv() + d = s.recv() i = 0 # skip trailing CR-LF: - while data[i] in {'\C', '\L'}: inc(i) - if data[i] == '\0': data.add(s.recv()) + while charAt(d, i, s) in {'\C', '\L'}: inc(i) -proc parseBody(data: var string, start: int, s: TSocket, +proc parseBody(d: var string, start: int, s: TSocket, headers: seq[THeader]): string = if getHeaderValue(headers, "Transfer-Encoding") == "chunked": - result = parseChunks(data, start, s) + result = parseChunks(d, start, s) else: - result = copy(data, start) + result = copy(d, start) # -REGION- Content-Length # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3 var contentLengthHeader = getHeaderValue(headers, "Content-Length") @@ -112,7 +140,7 @@ proc parseBody(data: var string, start: int, s: TSocket, result.add(moreData) proc parseResponse(s: TSocket): TResponse = - var data = s.recv() + var d = s.recv() var i = 0 # Parse the version @@ -120,8 +148,8 @@ proc parseResponse(s: TSocket): TResponse = # ``HTTP/1.1`` 200 OK var matches: array[0..1, string] - var L = data.matchLen(peg"\i 'HTTP/' {'1.1'/'1.0'} \s+ {(!\n .)*}\n", - matches, i) + var L = d.matchLen(peg"\i 'HTTP/' {'1.1'/'1.0'} \s+ {(!\n .)*}\n", + matches, i) if L < 0: httpError("invalid HTTP header") result.version = matches[0] @@ -135,29 +163,29 @@ proc parseResponse(s: TSocket): TResponse = result.headers = @[] while true: var key = "" - while data[i] != ':': - if data[i] == '\0': httpError("invalid HTTP header, ':' expected") - key.add(data[i]) + while d[i] != ':': + if d[i] == '\0': httpError("invalid HTTP header, ':' expected") + key.add(d[i]) inc(i) inc(i) # skip ':' - if data[i] == ' ': inc(i) # skip if the character is a space + if d[i] == ' ': inc(i) # skip if the character is a space var val = "" - while data[i] notin {'\C', '\L', '\0'}: - val.add(data[i]) + while d[i] notin {'\C', '\L', '\0'}: + val.add(d[i]) inc(i) result.headers.add((key, val)) - if data[i] == '\C': inc(i) - if data[i] == '\L': inc(i) + if d[i] == '\C': inc(i) + if d[i] == '\L': inc(i) else: httpError("invalid HTTP header, CR-LF expected") - if data[i] == '\C': inc(i) - if data[i] == '\L': + if d[i] == '\C': inc(i) + if d[i] == '\L': inc(i) break - result.body = parseBody(data, i, s, result.headers) + result.body = parseBody(d, i, s, result.headers) proc request*(url: string): TResponse = var r = parse(url) @@ -169,6 +197,8 @@ proc request*(url: string): TResponse = headers = "GET / HTTP/1.1\c\L" add(headers, "Host: " & r.hostname & "\c\L\c\L") + add(headers, "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl;" & + " rv:1.9.2) Gecko/20100115 Firefox/3.6") var s = socket() s.connect(r.hostname, TPort(80)) @@ -210,4 +240,7 @@ proc downloadFile*(url: string, outputFilename: string) = when isMainModule: - downloadFile("http://www.google.com", "GoogleTest.html") + #downloadFile("http://force7.de/nimrod/index.html", "nimrodindex.html") + #downloadFile("http://www.httpwatch.com/", "ChunkTest.html") + downloadFile("http://www.httpwatch.com/httpgallery/chunked/", "ChunkTest.html") + diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 0878f87eb..0878f87eb 100644..100755 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim index 0728d07b1..6809c0f7c 100755 --- a/lib/pure/parsexml.nim +++ b/lib/pure/parsexml.nim @@ -321,8 +321,8 @@ proc parseEntity(my: var TXmlParser, dest: var string) = elif buf[pos] == 'g' and buf[pos+1] == 't' and buf[pos+2] == ';': add(dest, '>') inc(pos, 2) - elif buf[pos] == 'a' and buf[pos+1] == 'm' and buf[pos+2] == 'p' - and buf[pos+3] == ';': + elif buf[pos] == 'a' and buf[pos+1] == 'm' and buf[pos+2] == 'p' and + buf[pos+3] == ';': add(dest, '&') inc(pos, 3) elif buf[pos] == 'a' and buf[pos+1] == 'p' and buf[pos+2] == 'o' and diff --git a/lib/system.nim b/lib/system.nim index 7788e40e5..13d0b4746 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -698,6 +698,31 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} = setLen(x, xl + y.len) for i in 0..high(y): x[xl+i] = y[i] +proc del* [T](x: var seq[T], i: int) {.noSideEffect.} = + ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`. + ## This is an O(1) operation. + var xl = x.len + x[i] = x[xl-1] + setLen(x, xl-1) + +proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = + ## deletes the item at index `i` by moving ``x[i+1..]`` by one position. + ## This is an O(n) operation. + var xl = x.len + for j in i..xl-2: x[j] = x[j+1] + setLen(x, xl-1) + +proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = + ## inserts `item` into `x` at position `i`. + var xl = x.len + setLen(x, xl+1) + var j = xl-1 + while j >= i: + x[j+1] = x[j] + inc(j) + x[i] = item + + proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.} ## takes any Nimrod variable and returns its string representation. It ## works even for complex data graphs with cycles. This is a great diff --git a/rod/astalgo.nim b/rod/astalgo.nim index d47dfcccb..1b4572b2b 100755 --- a/rod/astalgo.nim +++ b/rod/astalgo.nim @@ -311,7 +311,8 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, maxRecDepth: int) toRope("align"), toRope(n.align), toRope("sons"), result]) -proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, maxRecDepth: int): PRope = +proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, + maxRecDepth: int): PRope = var istr: PRope if n == nil: result = toRope("null") |