blob: 1e76c1c58fe2579c097a742f23dafde7525fc52c [file] [log] [blame]
//===-- MIUtilFileStd.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Third party headers
#include <assert.h>
#include <cerrno>
#include <stdio.h>
#include <string.h> // For strerror()
// In-house headers:
#include "MICmnResources.h"
#include "MIUtilFileStd.h"
#include "lldb/Host/FileSystem.h"
#include "llvm/Support/ConvertUTF.h"
//++
//------------------------------------------------------------------------------------
// Details: CMIUtilFileStd constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMIUtilFileStd::CMIUtilFileStd()
: m_fileNamePath(CMIUtilString()), m_pFileHandle(nullptr)
#if defined(_MSC_VER)
,
m_constCharNewLine("\r\n")
#else
,
m_constCharNewLine("\n")
#endif // #if defined( _MSC_VER )
,
m_bFileError(false) {
}
//++
//------------------------------------------------------------------------------------
// Details: CMIUtilFileStd destructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMIUtilFileStd::~CMIUtilFileStd() { Close(); }
//++
//------------------------------------------------------------------------------------
// Details: Open file for writing. On the first call to this function after
// *this object
// is created the file is either created or replace, from then on open
// only opens
// an existing file.
// Type: Method.
// Args: vFileNamePath - (R) File name path.
// vwrbNewCreated - (W) True - file recreated, false - file appended
// too.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath,
bool &vwrbNewCreated) {
// Reset
m_bFileError = false;
vwrbNewCreated = false;
if (vFileNamePath.empty()) {
m_bFileError = true;
SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
return MIstatus::failure;
}
// File is already open so exit
if (m_pFileHandle != nullptr)
return MIstatus::success;
#if !defined(_MSC_VER)
// Open with 'write' and 'binary' mode
m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb");
#else
// Open a file with exclusive write and shared read permissions
std::wstring path;
if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR);
else {
errno = EINVAL;
m_pFileHandle = nullptr;
}
#endif // !defined( _MSC_VER )
if (m_pFileHandle == nullptr) {
m_bFileError = true;
SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE),
strerror(errno), vFileNamePath.c_str());
return MIstatus::failure;
}
vwrbNewCreated = true;
m_fileNamePath = vFileNamePath;
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// Details: Write data to existing opened file.
// Type: Method.
// Args: vData - (R) Text data.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMIUtilFileStd::Write(const CMIUtilString &vData) {
if (vData.size() == 0)
return MIstatus::success;
if (m_bFileError)
return MIstatus::failure;
if (m_pFileHandle == nullptr) {
m_bFileError = true;
SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
m_fileNamePath.c_str());
return MIstatus::failure;
}
// Get the string size
MIuint size = vData.size();
if (::fwrite(vData.c_str(), 1, size, m_pFileHandle) == size) {
// Flush the data to the file
::fflush(m_pFileHandle);
return MIstatus::success;
}
// Not all of the data has been transferred
m_bFileError = true;
SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
m_fileNamePath.c_str());
return MIstatus::failure;
}
//++
//------------------------------------------------------------------------------------
// Details: Write data to existing opened file.
// Type: Method.
// Args: vData - (R) Text data.
// vCharCnt - (R) Text data length.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt) {
if (vCharCnt == 0)
return MIstatus::success;
if (m_bFileError)
return MIstatus::failure;
if (m_pFileHandle == nullptr) {
m_bFileError = true;
SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
m_fileNamePath.c_str());
return MIstatus::failure;
}
if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) {
// Flush the data to the file
::fflush(m_pFileHandle);
return MIstatus::success;
}
// Not all of the data has been transferred
m_bFileError = true;
SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
m_fileNamePath.c_str());
return MIstatus::failure;
}
//++
//------------------------------------------------------------------------------------
// Details: Close existing opened file. Note Close() must must an open!
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
void CMIUtilFileStd::Close() {
if (m_pFileHandle == nullptr)
return;
::fclose(m_pFileHandle);
m_pFileHandle = nullptr;
// m_bFileError = false; Do not reset as want to remain until next attempt at
// open or create
}
//++
//------------------------------------------------------------------------------------
// Details: Retrieve state of whether the file is ok.
// Type: Method.
// Args: None.
// Return: True - file ok.
// False - file has a problem.
// Throws: None.
//--
bool CMIUtilFileStd::IsOk() const { return !m_bFileError; }
//++
//------------------------------------------------------------------------------------
// Details: Status on a file existing already.
// Type: Method.
// Args: vFileNamePath.
// Return: True - Exists.
// False - Not found.
// Throws: None.
//--
bool CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const {
if (vFileNamePath.empty())
return false;
FILE *pTmp = nullptr;
pTmp = ::fopen(vFileNamePath.c_str(), "wb");
if (pTmp != nullptr) {
::fclose(pTmp);
return true;
}
return false;
}
//++
//------------------------------------------------------------------------------------
// Details: Retrieve the file current carriage line return characters used.
// Type: Method.
// Args: None.
// Return: CMIUtilString & - Text.
// Throws: None.
//--
const CMIUtilString &CMIUtilFileStd::GetLineReturn() const {
return m_constCharNewLine;
}
//++
//------------------------------------------------------------------------------------
// Details: Given a file name directory path, strip off the filename and return
// the path.
// It look for either backslash or forward slash.
// Type: Method.
// Args: vDirectoryPath - (R) Text directory path.
// Return: CMIUtilString - Directory path.
// Throws: None.
//--
CMIUtilString
CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath) {
const size_t nPos = vDirectoryPath.rfind('\\');
size_t nPos2 = vDirectoryPath.rfind('/');
if ((nPos == std::string::npos) && (nPos2 == std::string::npos))
return vDirectoryPath;
if (nPos > nPos2)
nPos2 = nPos;
const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str());
return strPath;
}
//++
//------------------------------------------------------------------------------------
// Details: Return either backslash or forward slash appropriate to the OS this
// application
// is running on.
// Type: Static method.
// Args: None.
// Return: char - '/' or '\' character.
// Throws: None.
//--
char CMIUtilFileStd::GetSlash() {
#if !defined(_MSC_VER)
return '/';
#else
return '\\';
#endif // !defined( _MSC_VER )
}