00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00051 #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE
00052 #define WINSTL_INCL_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE
00053 
00054 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00055 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE_MAJOR     4
00056 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE_MINOR     7
00057 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE_REVISION  2
00058 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_MEMORY_MAPPED_FILE_EDIT      91
00059 #endif 
00060 
00061 
00062 
00063 
00064 
00065 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00066 # include <winstl/winstl.h>
00067 #endif 
00068 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00069 # ifndef WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS
00070 #  include <winstl/error/exceptions.hpp>
00071 # endif 
00072 #endif 
00073 #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE
00074 # include <stlsoft/smartptr/scoped_handle.hpp>
00075 #endif 
00076 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_STRING_H_FWD
00077 # include <stlsoft/shims/access/string/fwd.h>
00078 #endif 
00079 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
00080 # include <stlsoft/util/std_swap.hpp>
00081 #endif 
00082 
00083 #ifdef STLSOFT_UNITTEST
00084 # include <winstl/filesystem/file_path_buffer.hpp>
00085 #endif 
00086 
00087 
00088 
00089 
00090 
00091 #ifndef _WINSTL_NO_NAMESPACE
00092 # if defined(_STLSOFT_NO_NAMESPACE) || \
00093      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00094 
00095 namespace winstl
00096 {
00097 # else
00098 
00099 
00100 namespace stlsoft
00101 {
00102 
00103 namespace winstl_project
00104 {
00105 
00106 # endif 
00107 #endif 
00108 
00109 
00110 
00111 
00112 
00117 class memory_mapped_file
00118 {
00121 public:
00123     typedef memory_mapped_file              class_type;
00125 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00126     typedef ws_uint64_t                     size_type;
00127 #else 
00128     typedef ws_uint32_t                     size_type;
00129 #endif 
00131     typedef ws_dword_t                      error_type;
00132 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00134     typedef ws_uint64_t                     offset_type;
00135 #endif 
00137     typedef ws_bool_t                       bool_type;
00139 
00142 private:
00143 #if (   defined(STLSOFT_COMPILER_IS_MSVC) && \
00144         _MSC_VER < 1200) || \
00145     defined(STLSOFT_COMPILER_IS_WATCOM)
00146     static void CloseHandle(HANDLE h)
00147     {
00148         ::CloseHandle(h);
00149     }
00150 #endif 
00151 
00152     void open_(
00153         ws_char_a_t const*  fileName
00154 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00155     ,   offset_type         offset
00156     ,   ws_uint32_t         requestSize
00157 #endif 
00158     )
00159     {
00160         scoped_handle<HANDLE>   hfile(  ::CreateFileA(  fileName
00161                                                     ,   GENERIC_READ
00162                                                     ,   FILE_SHARE_READ
00163                                                     ,   NULL
00164                                                     ,   OPEN_EXISTING
00165                                                     ,   FILE_FLAG_RANDOM_ACCESS
00166                                                     ,   NULL)
00167                             ,   CloseHandle
00168                             ,   INVALID_HANDLE_VALUE);
00169 
00170 
00171 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00172         open_helper_(hfile.get(), offset, requestSize);
00173 #else 
00174         open_helper_(hfile.get());
00175 #endif 
00176     }
00177 
00178     void open_(
00179         ws_char_w_t const*  fileName
00180 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00181     ,   offset_type         offset
00182     ,   ws_uint32_t         requestSize
00183 #endif 
00184     )
00185     {
00186         scoped_handle<HANDLE>   hfile(  ::CreateFileW(  fileName
00187                                                     ,   GENERIC_READ
00188                                                     ,   FILE_SHARE_READ
00189                                                     ,   NULL
00190                                                     ,   OPEN_EXISTING
00191                                                     ,   FILE_FLAG_RANDOM_ACCESS
00192                                                     ,   NULL)
00193                             ,   CloseHandle
00194                             ,   INVALID_HANDLE_VALUE);
00195 
00196 
00197 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00198         open_helper_(hfile.get(), offset, requestSize);
00199 #else 
00200         open_helper_(hfile.get());
00201 #endif 
00202     }
00203 
00204     void open_helper_(
00205         HANDLE      hFile
00206 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00207     ,   offset_type offset
00208     ,   ws_uint32_t requestSize
00209 #endif 
00210     )
00211     {
00212         if(INVALID_HANDLE_VALUE == hFile)
00213         {
00214             on_error_("Failed to open file for mapping");
00215         }
00216         else
00217         {
00218             DWORD   fileSizeHigh;
00219             DWORD   fileSizeLow =   ::GetFileSize(hFile, &fileSizeHigh);
00220             DWORD   error       =   ::GetLastError();
00221 
00222             if( INVALID_FILE_SIZE == fileSizeLow &&
00223                 ERROR_SUCCESS != error)
00224             {
00225                 on_error_("Failed to determine mapped file size", error);
00226             }
00227 #ifndef STLSOFT_CF_64BIT_INT_SUPPORT
00228             else if(0 != fileSizeHigh)
00229             {
00230                 on_error_("Cannot map files with sizes larger than 4GB with compilers that do not support 64-bit integers", ERROR_SUCCESS);
00231             }
00232 #endif 
00233             else if(0 == fileSizeHigh &&
00234                     0 == fileSizeLow)
00235             {
00236                 
00237                 
00238                 m_memory    =   NULL;
00239                 m_cb        =   0;
00240             }
00241             else
00242             {
00243                 DWORD   maxSizeHi   =   0;
00244                 DWORD   maxSizeLo   =   0;
00245 
00246                 if(0 == requestSize)
00247                 {
00248 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00249                     requestSize =   ws_uint32_t((size_type(fileSizeHigh) << 32) | fileSizeLow);
00250 #else 
00251                     requestSize =   fileSizeLow;
00252 #endif 
00253                 }                 
00254 
00255 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00256                 if( 
00257 0 != requestSize)
00258                 {
00259                     offset_type maxSize     =   offset + requestSize;
00260                     offset_type actualSize  =   (offset_type(fileSizeHigh) << 32) + fileSizeLow;
00261 
00262                     if(maxSize > actualSize)
00263                     {
00264                         WINSTL_ASSERT(actualSize >= offset);
00265 
00266                         requestSize = static_cast<ws_uint32_t>(actualSize - offset);
00267                         maxSize = 0;
00268                     }
00269 
00270                     maxSizeHi = static_cast<DWORD>(maxSize >> 32);
00271                     maxSizeLo = static_cast<DWORD>(maxSize);
00272                 }
00273 #endif 
00274 
00275                 if(0 == requestSize)
00276                 {
00277                     m_memory    =   NULL;
00278                     m_cb        =   0;
00279                 }
00280                 else
00281                 {
00282                     scoped_handle<HANDLE>   hmap(
00283                                                 ::CreateFileMappingA(
00284                                                     hFile
00285                                                 ,   NULL
00286                                                 ,   PAGE_READONLY
00287                                                 ,   maxSizeHi
00288                                                 ,   maxSizeLo
00289                                                 ,   NULL
00290                                                 )
00291                                             ,   CloseHandle
00292                                             ,   NULL
00293                                             );
00294 
00295                     if(hmap.empty())
00296                     {
00297                         on_error_("Failed to open file mapping");
00298                     }
00299                     else
00300                     {
00301                         void* memory = ::MapViewOfFile(
00302                                             hmap.get()
00303                                         ,   FILE_MAP_READ
00304                                         ,   static_cast<ws_uint32_t>(offset >> 32)
00305                                         ,   static_cast<ws_uint32_t>(offset)
00306                                         ,   requestSize
00307                                         );
00308 
00309                         if(NULL == memory)
00310                         {
00311                             on_error_("Failed to map view of file");
00312                         }
00313                         else
00314                         {
00315                             m_memory    =   memory;
00316                             m_cb        =   requestSize;
00317                         }
00318                     }
00319                 }
00320             }
00321         }
00322     }
00324 
00327 public:
00337     ss_explicit_k memory_mapped_file(ws_char_a_t const* fileName)
00338         : m_cb(0)
00339         , m_memory(NULL)
00340     {
00341         open_(fileName, 0, 0);
00342     }
00344     ss_explicit_k memory_mapped_file(ws_char_w_t const* fileName)
00345         : m_cb(0)
00346         , m_memory(NULL)
00347     {
00348         open_(fileName, 0, 0);
00349     }
00351     template <ss_typename_param_k S>
00352     ss_explicit_k memory_mapped_file(S const& fileName)
00353         : m_cb(0)
00354         , m_memory(NULL)
00355     {
00356         open_(stlsoft_ns_qual(c_str_ptr)(fileName), 0, 0);
00357     }
00358 
00359 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00369     memory_mapped_file(
00370         ws_char_a_t const*  fileName
00371     ,   offset_type         offset
00372     ,   ws_uint32_t         requestSize
00373     )
00374         : m_cb(0)
00375         , m_memory(NULL)
00376     {
00377         open_(fileName, offset, requestSize);
00378     }
00388     memory_mapped_file(
00389         ws_char_w_t const*  fileName
00390     ,   offset_type         offset
00391     ,   ws_uint32_t         requestSize
00392     )
00393         : m_cb(0)
00394         , m_memory(NULL)
00395     {
00396         open_(fileName, offset, requestSize);
00397     }
00407     template <ss_typename_param_k S>
00408     memory_mapped_file(
00409         S const&    fileName
00410     ,   offset_type offset
00411     ,   ws_uint32_t requestSize
00412     )
00413         : m_cb(0)
00414         , m_memory(NULL)
00415     {
00416         open_(stlsoft_ns_qual(c_str_ptr)(fileName), offset, requestSize);
00417     }
00418 #endif 
00419 
00421     ~memory_mapped_file() stlsoft_throw_0()
00422     {
00423         WINSTL_ASSERT(is_valid());
00424 
00425         if(NULL != m_memory)
00426         {
00427             ::UnmapViewOfFile(m_memory);
00428         }
00429     }
00430 
00432     void swap(class_type& rhs) stlsoft_throw_0()
00433     {
00434         WINSTL_ASSERT(is_valid());
00435 
00436         std_swap(m_cb, rhs.m_cb);
00437         std_swap(m_memory, rhs.m_memory);
00438 #ifndef STLSOFT_CF_EXCEPTION_SUPPORT
00439         std_swap(m_lastError, rhs.m_lastError);
00440 #endif 
00441 
00442         WINSTL_ASSERT(is_valid());
00443     }
00445 
00448 public:
00450     void const* memory() const
00451     {
00452         return m_memory;
00453     }
00455     size_type size() const
00456     {
00457         return m_cb;
00458     }
00459 
00460 #ifndef STLSOFT_CF_EXCEPTION_SUPPORT
00462     error_type lastError() const
00463     {
00464         return m_lastError;
00465     }
00466 #endif 
00468 
00471 private:
00472     void on_error_(
00473         char const* message
00474     ,   error_type  error = ::GetLastError()
00475     )
00476     {
00477 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00478         
00479         
00480         
00481         windows_exception_policy    xp;
00482 
00483         xp(message, error);
00484 #else 
00485 
00486         STLSOFT_SUPPRESS_UNUSED(message);
00487 
00488         m_lastError = error;
00489 #endif 
00490     }
00491 
00492     bool_type is_valid() const
00493     {
00494 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00495         if((NULL != m_memory) != (0 != m_cb))
00496         {
00497             return false;
00498         }
00499 #endif 
00500 
00501         return true;
00502     }
00504 
00507 private:
00508     size_type   m_cb;
00509     void*       m_memory;
00510 #ifndef STLSOFT_CF_EXCEPTION_SUPPORT
00511     error_type  m_lastError;
00512 #endif 
00514 
00517 private:
00518     memory_mapped_file(class_type const&);
00519     class_type& operator =(class_type const&);
00521 };
00522 
00523 
00524 
00525 
00526 
00527 #ifdef STLSOFT_UNITTEST
00528 # include "./unittest/memory_mapped_file_unittest_.h"
00529 #endif 
00530 
00531 
00532 
00533 
00534 
00535 #ifndef _WINSTL_NO_NAMESPACE
00536 # if defined(_STLSOFT_NO_NAMESPACE) || \
00537      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00538 } 
00539 # else
00540 } 
00541 } 
00542 # endif 
00543 #endif 
00544 
00545 namespace std
00546 {
00547 
00548     inline void swap(
00549         winstl_ns_qual(memory_mapped_file)& lhs
00550     ,   winstl_ns_qual(memory_mapped_file)& rhs
00551     )
00552     {
00553         lhs.swap(rhs);
00554     }
00555 
00556 } 
00557 
00558 
00559 
00560 #endif 
00561 
00562