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