summary refs log tree commit diff stats
path: root/lib/pure/memfiles.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/memfiles.nim')
-rw-r--r--lib/pure/memfiles.nim93
1 files changed, 65 insertions, 28 deletions
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 9f4094b40..807f3da43 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2012 Nimrod Contributors
+#        (c) Copyright 2014 Nimrod Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -34,6 +34,43 @@ type
     else:
       handle: cint
 
+
+proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead,
+             mappedSize = -1, offset = 0): pointer =
+  var readonly = mode == fmRead
+  when defined(windows):
+    result = mapViewOfFileEx(
+      m.mapHandle,
+      if readonly: FILE_MAP_READ else: FILE_MAP_WRITE,
+      int32(offset shr 32),
+      int32(offset and 0xffffffff),
+      if mappedSize == -1: 0 else: mappedSize,
+      nil)
+    if result == nil:
+      osError(osLastError())
+  else:
+    assert mappedSize > 0
+    result = mmap(
+      nil,
+      mappedSize,
+      if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
+      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      m.handle, offset)
+    if result == cast[pointer](MAP_FAILED):
+      osError(osLastError())
+
+
+proc unmapMem*(f: var TMemFile, p: pointer, size: int) =
+  ## unmaps the memory region ``(p, <p+size)`` of the mapped file `f`.
+  ## All changes are written back to the file system, if `f` was opened
+  ## with write access. ``size`` must be of exactly the size that was requested
+  ## via ``mapMem``.
+  when defined(windows):
+    if unmapViewOfFile(p) == 0: osError(osLastError())
+  else:
+    if munmap(p, size) != 0: osError(osLastError())
+
+
 proc open*(filename: string, mode: TFileMode = fmRead,
            mappedSize = -1, offset = 0, newFileSize = -1): TMemFile =
   ## opens a memory mapped file. If this fails, ``EOS`` is raised.
@@ -52,9 +89,9 @@ proc open*(filename: string, mode: TFileMode = fmRead,
   when defined(windows):
     template fail(errCode: TOSErrorCode, msg: expr) =
       rollback()
-      if result.fHandle != 0: discard CloseHandle(result.fHandle)
-      if result.mapHandle != 0: discard CloseHandle(result.mapHandle)
-      OSError(errCode)
+      if result.fHandle != 0: discard closeHandle(result.fHandle)
+      if result.mapHandle != 0: discard closeHandle(result.mapHandle)
+      osError(errCode)
       # return false
       #raise newException(EIO, msg)
 
@@ -69,36 +106,36 @@ proc open*(filename: string, mode: TFileMode = fmRead,
         0)
 
     when useWinUnicode:
-      result.fHandle = callCreateFile(CreateFileW, newWideCString(filename))
+      result.fHandle = callCreateFile(createFileW, newWideCString(filename))
     else:
-      result.fHandle = callCreateFile(CreateFileA, filename)
+      result.fHandle = callCreateFile(createFileA, filename)
 
     if result.fHandle == INVALID_HANDLE_VALUE:
-      fail(OSLastError(), "error opening file")
+      fail(osLastError(), "error opening file")
 
     if newFileSize != -1:
       var 
         sizeHigh = int32(newFileSize shr 32)
         sizeLow  = int32(newFileSize and 0xffffffff)
 
-      var status = SetFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
+      var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
                                   FILE_BEGIN)
-      let lastErr = OSLastError()
+      let lastErr = osLastError()
       if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
-         (SetEndOfFile(result.fHandle) == 0):
+         (setEndOfFile(result.fHandle) == 0):
         fail(lastErr, "error setting file size")
 
     # since the strings are always 'nil', we simply always call
     # CreateFileMappingW which should be slightly faster anyway:
-    result.mapHandle = CreateFileMappingW(
+    result.mapHandle = createFileMappingW(
       result.fHandle, nil,
       if readonly: PAGE_READONLY else: PAGE_READWRITE,
       0, 0, nil)
 
     if result.mapHandle == 0:
-      fail(OSLastError(), "error creating mapping")
+      fail(osLastError(), "error creating mapping")
 
-    result.mem = MapViewOfFileEx(
+    result.mem = mapViewOfFileEx(
       result.mapHandle,
       if readonly: FILE_MAP_READ else: FILE_MAP_WRITE,
       int32(offset shr 32),
@@ -107,12 +144,12 @@ proc open*(filename: string, mode: TFileMode = fmRead,
       nil)
 
     if result.mem == nil:
-      fail(OSLastError(), "error mapping view")
+      fail(osLastError(), "error mapping view")
 
     var hi, low: int32
-    low = GetFileSize(result.fHandle, addr(hi))
+    low = getFileSize(result.fHandle, addr(hi))
     if low == INVALID_FILE_SIZE:
-      fail(OSLastError(), "error getting file size")
+      fail(osLastError(), "error getting file size")
     else:
       var fileSize = (int64(hi) shr 32) or low
       if mappedSize != -1: result.size = min(fileSize, mappedSize).int
@@ -122,7 +159,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
     template fail(errCode: TOSErrorCode, msg: expr) =
       rollback()
       if result.handle != 0: discard close(result.handle)
-      OSError(errCode)
+      osError(errCode)
   
     var flags = if readonly: O_RDONLY else: O_RDWR
 
@@ -133,22 +170,22 @@ proc open*(filename: string, mode: TFileMode = fmRead,
     if result.handle == -1:
       # XXX: errno is supposed to be set here
       # Is there an exception that wraps it?
-      fail(OSLastError(), "error opening file")
+      fail(osLastError(), "error opening file")
 
     if newFileSize != -1:
       if ftruncate(result.handle, newFileSize) == -1:
-        fail(OSLastError(), "error setting file size")
+        fail(osLastError(), "error setting file size")
 
     if mappedSize != -1:
       result.size = mappedSize
     else:
-      var stat: Tstat
+      var stat: TStat
       if fstat(result.handle, stat) != -1:
         # XXX: Hmm, this could be unsafe
         # Why is mmap taking int anyway?
         result.size = int(stat.st_size)
       else:
-        fail(OSLastError(), "error getting file size")
+        fail(osLastError(), "error getting file size")
 
     result.mem = mmap(
       nil,
@@ -159,7 +196,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
       offset)
 
     if result.mem == cast[pointer](MAP_FAILED):
-      fail(OSLastError(), "file mapping failed")
+      fail(osLastError(), "file mapping failed")
 
 proc close*(f: var TMemFile) =
   ## closes the memory mapped file `f`. All changes are written back to the
@@ -170,14 +207,14 @@ proc close*(f: var TMemFile) =
 
   when defined(windows):
     if f.fHandle != INVALID_HANDLE_VALUE:
-      lastErr = OSLastError()
-      error = UnmapViewOfFile(f.mem) == 0
-      error = (CloseHandle(f.mapHandle) == 0) or error
-      error = (CloseHandle(f.fHandle) == 0) or error
+      error = unmapViewOfFile(f.mem) == 0
+      lastErr = osLastError()
+      error = (closeHandle(f.mapHandle) == 0) or error
+      error = (closeHandle(f.fHandle) == 0) or error
   else:
     if f.handle != 0:
-      lastErr = OSLastError()
       error = munmap(f.mem, f.size) != 0
+      lastErr = osLastError()
       error = (close(f.handle) != 0) or error
 
   f.size = 0
@@ -189,5 +226,5 @@ proc close*(f: var TMemFile) =
   else:
     f.handle = 0
   
-  if error: OSError(lastErr)
+  if error: osError(lastErr)