/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a zlib-style license that can
* be found in the License.txt file in the root of the source tree.
*/
//---------------------------------------------------------------------------
#include "ZenLib/PreComp.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "ZenLib/Conf_Internal.h"
//---------------------------------------------------------------------------
#include "ZenLib/FileName.h"
//---------------------------------------------------------------------------
#ifdef ZENLIB_USEWX
#include <wx/file.h>
#include <wx/filename.h>
#include <wx/utils.h>
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
#ifdef WINDOWS
#else
#include <cstdio>
#endif
#include <sys/stat.h>
#if !defined(WINDOWS)
#include <unistd.h>
#endif //!defined(WINDOWS)
#include <fstream>
using namespace std;
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
#endif
#elif defined WINDOWS
#undef __TEXT
#include <windows.h>
#ifdef WINDOWS_UWP
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.storage.h>
#include <windows.storage.accesscache.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::Storage;
using namespace ABI::Windows::Storage::Streams;
using namespace ABI::Windows::Storage::FileProperties;
#endif
#endif
#endif //ZENLIB_USEWX
#include "ZenLib/OS_Utils.h"
#include "ZenLib/File.h"
//---------------------------------------------------------------------------
#ifdef WINDOWS_UWP
struct WrtFile
{
ComPtr<IStorageFile> File;
ComPtr<IRandomAccessStream> Buffer;
};
#endif
//---------------------------------------------------------------------------
namespace ZenLib
{
//---------------------------------------------------------------------------
// Debug
#ifdef ZENLIB_DEBUG
#include <stdio.h>
#include <windows.h>
namespace ZenLib_File_Debug
{
FILE* F;
std::string Debug;
SYSTEMTIME st_In;
void Debug_Open(bool Out)
{
F=fopen("C:\\Temp\\ZenLib_Debug.txt", "a+t");
Debug.clear();
SYSTEMTIME st;
GetLocalTime( &st );
char Duration[100];
if (Out)
{
FILETIME ft_In;
if (SystemTimeToFileTime(&st_In, &ft_In))
{
FILETIME ft_Out;
if (SystemTimeToFileTime(&st, &ft_Out))
{
ULARGE_INTEGER UI_In;
UI_In.HighPart=ft_In.dwHighDateTime;
UI_In.LowPart=ft_In.dwLowDateTime;
ULARGE_INTEGER UI_Out;
UI_Out.HighPart=ft_Out.dwHighDateTime;
UI_Out.LowPart=ft_Out.dwLowDateTime;
ULARGE_INTEGER UI_Diff;
UI_Diff.QuadPart=UI_Out.QuadPart-UI_In.QuadPart;
FILETIME ft_Diff;
ft_Diff.dwHighDateTime=UI_Diff.HighPart;
ft_Diff.dwLowDateTime=UI_Diff.LowPart;
SYSTEMTIME st_Diff;
if (FileTimeToSystemTime(&ft_Diff, &st_Diff))
{
sprintf(Duration, "%02hd:%02hd:%02hd.%03hd", st_Diff.wHour, st_Diff.wMinute, st_Diff.wSecond, st_Diff.wMilliseconds);
}
else
strcpy(Duration, " ");
}
else
strcpy(Duration, " ");
}
else
strcpy(Duration, " ");
}
else
{
st_In=st;
strcpy(Duration, " ");
}
fprintf(F," %02hd:%02hd:%02hd.%03hd %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, Duration);
}
void Debug_Close()
{
Debug += "\r\n";
fwrite(Debug.c_str(), Debug.size(), 1, F); \
fclose(F);
}
}
using namespace ZenLib_File_Debug;
#define ZENLIB_DEBUG1(_NAME,_TOAPPEND) \
Debug_Open(false); \
Debug+=", ";Debug+=_NAME; \
_TOAPPEND; \
Debug_Close();
#define ZENLIB_DEBUG2(_NAME,_TOAPPEND) \
Debug_Open(true); \
Debug+=", ";Debug+=_NAME; \
_TOAPPEND; \
Debug_Close();
#else // ZENLIB_DEBUG
#define ZENLIB_DEBUG1(_NAME,_TOAPPEND)
#define ZENLIB_DEBUG2(_NAME,_TOAPPEND)
#endif // ZENLIB_DEBUG
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
//---------------------------------------------------------------------------
File::File()
{
#ifdef ZENLIB_USEWX
File_Handle=NULL;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
File_Handle=NULL;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
File_Handle=NULL;
#else
File_Handle=INVALID_HANDLE_VALUE;
#endif
#endif
#endif //ZENLIB_USEWX
Position=(int64u)-1;
Size=(int64u)-1;
}
File::File(Ztring File_Name, access_t Access)
{
#ifdef ZENLIB_USEWX
File_Handle=NULL;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
File_Handle=NULL;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
File_Handle=NULL;
#else
File_Handle=INVALID_HANDLE_VALUE;
#endif
#endif
#endif //ZENLIB_USEWX
Position=(int64u)-1;
Size=(int64u)-1;
Open(File_Name, Access);
}
//---------------------------------------------------------------------------
File::~File()
{
Close();
}
//***************************************************************************
// Open/Close
//***************************************************************************
//---------------------------------------------------------------------------
bool File::Open (const tstring &File_Name_, access_t Access)
{
Close();
ZENLIB_DEBUG1( "File Open",
Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
File_Name=File_Name_;
#ifdef ZENLIB_USEWX
File_Handle=(void*)new wxFile();
if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
{
//Sometime the file is locked for few milliseconds, we try again later
wxMilliSleep(1000);
if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
//File is not openable
return false;
}
return true;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
/*
int access;
switch (Access)
{
case Access_Read : access=O_BINARY|O_RDONLY ; break;
case Access_Write : access=O_BINARY|O_WRONLY|O_CREAT|O_TRUNC ; break;
case Access_Read_Write : access=O_BINARY|O_RDWR |O_CREAT ; break;
case Access_Write_Append : access=O_BINARY|O_WRONLY|O_CREAT|O_APPEND ; break;
default : access=0 ;
}
#ifdef UNICODE
File_Handle=open(File_Name.To_Local().c_str(), access);
#else
File_Handle=open(File_Name.c_str(), access);
#endif //UNICODE
return File_Handle!=-1;
*/
ios_base::openmode mode;
switch (Access)
{
case Access_Write : mode=ios_base::binary|ios_base::in|ios_base::out; break;
case Access_Read_Write : mode=ios_base::binary|ios_base::in|ios_base::out; break;
case Access_Write_Append : if (!Exists(File_Name))
mode=ios_base::binary|ios_base::out;
else
mode=ios_base::binary|ios_base::out|ios_base::app;
break;
default : mode = ios_base::binary | ios_base::in;
}
#ifdef UNICODE
File_Handle=new fstream(File_Name.To_Local().c_str(), mode);
#else
File_Handle=new fstream(File_Name.c_str(), mode);
#endif //UNICODE
if (!((fstream*)File_Handle)->is_open())
{
delete (fstream*)File_Handle; File_Handle=NULL;
return false;
}
return true;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
File_Handle=new WrtFile();
FileAccessMode Desired_Mode;
StorageOpenOptions Share_Mode;
switch (Access)
{
case Access_Read: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
case Access_Write:
case Access_Read_Write:
case Access_Write_Append: Desired_Mode=FileAccessMode_ReadWrite; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
default: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_None;
}
// Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
File_Name.FindAndReplace(__T("/"), __T("\\"));
if (FAILED(Get_File(HStringReference(File_Name.c_str(), (unsigned int)File_Name.size()), ((WrtFile*)File_Handle)->File)))
{
if (Access==Access_Write || Access==Access_Read_Write || Access==Access_Write_Append)
{
if (!Create(File_Name, false))
{
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
if (Access==Access_Write_Append)
{
Size_Get();
if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
{
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
}
return true;
}
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
//IStorageFile don't provide OpenWithOptionsAsync
ComPtr<IStorageFile2> File2;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
{
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open;
if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open)) ||
FAILED(Await(Async_Open)) ||
FAILED(Async_Open->GetResults(&((WrtFile*)File_Handle)->Buffer))
|| !((WrtFile*)File_Handle)->Buffer)
{
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
if (Access==Access_Write_Append)
{
Size_Get();
if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
{
ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
return false;
}
}
else
Position=0;
#else
DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
switch (Access)
{
case Access_Read : dwDesiredAccess=FILE_READ_DATA; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_EXISTING; break;
case Access_Write : dwDesiredAccess=GENERIC_WRITE; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS; break;
case Access_Read_Write : dwDesiredAccess=FILE_READ_DATA|GENERIC_WRITE; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS; break;
case Access_Write_Append : dwDesiredAccess = FILE_APPEND_DATA; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; dwCreationDisposition = OPEN_ALWAYS; break;
default : dwDesiredAccess=0; dwShareMode=0; dwCreationDisposition=0; break;
}
#ifdef UNICODE
File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#else
File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#endif //UNICODE
#if 0 //Disabled
if (File_Handle==INVALID_HANDLE_VALUE)
{
//Sometimes the file is locked for few milliseconds, we try again later
DWORD dw = GetLastError();
if (dw!=ERROR_FILE_NOT_FOUND)
{
/*
char lpMsgBuf[1000];
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
lpMsgBuf,
1000, NULL );
*/
Sleep(1000);
#ifdef UNICODE
File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#else
File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#endif //UNICODE
}
}
#endif //0
if (File_Handle==INVALID_HANDLE_VALUE)
{
ZENLIB_DEBUG2( "File Open",
Debug+=", returns 0";)
//File is not openable
return false;
}
ZENLIB_DEBUG2( "File Open",
Debug+=", returns 1";)
if (Access == Access_Write_Append)
Size_Get();
else
Position = 0;
#endif
return true;
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Create (const Ztring &File_Name_, bool OverWrite)
{
Close();
ZENLIB_DEBUG1( "File Create",
Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
File_Name=File_Name_;
#ifdef ZENLIB_USEWX
File_Handle=(void*)new wxFile();
if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
{
//Sometime the file is locked for few milliseconds, we try again later
wxMilliSleep(3000);
if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
//File is not openable
return false;
}
return true;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
/*
int access;
switch (OverWrite)
{
case false : access=O_BINARY|O_CREAT|O_WRONLY|O_EXCL ; break;
default : access=O_BINARY|O_CREAT|O_WRONLY|O_TRUNC; break;
}
#ifdef UNICODE
File_Handle=open(File_Name.To_Local().c_str(), access);
#else
File_Handle=open(File_Name.c_str(), access);
#endif //UNICODE
return File_Handle!=-1;
*/
/*ios_base::openmode mode;
switch (OverWrite)
{
//case false : mode= ; break;
default : mode=0 ; break;
}*/
ios_base::openmode access;
if (!OverWrite && Exists(File_Name))
return false;
access=ios_base::binary|ios_base::in|ios_base::out|ios_base::trunc;
#ifdef UNICODE
File_Handle=new fstream(File_Name.To_Local().c_str(), access);
#else
File_Handle=new fstream(File_Name.c_str(), access);
#endif //UNICODE
return ((fstream*)File_Handle)->is_open();
#elif defined WINDOWS
#ifdef WINDOWS_UWP
File_Handle=new WrtFile();
FileAccessMode Desired_Mode=FileAccessMode_ReadWrite;
StorageOpenOptions Share_Mode=StorageOpenOptions_AllowReadersAndWriters;
CreationCollisionOption Collision_Option=CreationCollisionOption_FailIfExists;
if (OverWrite)
Collision_Option=CreationCollisionOption_ReplaceExisting;
//Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
File_Name.FindAndReplace(__T("/"), __T("\\"));
//Split file and folder
tstring Destination_Dir=FileName::Path_Get(File_Name);
tstring Destination_File=FileName::Name_Get(File_Name);
//Open dst folder
ComPtr<IStorageFolder> Folder;
if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
return false;
//Create file
ComPtr<IAsyncOperation<StorageFile*> > Async_Create;
ComPtr<IStorageFile> File;
if (FAILED(Folder->CreateFileAsync(HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Create)) ||
FAILED(Await(Async_Create)) ||
FAILED(Async_Create->GetResults(&((WrtFile*)File_Handle)->File)) ||
!((WrtFile*)File_Handle)->File)
return false;
//IStorageFile don't provide OpenWithOptionsAsync
ComPtr<IStorageFile2> File2;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
return false;
ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open_File;
if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open_File)) ||
FAILED(Await(Async_Open_File)) ||
FAILED(Async_Open_File->GetResults(&((WrtFile*)File_Handle)->Buffer)) ||
!((WrtFile*)File_Handle)->Buffer)
return false;
return true;
#else
DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
if (OverWrite) {
dwDesiredAccess=GENERIC_WRITE;
dwCreationDisposition=CREATE_ALWAYS;
} else {
dwDesiredAccess=GENERIC_WRITE;
dwCreationDisposition=CREATE_NEW;
}
dwShareMode=0;
#ifdef UNICODE
File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#else
File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#endif //UNICODE
#if 0 //Disabled
if (File_Handle==INVALID_HANDLE_VALUE)
{
//Sometime the file is locked for few milliseconds, we try again later
Sleep(3000);
#ifdef UNICODE
File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#else
File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
#endif //UNICODE
}
#endif //0
if (File_Handle==INVALID_HANDLE_VALUE)
{
ZENLIB_DEBUG2( "File Create",
Debug+=", returns 0";)
//File is not openable
return false;
}
ZENLIB_DEBUG2( "File Create",
Debug+=", returns 1";)
#endif
return true;
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
void File::Close ()
{
#ifdef ZENLIB_DEBUG
bool isOpen=false;
#ifdef ZENLIB_USEWX
if (File_Handle!=NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle!=NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (File_Handle)
#else
if (File_Handle!=INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
{
ZENLIB_DEBUG1( "File Close",
Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8();)
isOpen=true;
}
#endif
#ifdef ZENLIB_USEWX
delete (wxFile*)File_Handle; File_Handle=NULL;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
//close(File_Handle); File_Handle=-1;
delete (fstream*)File_Handle; File_Handle=NULL;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
delete(WrtFile*)File_Handle; File_Handle=NULL;
#else
CloseHandle(File_Handle); File_Handle=INVALID_HANDLE_VALUE;
#endif
#endif
#endif //ZENLIB_USEWX
Position=(int64u)-1;
Size=(int64u)-1;
#ifdef ZENLIB_DEBUG
if (isOpen)
{
ZENLIB_DEBUG2( "File Close",
)
}
#endif
}
//***************************************************************************
// Read/Write
//***************************************************************************
//---------------------------------------------------------------------------
size_t File::Read (int8u* Buffer, size_t Buffer_Size_Max)
{
ZENLIB_DEBUG1("File Read",
Debug += ", File_Name="; Debug += Ztring(File_Name).To_UTF8(); Debug += ", MaxSize="; Debug += Ztring::ToZtring(Buffer_Size_Max).To_UTF8())
#ifdef ZENLIB_USEWX
if (File_Handle == NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle == NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
boolean Can_Read=FALSE;
if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanRead(&Can_Read)) || !Can_Read)
#else
if (File_Handle == INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return 0;
#ifdef ZENLIB_USEWX
size_t ByteRead=((wxFile*)File_Handle)->Read(Buffer, Buffer_Size_Max);
Position+=ByteRead;
return ByteRead;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
//return read((int)File_Handle, Buffer, Buffer_Size_Max);
if (Position==(int64u)-1)
Position_Get();
if (Size==(int64u)-1)
Size_Get();
if (Position!=(int64u)-1 && Position+Buffer_Size_Max>Size)
Buffer_Size_Max=(size_t)(Size-Position); //We don't want to enable eofbit (impossible to seek after)
((fstream*)File_Handle)->read((char*)Buffer, Buffer_Size_Max);
size_t ByteRead=((fstream*)File_Handle)->gcount();
Position+=ByteRead;
return ByteRead;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IInputStream> Stream;
if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
return 0;
ComPtr<IDataReaderFactory> Reader_Factory;
if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &Reader_Factory)) || !Reader_Factory)
return 0;
ComPtr<IDataReader> Reader;
if (FAILED(Reader_Factory->CreateDataReader(*Stream.GetAddressOf(), &Reader)) || !Reader)
return 0;
UINT32 Readed=0;
ComPtr<IAsyncOperation<UINT32> > Async_Read;
if (FAILED(Reader->LoadAsync((UINT32)Buffer_Size_Max, &Async_Read)) ||
FAILED(Await(Async_Read)) ||
FAILED(Async_Read->GetResults(&Readed)))
return 0;
if (FAILED(Reader->ReadBytes((UINT32)Buffer_Size_Max, (BYTE*)Buffer)))
return 0;
Reader->DetachStream(&Stream);
return (size_t)Readed;
#else
DWORD Buffer_Size;
if (ReadFile(File_Handle, Buffer, (DWORD)Buffer_Size_Max, &Buffer_Size, NULL))
{
Position+=Buffer_Size;
ZENLIB_DEBUG2( "File Read",
Debug+=", new position ";Debug+=Ztring::ToZtring(Position).To_UTF8();;Debug+=", returns ";Debug+=Ztring::ToZtring((int64u)Buffer_Size).To_UTF8();)
return Buffer_Size;
}
else
{
ZENLIB_DEBUG2( "File Read",
Debug+=", returns 0";)
return 0;
}
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
size_t File::Write (const int8u* Buffer, size_t Buffer_Size)
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
boolean Can_Write=FALSE;
if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return 0;
#ifdef ZENLIB_USEWX
return ((wxFile*)File_Handle)->Write(Buffer, Buffer_Size);
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
//return write(File_Handle, Buffer, Buffer_Size);
((fstream*)File_Handle)->write((char*)Buffer, Buffer_Size);
if (((fstream*)File_Handle)->bad())
{
Position=(int64u)-1;
return 0;
}
else
{
if (Position!=(int64u)-1)
Position+=Buffer_Size;
return Buffer_Size;
}
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IOutputStream> Stream;
if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
return 0;
ComPtr<IDataWriterFactory> Writer_Factory;
if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), &Writer_Factory)) || !Writer_Factory)
return 0;
ComPtr<IDataWriter> Writer;
if (FAILED(Writer_Factory->CreateDataWriter(*Stream.GetAddressOf(), &Writer)) || !Writer)
return 0;
if (FAILED(Writer->WriteBytes((UINT32)Buffer_Size, (BYTE*)Buffer)))
return 0;
UINT32 Written=0;
ComPtr<IAsyncOperation<UINT32> > Async_Write;
if (FAILED(Writer->StoreAsync(&Async_Write)) ||
FAILED(Await(Async_Write)) ||
FAILED(Async_Write->GetResults(&Written)))
return 0;
Writer->DetachStream(&Stream);
return (size_t)Written;
#else
DWORD Buffer_Size_Written;
if (WriteFile(File_Handle, Buffer, (DWORD)Buffer_Size, &Buffer_Size_Written, NULL))
{
if (Position!=(int64u)-1)
Position+=Buffer_Size_Written;
return Buffer_Size_Written;
}
else
{
Position=(int64u)-1;
return 0;
}
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Truncate (int64u Offset)
{
if (File_Handle==NULL)
return false;
#ifdef ZENLIB_USEWX
return false; //Not supported
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
#if defined(WINDOWS)
return false; //Not supported
#else //defined(WINDOWS)
//Need to close the file, use truncate, reopen it
#if !defined(__ANDROID_API__) || __ANDROID_API__ >= 21
if (Offset==(int64u)-1)
Offset=Position_Get();
Ztring File_Name_Sav=File_Name;
Close();
truncate(File_Name_Sav.To_Local().c_str(), Offset);
if (!Open(File_Name_Sav, Access_Read_Write))
return false;
GoTo(0, FromEnd);
return true;
#else
return false; //Not supported
#endif
#endif //!defined(WINDOWS)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
boolean Can_Write=FALSE;
if (!((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
return false;
ComPtr<IOutputStream> Stream;
if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
return false;
if (Offset==(int64u)-1)
{
if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Position_Get())))
return false;
}
else
{
if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Offset)))
return false;
}
return true;
#else
if(Offset!=(int64u)-1 && Offset!=Position_Get())
if (!GoTo(Offset))
return false;
SetEndOfFile(File_Handle);
return true;
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
size_t File::Write (const Ztring &ToWrite)
{
std::string AnsiString=ToWrite.To_UTF8();
return Write((const int8u*)AnsiString.c_str(), AnsiString.size());
}
//***************************************************************************
// Moving
//***************************************************************************
//---------------------------------------------------------------------------
bool File::GoTo (int64s Position_ToMove, move_t MoveMethod)
{
ZENLIB_DEBUG1( "File GoTo",
Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8(); Debug+="File GoTo: "; Debug +=Ztring(File_Name).To_UTF8(); Debug+=", MoveMethod="; Debug +=Ztring::ToZtring(MoveMethod).To_UTF8(); Debug+=", MaxSize="; Debug +=Ztring::ToZtring(Position_ToMove).To_UTF8())
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return false;
Position=(int64u)-1; //Disabling memory
#ifdef ZENLIB_USEWX
return ((wxFile*)File_Handle)->Seek(Position, (wxSeekMode)MoveMethod)!=wxInvalidOffset; //move_t and wxSeekMode are same
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
/*
int fromwhere;
switch (MoveMethod)
{
case FromBegin : fromwhere=SEEK_SET; break;
case FromCurrent : fromwhere=SEEK_CUR; break;
case FromEnd : fromwhere=SEEK_END; break;
default : fromwhere=SEEK_CUR; break;
}
return lseek(File_Handle, Position, fromwhere)!=-1;
*/
ios_base::seekdir dir;
switch (MoveMethod)
{
case FromBegin : dir=ios_base::beg; break;
case FromCurrent : dir=ios_base::cur; break;
case FromEnd : dir=ios_base::end; break;
default : dir=ios_base::beg;
}
((fstream*)File_Handle)->seekg((streamoff)Position_ToMove, dir);
return !((fstream*)File_Handle)->fail();
#elif defined WINDOWS
#ifdef WINDOWS_UWP
UINT64 New_Position=0;
switch (MoveMethod)
{
case FromBegin : New_Position=Position_ToMove; break;
case FromCurrent : New_Position=Position_Get()+Position_ToMove; break;
case FromEnd : New_Position=Size_Get()-Position_ToMove; break;
default : New_Position=Position_ToMove;
}
if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(New_Position)))
return false;
return true;
#else
LARGE_INTEGER GoTo;
GoTo.QuadPart=Position_ToMove;
BOOL i=SetFilePointerEx(File_Handle, GoTo, NULL, MoveMethod);
#ifdef ZENLIB_DEBUG
LARGE_INTEGER Temp; Temp.QuadPart=0;
SetFilePointerEx(File_Handle, Temp, &Temp, FILE_CURRENT);
ZENLIB_DEBUG2( "File GoTo",
Debug+=", new position ";Debug+=Ztring::ToZtring(Temp.QuadPart).To_UTF8();Debug+=", returns ";Debug+=i?'1':'0';)
#endif //ZENLIB_DEBUG
return i?true:false;
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
int64u File::Position_Get ()
{
if (Position!=(int64u)-1)
return Position;
ZENLIB_DEBUG1( "File Position_Get",
Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
#else
if (File_Handle == INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return (int64u)-1;
#ifdef ZENLIB_USEWX
return (int64u)-1;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
Position=((fstream*)File_Handle)->tellg();
return Position;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (FAILED(((WrtFile*)File_Handle)->Buffer->get_Position((UINT64*)&Position)))
return (int64u)-1;
#else
LARGE_INTEGER GoTo; GoTo.QuadPart=0;
GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, FILE_CURRENT);
Position=GoTo.QuadPart;
ZENLIB_DEBUG2( "File GoTo",
Debug+=", new position ";Debug+=Ztring::ToZtring(GoTo.QuadPart).To_UTF8();Debug+=", returns 1";)
#endif
return Position;
#endif
#endif //ZENLIB_USEWX
}
//***************************************************************************
// Attributes
//***************************************************************************
//---------------------------------------------------------------------------
int64u File::Size_Get()
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return 0;
#ifdef ZENLIB_USEWX
return ((wxFile*)File_Handle)->Length();
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
/*
int CurrentPos=lseek(File_Handle, 0, SEEK_CUR);
int64u File_Size;
File_Size=lseek(File_Handle, 0, SEEK_END);
lseek(File_Handle, CurrentPos, SEEK_SET);
*/
fstream::pos_type CurrentPos=((fstream*)File_Handle)->tellg();
if (CurrentPos!=(fstream::pos_type)-1)
{
((fstream*)File_Handle)->seekg(0, ios_base::end);
Size=((fstream*)File_Handle)->tellg();
((fstream*)File_Handle)->seekg(CurrentPos);
}
else
Size=(int64u)-1;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IStorageItem> Item;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return (int64u)-1;
ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
ComPtr<IBasicProperties> Properties;
if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
FAILED(Await(Async_Properties)) ||
FAILED(Async_Properties->GetResults(&Properties)) ||
!Properties)
return (int64u)-1;
if (FAILED(Properties->get_Size(&Size)))
return (int64u)-1;
#else
LARGE_INTEGER x = {0};
BOOL bRet = ::GetFileSizeEx(File_Handle, &x);
if (bRet == FALSE)
return (int64u)-1;
Size=x.QuadPart;
#endif
#endif
return Size;
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
Ztring File::Created_Get()
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return Ztring();
#ifdef ZENLIB_USEWX
return __T(""); //Not implemented
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
return __T(""); //Not implemented
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IStorageItem> Item;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return __T("");
DateTime Time;
if (FAILED(Item->get_DateCreated(&Time)))
return __T("");
return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
#else
FILETIME TimeFT;
if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
{
int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
return Time;
}
else
return __T(""); //There was a problem
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
#if defined WINDOWS
static Ztring Calc_Time(const FILETIME& TimeFT)
{
int64u Time64 = 0x100000000ULL * TimeFT.dwHighDateTime + TimeFT.dwLowDateTime;
TIME_ZONE_INFORMATION Info;
DWORD Result = GetTimeZoneInformation(&Info);
if (Result != TIME_ZONE_ID_INVALID)
{
Time64 -= ((int64s)Info.Bias) * 60 * 1000 * 1000 * 10;
if (Result == TIME_ZONE_ID_DAYLIGHT)
Time64 -= ((int64s)Info.DaylightBias) * 60 * 1000 * 1000 * 10;
else
Time64 -= ((int64s)Info.StandardBias) * 60 * 1000 * 1000 * 10;
}
Ztring Time; Time.Date_From_Milliseconds_1601(Time64 / 10000);
Time.FindAndReplace(__T("UTC "), __T(""));
return Time;
}
#endif
//---------------------------------------------------------------------------
Ztring File::Created_Local_Get()
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return Ztring();
#ifdef ZENLIB_USEWX
return __T(""); //Not implemented
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
return __T(""); //Not implemented
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IStorageItem> Item;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return __T("");
DateTime Time;
if (FAILED(Item->get_DateCreated(&Time)))
return __T("");
FILETIME File_Time;
ULARGE_INTEGER Time_Union;
Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
File_Time.dwHighDateTime=Time_Union.HighPart;
File_Time.dwLowDateTime=Time_Union.LowPart;
return Calc_Time(File_Time);
#else
FILETIME TimeFT;
if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
{
return Calc_Time(TimeFT);
}
else
return __T(""); //There was a problem
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
Ztring File::Modified_Get()
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return Ztring();
#ifdef ZENLIB_USEWX
return __T(""); //Not implemented
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
struct stat Stat;
int Result=stat(File_Name.To_Local().c_str(), &Stat);
if (Result<0)
return __T(""); //Error
Ztring Time; Time.Date_From_Seconds_1970((int64s)Stat.st_mtime);
return Time;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IStorageItem> Item;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return __T("");
ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
ComPtr<IBasicProperties> Properties;
if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
FAILED(Await(Async_Properties)) ||
FAILED(Async_Properties->GetResults(&Properties)) ||
!Properties)
return __T("");
DateTime Time;
if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
return __T("");
return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
#else
FILETIME TimeFT;
if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
{
int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
return Time;
}
else
return __T(""); //There was a problem
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
Ztring File::Modified_Local_Get()
{
#ifdef ZENLIB_USEWX
if (File_Handle==NULL)
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
if (File_Handle==NULL)
#elif defined WINDOWS
#ifdef WINDOWS_UWP
if (!File_Handle || !((WrtFile*)File_Handle)->File)
#else
if (File_Handle==INVALID_HANDLE_VALUE)
#endif
#endif
#endif //ZENLIB_USEWX
return Ztring();
#ifdef ZENLIB_USEWX
return __T(""); //Not implemented
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
struct stat Stat;
int Result=stat(File_Name.To_Local().c_str(), &Stat);
if (Result<0)
return __T(""); //Error
Ztring Time; Time.Date_From_Seconds_1970_Local(Stat.st_mtime);
return Time;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
ComPtr<IStorageItem> Item;
if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return __T("");
ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
ComPtr<IBasicProperties> Properties;
if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
FAILED(Await(Async_Properties)) ||
FAILED(Async_Properties->GetResults(&Properties)) ||
!Properties)
return __T("");
DateTime Time;
if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
return __T("");
FILETIME File_Time;
ULARGE_INTEGER Time_Union;
Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
File_Time.dwHighDateTime=Time_Union.HighPart;
File_Time.dwLowDateTime=Time_Union.LowPart;
return Calc_Time(File_Time);
#else
FILETIME TimeFT;
if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
{
return Calc_Time(TimeFT);
}
else
return __T(""); //There was a problem
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Opened_Get()
{
#ifdef ZENLIB_USEWX
return File_Handle!=NULL;
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
//return File_Handle!=-1;
return File_Handle!=NULL && ((fstream*)File_Handle)->is_open();
#elif defined WINDOWS
#ifdef WINDOWS_UWP
return File_Handle && ((WrtFile*)File_Handle)->File && ((WrtFile*)File_Handle)->Buffer;
#else
return File_Handle!=INVALID_HANDLE_VALUE;
#endif
#endif
#endif //ZENLIB_USEWX
}
//***************************************************************************
// Helpers
//***************************************************************************
//---------------------------------------------------------------------------
int64u File::Size_Get(const Ztring &File_Name)
{
File F(File_Name);
return F.Size_Get();
}
//---------------------------------------------------------------------------
Ztring File::Created_Get(const Ztring &File_Name)
{
File F(File_Name);
return F.Created_Get();
}
//---------------------------------------------------------------------------
Ztring File::Modified_Get(const Ztring &File_Name)
{
File F(File_Name);
return F.Modified_Get();
}
//---------------------------------------------------------------------------
bool File::Exists(const Ztring &File_Name)
{
ZENLIB_DEBUG1( "File Exists",
Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
#ifdef ZENLIB_USEWX
wxFileName FN(File_Name.c_str());
return FN.FileExists();
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
#if defined WINDOWS
if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
return false;
#endif //defined WINDOWS
struct stat buffer;
int status;
#ifdef UNICODE
status=stat(File_Name.To_Local().c_str(), &buffer);
#else
status=stat(File_Name.c_str(), &buffer);
#endif //UNICODE
return status==0 && S_ISREG(buffer.st_mode);
#elif defined WINDOWS
if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
return false;
#ifdef WINDOWS_UWP
//Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
Ztring File_Name_=File_Name;
File_Name_.FindAndReplace(__T("/"), __T("\\"));
//Try to access file directly
ComPtr<IStorageFile> File;
if (SUCCEEDED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File)))
return true;
//Try directory access methods
tstring Dir_=FileName::Path_Get(File_Name_);
tstring File_=FileName::Name_Get(File_Name_);
ComPtr<IStorageFolder> Folder;
if (FAILED(Get_Folder(HStringReference(Dir_.c_str(), (unsigned int)Dir_.size()), Folder)))
return false;
//IStorageFolder don't provide TryGetItemAsync
ComPtr<IStorageFolder2> Folder2;
if (FAILED(Folder->QueryInterface(IID_PPV_ARGS(&Folder2))) || !Folder2)
return false;
ComPtr<IAsyncOperation<IStorageItem*> > Async_GetItem;
ComPtr<IStorageItem> Item;
ComPtr<IStorageFile> AsFile;
if (SUCCEEDED(Folder2->TryGetItemAsync(HStringReference(File_.c_str(), (unsigned int)File_.size()).Get(), &Async_GetItem)) &&
SUCCEEDED(Await(Async_GetItem)) &&
SUCCEEDED(Async_GetItem->GetResults(&Item)) &&
Item &&
SUCCEEDED(Item.As(&AsFile)))
return true;
return false;
#else
#ifdef UNICODE
DWORD FileAttributes=GetFileAttributesW(File_Name.c_str());
#else
DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
#endif //UNICODE
ZENLIB_DEBUG2( "File Exists",
Debug+=", File_Name="; Debug+=Ztring::ToZtring(((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY))?1:0).To_UTF8())
return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite)
{
#ifdef ZENLIB_USEWX
return wxCopyFile(Source.c_str(), Destination.c_str(), OverWrite);
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
return false;
#elif defined WINDOWS
#ifdef WINDOWS_UWP
NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
if (OverWrite)
Collision_Option=NameCollisionOption_ReplaceExisting;
//Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
Ztring Source_=Source;
Source_.FindAndReplace(__T("/"), __T("\\"));
Ztring Destination_=Destination;
Destination_.FindAndReplace(__T("/"), __T("\\"));
//Split destination file and folder
tstring Destination_Dir=FileName::Path_Get(Destination_);
tstring Destination_File=FileName::Name_Get(Destination_);
//Open src file
ComPtr<IStorageFile> File;
if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
return false;
//Open dst folder
ComPtr<IStorageFolder> Folder;
if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
return false;
//Copy file
ComPtr<IAsyncOperation<StorageFile*> > Async_Copy;
ComPtr<IStorageFile> New_File;
if (FAILED(File->CopyOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Copy)) ||
FAILED(Await(Async_Copy)) ||
FAILED(Async_Copy->GetResults(&New_File)) ||
!New_File)
return false;
return true;
#else
#ifdef UNICODE
return CopyFileW(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
#else
return CopyFile(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
#endif //UNICODE
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Move(const Ztring &Source, const Ztring &Destination, bool OverWrite)
{
if (OverWrite && Exists(Source))
Delete(Destination);
#ifdef ZENLIB_USEWX
if (OverWrite && Exists(Destination))
wxRemoveFile(Destination.c_str());
return wxRenameFile(Source.c_str(), Destination.c_str());
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
return !std::rename(Source.To_Local().c_str(), Destination.To_Local().c_str());
#elif defined WINDOWS
#ifdef WINDOWS_UWP
NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
if (OverWrite)
Collision_Option=NameCollisionOption_ReplaceExisting;
//Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
Ztring Source_=Source;
Source_.FindAndReplace(__T("/"), __T("\\"));
Ztring Destination_=Destination;
Destination_.FindAndReplace(__T("/"), __T("\\"));
//Split destination file and folder
tstring Destination_Dir=FileName::Path_Get(Destination_);
tstring Destination_File=FileName::Name_Get(Destination_);
//Open src file
ComPtr<IStorageFile> File;
if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
return false;
//Open dst folder
ComPtr<IStorageFolder> Folder;
if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
return false;
//Move file
ComPtr<IAsyncAction> Async_Move;
if (FAILED(File->MoveOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Move)) ||
FAILED(Await(Async_Move)) ||
FAILED(Async_Move->GetResults()))
return false;
return true;
#else
#ifdef UNICODE
return MoveFileExW(Source.c_str(), Destination.c_str(), 0)!=0;
#else
return MoveFileEx(Source.c_str(), Destination.c_str(), 0)!=0;
#endif //UNICODE
#endif
#endif
#endif //ZENLIB_USEWX
}
//---------------------------------------------------------------------------
bool File::Delete(const Ztring &File_Name)
{
#ifdef ZENLIB_USEWX
return wxRemoveFile(File_Name.c_str());
#else //ZENLIB_USEWX
#ifdef ZENLIB_STANDARD
#ifdef UNICODE
return unlink(File_Name.To_Local().c_str())==0;
#else
return unlink(File_Name.c_str())==0;
#endif //UNICODE
#elif defined WINDOWS
#ifdef WINDOWS_UWP
//Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
Ztring File_Name_=File_Name;
File_Name_.FindAndReplace(__T("/"), __T("\\"));
ComPtr<IStorageFile> File_;
if (FAILED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File_)))
return false;
ComPtr<IStorageItem> Item;
if (FAILED(File_->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
return false;
ComPtr<IAsyncAction> Async_Delete;
if (FAILED(Item->DeleteAsync(StorageDeleteOption_Default, &Async_Delete)) ||
FAILED(Await(Async_Delete)) ||
FAILED(Async_Delete->GetResults()))
return false;
return true;
#else
#ifdef UNICODE
return DeleteFileW(File_Name.c_str())!=0;
#else
return DeleteFile(File_Name.c_str())!=0;
#endif //UNICODE
#endif
#endif
#endif //ZENLIB_USEWX
}
//***************************************************************************
//
//***************************************************************************
} //namespace
↑ V303 The function 'SetFilePointer' is deprecated in the Win64 system. It is safer to use the 'SetFilePointerEx' function.
↑ V525 The code contains the collection of similar blocks. Check items '3', '4', '4', '4' in lines 362, 363, 364, 365.
↑ V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.