cligen/mfile

Search:
Group by:

Module similar to std/memfiles but better layered & no exceptions interface which can help w/fancy file making needs or safety inside || blocks. Also adds noShrink safety, has non-system.open-colliding type constructor, uses .len (not .size) for more Nim-wide consistency & supports WO memory, and has FileInfo in the object (for various inspections).

Types

MFile = object
  fd*: cint                  ## open file|-1; open_osfhandle(fh,) on Win; FileHandle=cint
  fi*: FileInfo              ## File metadata at time of open
  when defined(windows):
    fh*: cint                ## Underlying OS File Handle; fdclose(fd) auto-closes this
    mh*: Handle              ## M)ap H)andle *CAUTION*: Windows specific public field
  prot*: cint                ## Map Protection
  flags*: cint               ## Map Flags (-1 => not open)
  mslc*: MSlice              ## (mem, len) of file
Like MemFile but safe in an MT-environment

Lets

PROT_RW = 3'i32
read-write is a common combination

Procs

proc `<`(a, b: MFile): bool {....raises: [], tags: [], forbids: [].}
proc `==`(a, b: MFile): bool {....raises: [], tags: [], forbids: [].}
proc `==`(a: MFile; p: pointer): bool {....raises: [], tags: [], forbids: [].}
proc `[]`[A, B](mf: MFile; s: HSlice[A, B]): MSlice
proc add[T: SomeInteger](mf: var MFile; ch: char; off: var T)
Append ch to mf, resizing if necessary and updating offset off.
proc add[T: SomeInteger](mf: var MFile; ms: MSlice; off: var T)
Append ms to mf, resizing if necessary and updating offset off.
proc close(mf: MFile; err = stderr) {....raises: [], tags: [WriteIOEffect],
                                      forbids: [].}
Release memory acquired by MFile mopen()s; Allows let mf = mopen()
proc close(mf: var MFile; err = stderr) {....raises: [], tags: [WriteIOEffect],
    forbids: [].}
Release memory acquired by mf mopen()s; Sets fields to invalid.
proc fdClose(mf: MFile): int {....raises: [], tags: [], forbids: [].}
Only release file handles underlying mf
proc fdClose(mf: var MFile): int {....raises: [], tags: [], forbids: [].}
Only release file handles underlying mf
proc inCore(mf: MFile): tuple[resident, total: int] {....raises: [], tags: [],
    forbids: [].}
proc len(mf: MFile): int {....raises: [], tags: [], forbids: [].}
accessor to use MFile like MSlice
proc len=(mf: var MFile; n: int) {....raises: [], tags: [], forbids: [].}
use MFile ~ MSlice
proc mem(mf: MFile): pointer {....raises: [], tags: [], forbids: [].}
accessor to use MFile like MSlice
proc mem=(mf: var MFile; m: pointer) {....raises: [], tags: [], forbids: [].}
use MFile ~ MSlice
proc mopen(fd, fh: cint; fi: FileInfo; prot = PROT_READ; flags = MAP_SHARED;
           a = 0.Off; b = Off(-1); allowRemap = false; noShrink = false;
           err = stderr): MFile {....raises: [], tags: [WriteIOEffect], forbids: [].}
mmap(2) wrapper to simplify life. Byte range [a,b) of the file pointed to by 'fd' translates to [result.mem ..< .len).
proc mopen(fh: cint; prot = PROT_READ; flags = MAP_SHARED; a = 0; b = Off(-1);
           allowRemap = false; noShrink = false; err = stderr): MFile {.
    ...raises: [], tags: [WriteIOEffect], forbids: [].}
Init map for already open fh. See mopen(cint, Stat) for details.
proc mopen(path: string; prot = PROT_READ; flags = MAP_SHARED; a = 0; b = -1;
           allowRemap = false; noShrink = false; perMask = 0o000000000666;
           err = stderr): MFile {....raises: [], tags: [WriteIOEffect], forbids: [].}
Init map for path. See mopen(cint,Stat) for mapping details. This proc also creates a file, if necessary, with permission perMask.
proc nSplit(n: int; path: string; sep = '\n'; prot = PROT_READ;
            flags = MAP_SHARED): tuple[mf: MFile, parts: seq[MSlice]] {.
    ...raises: [], tags: [WriteIOEffect], forbids: [].}
Split seekable file @path into n roughly equal sep-delimited parts with any separator char included in slices. Caller should close result.mf (which is nil on failure) when desired. result.len can be < n for small file sizes (in number of seps). For IO efficiency, subdivision is done by bytes as a guess. So, this is fast, but accuracy is limited by statistical regularity.
proc resize(mf: var MFile; newFileSize: int64; err = stderr): int {....raises: [],
    tags: [WriteIOEffect], forbids: [].}
Resize & re-map file underlying an allowRemap MFile. .mem will likely change. Note: this assumes entire file is mapped @off=0.
proc toMSlice(mf: MFile): MSlice {....raises: [], tags: [], forbids: [].}
MSlice field accessor for consistency with toMSlice(string)

Iterators

iterator lines(mf: MFile; buf: var string; sep = '\n'; eat = '\r'): string {.
    ...raises: [], tags: [], forbids: [].}
Copy each line in mf to passed buf, like system.lines(File). sep, eat, and delimiting logic is as for mslice.mSlices, but Nim strings are returned. Default parameters parse lines ending in either Unix(\n) or Windows(\r\n) style on on a line-by-line basis (not every line needs the same ending). sep='\\r', eat='\\0' parses archaic MacOS9 files.
var buffer: string = ""
for line in lines(mopen("foo"), buffer): echo line
iterator lines(mf: MFile; sep = '\n'; eat = '\r'): string {....raises: [],
    tags: [], forbids: [].}
Exactly like lines(MFile, var string) but yields new Nim strings.
for line in lines(mopen("foo")): echo line   #Example
iterator mSlices(mf: MFile; sep = '\n'; eat = '\r'): MSlice {....raises: [],
    tags: [], forbids: [].}
iterator mSlices(path: string; sep = '\n'; eat = '\r'; keep = false;
                 err = stderr; mf: var MFile = doNotUse): MSlice {....raises: [],
    tags: [WriteIOEffect], forbids: [].}
A convenient input iterator that mopen()s path or if that fails falls back to ordinary file IO but constructs MSlice from lines. true keep means MFile or strings backing MSlice's are kept alive for life of program unless you also pass mf which returns the MFile to close when unneeded.
iterator rows(f: File; s: Sep; n = 0): seq[string] {....raises: [IOError],
    tags: [ReadIOEffect], forbids: [].}
Exactly like rows(File, Sep) but yields new Nim seqs.
iterator rows(f: File; s: Sep; row: var seq[string]; n = 0): seq[string] {.
    ...raises: [IOError], tags: [ReadIOEffect], forbids: [].}
Like lines(File) but also split each line into columns with Sep.
iterator rows(mf: MFile; s: Sep; n = 0; sep = '\n'; eat = '\r'): seq[MSlice] {.
    ...raises: [], tags: [], forbids: [].}
Exactly like rows(MFile, Sep) but yields new Nim seqs.
iterator rows(mf: MFile; s: Sep; row: var seq[MSlice]; n = 0; sep = '\n';
              eat = '\r'): seq[MSlice] {....raises: [], tags: [], forbids: [].}
Like lines(MFile) but also split each line into columns with Sep.