/*
* Copyright (C) 2022-2030 Twilight-Dream
*
* 本文件是 mio 的一部分。
*
* mio 是自由软件:你可以再分发之和/或依照由自由软件基金会发布的 GNU 通用公共许可证修改之,无论是版本 3 许可证,还是(按你的决定)任何以后版都可以。
*
* 发布 TDOM-EncryptOrDecryptFile-Reborn 是希望它能有用,但是并无保障;甚至连可销售和符合某个特定的目的都不保证。请参看 GNU 通用公共许可证,了解详情。
* 你应该随程序获得一份 GNU 通用公共许可证的复本。如果没有,请看 。
*/
/*
* Copyright (C) 2022-2030 Twilight-Dream
*
* This file is part of mio.
*
* mio is free software: you may redistribute it and/or modify it under the GNU General Public License as published by the Free Software Foundation, either under the Version 3 license, or (at your discretion) any later version.
*
* mio is released in the hope that it will be useful, but there are no guarantees; not even that it will be marketable and fit a particular purpose. Please see the GNU General Public License for details.
* You should get a copy of the GNU General Public License with your program. If not, see .
*/
#pragma once
#include "mio/mio.hpp"
//将文件数据进行镜像(映射)到操作系统的内存对象。以实现对磁盘的大文件(这里规定大小大于4GB)的字节流模拟访问和修改
//Mirroring (mapping) file data to the operating system's memory objects. to enable byte stream emulation access and modification of large files (here specified size > 4 giga byte) on disk
namespace MemoryObjectConfrontationDiskFileData
{
/*
Use C++ project mio
Github https://github.com/mandreyel/mio
An easy to use header-only cross-platform C++11 memory mapping library with an MIT license.
mio has been created with the goal to be easily includable (i.e. no dependencies) in any C++ project that needs memory mapped file IO without the need to pull in C++ Boost library.
Please feel free to open an issue, I'll try to address any concerns as best I can.
一个易于使用的头文件跨平台的C++11内存映射库,拥有MIT许可证。
创建mio的目的是为了在任何需要内存映射文件IO的C++项目中都能方便地包含(即没有依赖性),而不需要拉入C++ Boost 库。
请随时提出问题,我将尽力解决任何问题。
*/
template
concept TemplateConcept_MemoryMap = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v;
template
concept TemplateConcept_MemoryMap_ReadAndWrite = std::is_same_v || std::is_same_v;
enum class MemoryMapTypes
{
SIGNED_READ_AND_WRITE = 0,
SIGNED_READ_ONLY = 1,
UNSIGNED_READ_AND_WRITE = 2,
UNSIGNED_READ_ONLY = 3
};
class MemoryMapPointers
{
private:
std::unique_ptr pointer_signed_rw;
std::unique_ptr pointer_signed_ro;
std::unique_ptr pointer_unsigned_rw;
std::unique_ptr pointer_unsigned_ro;
public:
std::unique_ptr& signed_rw()
{
return pointer_signed_rw;
}
std::unique_ptr& signed_ro()
{
return pointer_signed_ro;
}
std::unique_ptr& unsigned_rw()
{
return pointer_unsigned_rw;
}
std::unique_ptr& unsigned_ro()
{
return pointer_unsigned_ro;
}
MemoryMapPointers() noexcept : pointer_signed_rw( nullptr ), pointer_signed_ro( nullptr ), pointer_unsigned_rw( nullptr ), pointer_unsigned_ro( nullptr ) {}
MemoryMapPointers(MemoryMapPointers& _object) = delete;
MemoryMapPointers& operator=(const MemoryMapPointers _object) = delete;
MemoryMapPointers( MemoryMapTypes map_types )
{
switch ( map_types )
{
case MemoryMapTypes::SIGNED_READ_AND_WRITE:
{
this->pointer_signed_rw = std::unique_ptr>( new mio::mmap_sink, std::default_delete() );
break;
}
case MemoryMapTypes::SIGNED_READ_ONLY:
{
this->pointer_signed_ro = std::unique_ptr>( new mio::mmap_source, std::default_delete() );
break;
}
case MemoryMapTypes::UNSIGNED_READ_AND_WRITE:
{
this->pointer_unsigned_rw = std::unique_ptr>( new mio::ummap_sink, std::default_delete() );
break;
}
case MemoryMapTypes::UNSIGNED_READ_ONLY:
{
this->pointer_unsigned_ro = std::unique_ptr>( new mio::ummap_source, std::default_delete() );
break;
}
default:
break;
}
}
~MemoryMapPointers()
{
if ( !( pointer_signed_rw == nullptr ) )
{
auto* pointer = pointer_signed_rw.release();
pointer = nullptr;
}
if ( !( pointer_signed_ro == nullptr ) )
{
auto* pointer = pointer_signed_ro.release();
pointer = nullptr;
}
if ( !( pointer_unsigned_rw == nullptr ) )
{
auto* pointer = pointer_unsigned_rw.release();
pointer = nullptr;
}
if ( !( pointer_unsigned_ro == nullptr ) )
{
auto* pointer = pointer_unsigned_ro.release();
pointer = nullptr;
}
}
};
template
requires TemplateConcept_MemoryMap
bool MMMO_CheckIsAssocisatedFile( MemoryMapType& mapped_object );
inline MemoryMapPointers MakeDefaultMemoryMappingObject( MemoryMapTypes map_types );
template
requires TemplateConcept_MemoryMap
std::tuple MMMO_TryAssociateFile_ToPack( const std::filesystem::path& file_path_name, MemoryMapType* memory_map_pointer );
template
requires TemplateConcept_MemoryMap
bool MMMO_FromUnpack( std::tuple& associated_data, MemoryMapType& default_memory_map_object);
template
requires TemplateConcept_MemoryMap_ReadAndWrite
void MMMO_TrySyncDiskFile( MemoryMapType_ReadAndWrite& mapped );
template
requires TemplateConcept_MemoryMap
bool UnmappingMemoryMapObject( MemoryMapType& mapped );
template
requires TemplateConcept_MemoryMap
inline bool MMMO_CheckIsAssocisatedFile( MemoryMapType& mapped_object )
{
if ( !mapped_object.is_mapped() )
{
std::cerr << CommonToolkit::from_u8string(u8"你开玩笑呢?这个内存映射对象根本就没有关联一个文件。") << std::endl;
std::cerr << "Are you kidding me? This memory mapped object is not associated with a file at all." << std::endl;
return false;
}
else
{
return true;
}
}
//创建一个内存映射对象
//Create a memory map object
inline MemoryMapPointers MakeDefaultMemoryMappingObject( MemoryMapTypes map_types )
{
return MemoryMapPointers( map_types );
}
//提供一个内存映射对象,然后尝试关联文件
//Provide a memory map object and then try to associate the file
template
requires TemplateConcept_MemoryMap
std::tuple MMMO_TryAssociateFile_ToPack( const std::filesystem::path& file_path_name, MemoryMapType* memory_map_pointer )
{
auto this_file_path_name = std::move( file_path_name );
auto& memory_map_reference = *memory_map_pointer;
if constexpr( std::same_as, mio::mmap_sink> || std::same_as, mio::ummap_sink> )
{
std::fstream file_stream_object;
if ( std::filesystem::exists( file_path_name ) )
{
std::u8string u8string_extension_name = u8".newfile";
this_file_path_name += CommonToolkit::from_u8string(u8string_extension_name);
std::filesystem::copy(file_path_name, this_file_path_name);
//文件打开后立即寻找流的末端
//seek to the end of stream immediately after open
file_stream_object.open( this_file_path_name, std::ios::in | std::ios::out | std::ios::ate | std::ios::binary );
if(file_stream_object.is_open())
{
//立即关闭文件
//Close the file now
file_stream_object.close();
}
}
}
memory_map_reference.map( this_file_path_name.string(), 0, mio::map_entire_file );
if ( !memory_map_reference.is_open() )
{
std::cerr << CommonToolkit::from_u8string(u8"呃,你确定那个文件的路径确实存在吗?你需要好好检查一下。") << std::endl;
std::cerr << "Uh, are you sure the path to that file actually exists? You need to check it properly." << std::endl;
std::cerr << CommonToolkit::from_u8string(u8"内存映射对象无效,可能是文件无法访问或者内存不足。\n文件路径是: ")
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
std::cerr << "The memory mapped object is invalid, probably because the file is inaccessible or out of memory.\nThe file path is. "
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
UnmappingMemoryMapObject( memory_map_reference );
return std::make_tuple( std::move( false ), std::move( memory_map_reference ) );
}
else
{
if ( MMMO_CheckIsAssocisatedFile( memory_map_reference ) )
{
std::cout << CommonToolkit::from_u8string(u8"内存映射对象已经关联文件\n文件路径是: ")
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
std::cout << "The memory mapped object has associated files.\nThe file path is: "
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
return std::make_tuple( std::move( true ), std::move( memory_map_reference ) );
}
else
{
std::cerr << CommonToolkit::from_u8string(u8"内存映射对象不能关联文件,文件路径是: ")
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
std::cerr << "The memory mapped objects cannot be associated with files.\nThe file path is. "
<< "[" << CommonToolkit::from_u8string(file_path_name.u8string()) << "]" << std::endl;
UnmappingMemoryMapObject( memory_map_reference );
return std::make_tuple( std::move( false ), std::move( memory_map_reference ) );
}
}
}
template
requires TemplateConcept_MemoryMap
bool MMMO_FromUnpack( std::tuple& associated_data, MemoryMapType& default_memory_map_object )
{
#if __cplusplus >= 201703L
auto& [associated_mmap_data_package_status, memory_map_object] = associated_data;
if ( associated_mmap_data_package_status )
{
default_memory_map_object = std::move( memory_map_object );
return associated_mmap_data_package_status;
}
else
{
return associated_mmap_data_package_status;
}
#else
bool associated_mmap_data_package_status = std::get( associated_data );
if ( associated_mmap_data_package_status )
{
default_memory_map_object = std::move( std::get( associated_data ) );
return associated_mmap_data_package_status;
}
else
{
return associated_mmap_data_package_status;
}
#endif
}
//已经映射完成的内存对象,只要内存对象管理的数据发生改变时,就需要同步磁盘文件数据进行写入
//Whenever the memory object is mapped, the data managed by the memory object is changed, the disk file data needs to be synchronized for writing.
template
requires TemplateConcept_MemoryMap_ReadAndWrite
void MMMO_TrySyncDiskFile( MemoryMapType_ReadAndWrite& mapped_object )
{
if ( mapped_object.is_open() && mapped_object.is_mapped() )
{
std::cout << CommonToolkit::from_u8string(u8"好了,试着把内存映射对象管理的数据的变化同步到磁盘上。") << std::endl;
std::cout << "OK, try synchronizing the changes in the data managed by the memory mapped object to the disk." << std::endl;
mapped_object.sync();
}
}
//提供一个内存映射对象,然后解除关联文件。
//Provide a memory map object and then unassociate the file
template
requires TemplateConcept_MemoryMap
inline bool UnmappingMemoryMapObject( MemoryMapType& mapped_object )
{
if ( MMMO_CheckIsAssocisatedFile( mapped_object ) )
{
mapped_object.unmap();
return true;
}
else
{
return false;
}
}
//测试代码是否可以被编译
//Test if the code can be compiled
#if 0
MemoryMapPointers mmp_pointer_object = MakeDefaultMemoryMappingObject(MIO_LibraryHelper::MemoryMapTypes::SIGNED_READ_AND_WRITE);
auto* managed_pointer = mmp_pointer_object.signed_rw().get();
auto associated_mmap_data_package = MMMO_TryAssociateFile_ToPack(std::string("./filename.dat"), managed_pointer);
bool associated_mmap_data_unpackage_status;
auto mapped_object = MMMO_FromUnpack(associated_mmap_data_package, associated_mmap_data_unpackage_status);
MMMO_TrySyncDiskFile(mapped_object);
bool unmake_status = UnmappingMemoryMapObject(mapped_object);
#endif
} // namespace MemoryObjectConfrontationDiskFileData