diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2015-04-10 14:02:22 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2015-04-10 14:02:22 +0200 |
commit | 6e6c6446a4d3d30a7e97ef4417bdca892e376b53 (patch) | |
tree | d1100588d5a540db5e266e152d6e285e08d3bf31 /lib/system/sysio.nim | |
parent | badd1a79f02c34d4629514440f06d915f18f4a60 (diff) | |
parent | ef9a3b4d3ba802aeddb2176770eb174c73e231a3 (diff) | |
download | Nim-6e6c6446a4d3d30a7e97ef4417bdca892e376b53.tar.gz |
Merge pull request #2329 from def-/readline
Speed up readLine by using getc_unlocked
Diffstat (limited to 'lib/system/sysio.nim')
-rw-r--r-- | lib/system/sysio.nim | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index cee4856fd..38a2132b2 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -31,6 +31,24 @@ proc fprintf(f: File, frmt: cstring) {.importc: "fprintf", 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 defined(windows): + 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,22 +85,40 @@ 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 defined(posix) or defined(windows): + 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)) |