C++: API C |
C++ C. , .
C C++. , . , , . .
. Tester-Driven Development.
, Tester-driven development — , , ,
++17. , -:
bool DocumentLoader::MakeDocumentWorkdirCopy()
{
std::error_code errorCode;
if (!std::filesystem::exists(m_filepath, errorCode) || errorCode)
{
throw DocumentLoadError(DocumentLoadError::NotFound(), m_filepath, errorCode.message());
}
else
{
// Lock document
HANDLE fileLock = CreateFileW(m_filepath.c_str(),
GENERIC_READ,
0, // Exclusive access
nullptr, // security attributes
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr //template file
);
if (!fileLock)
{
CloseHandle(fileLock);
throw DocumentLoadError(DocumentLoadError::IsLocked(), m_filepath, "cannot lock file");
}
CloseHandle(fileLock);
}
std::filesystem::copy_file(m_filepath, m_documentCopyPath);
}
, :
, - ?
, , . C C++, .
, :
bool DocumentLoader::MakeDocumentWorkdirCopy()
{
boost::system::error_code errorCode;
if (!boost::filesystem::exists(m_filepath, errorCode) || errorCode)
{
throw DocumentLoadError(DocumentLoadError::NotFound(), m_filepath, errorCode.message());
}
else if (!utils::ipc::MakeFileLock(m_filepath))
{
throw DocumentLoadError(DocumentLoadError::IsLocked(), m_filepath, "cannot lock file");
}
fs::copy_file(m_filepath, m_documentCopyPath);
}
, :
C++ . C? , : C fopen
. , out- C , C++ . , C++ RAII .
. , , C++ , C++ API C :
" "!
ifstream, :
int main()
{
try
{
std::ifstream in;
in.exceptions(std::ios::failbit);
in.open("C:/path-that-definitely-not-exist");
}
catch (const std::exception& ex)
{
std::cout << ex.what() << std::endl;
}
try
{
std::ifstream in;
in.exceptions(std::ios::failbit);
in.open("C:/");
}
catch (const std::exception& ex)
{
std::cout << ex.what() << std::endl;
}
}
, , . , . , ?
, API C, : . // ..
.
// ,
#if defined(_MSC_VER)
#define _CRT_SECURE_NO_WARNINGS
#endif
int main()
{
try
{
FILE *in = ::fopen("C:/path-that-definitely-not-exist", "r");
if (!in)
{
throw std::runtime_error("open failed");
}
// .. ..
fclose(in);
}
catch (const std::exception& ex)
{
std::cout << ex.what() << std::endl;
}
}
, C++17, API C.
, . iostream, , , read :
basic_istream& read(char_type* s, std::streamsize count);
iostream, tellg:
// count , filepath
std::string GetFirstFileBytes(const std::filesystem::path& filepath, size_t count)
{
assert(count != 0);
// ,
std::ifstream stream;
stream.exceptions(std::ifstream::failbit);
// : C++17 ifstream
// string, wstring
stream.open(filepath.native(), std::ios::binary);
std::string result(count, '\0');
// count
stream.read(&result[0], count);
// , , .
result = result.substr(0, static_cast(stream.tellg()));
return result;
}
C++ , C — fread
! , C++ wrapper for X, . : C++17.
, RAII . - :
namespace detail
{
// ,
struct FileDeleter
{
void operator()(FILE* ptr)
{
fclose(ptr);
}
};
}
// FileUniquePtr - unique_ptr, fclose
using FileUniquePtr = std::unique_ptr;
::fopen
fopen2
:
// ,
#if defined(_MSC_VER)
#define _CRT_SECURE_NO_WARNINGS
#endif
// , Unicode UNIX-.
FileUniquePtr fopen2(const char* filepath, const char* mode)
{
assert(filepath);
assert(mode);
FILE *file = ::fopen(filepath, mode);
if (!file)
{
throw std::runtime_error("file opening failed");
}
return FileUniquePtr(file);
}
:
, :
- , - , , .
: , , errno . :
// ,
#if defined(_MSC_VER)
#define _CRT_SECURE_NO_WARNINGS
#endif
// , Unicode UNIX-.
FileUniquePtr fopen3(const char* filepath, const char mode)
{
using namespace std::literals; // ""s.
assert(filepath);
assert(mode);
FILE *file = ::fopen(filepath, mode);
if (!file)
{
const char* reason = strerror(errno);
throw std::runtime_error("opening '"s + filepath + "' failed: "s + reason);
}
return FileUniquePtr(file);
}
, :
C++17 , — std::filesystem
. , boost::filesystem
:
boost::filesystem
, Undefined Behaviorfilesystem , path. Unicode Windows:
// VS2017 filesystem experimental
#include
#include
#include filesystem>
#include
#include
#include
namespace fs = std::experimental::filesystem;
FileUniquePtr fopen4(const fs::path& filepath, const char* mode)
{
using namespace std::literals;
assert(mode);
#if defined(_WIN32)
fs::path convertedMode = mode;
FILE *file = ::_wfopen(filepath.c_str(), convertedMode.c_str());
#else
FILE *file = ::fopen(filepath.c_str(), mode);
#endif
if (!file)
{
const char* reason = strerror(errno);
throw std::runtime_error("opening '"s + filepath.u8string() + "' failed: "s + reason);
}
return FileUniquePtr(file);
}
, - . .
, 2017 , , . , VS2017 constexpr if , GCC 8 - if :
-, constexpr if C++17, .
FileUniquePtr fopen5(const fs::path& filepath, const char* mode)
{
using namespace std::literals;
assert(mode);
FILE *file = nullptr;
// path::value_type - wchar_t, wide-
// Windows UTF-16, .
// : wchar_t UTF-16 Windows.
if constexpr (std::is_same_v)
{
fs::path convertedMode = mode;
file = _wfopen(filepath.c_str(), convertedMode.c_str());
}
// , UTF-8 Unicode
else
{
file = fopen(filepath.c_str(), mode);
}
if (!file)
{
const char* reason = strerror(errno);
throw std::runtime_error("opening '"s + filepath.u8string() + "' failed: "s + reason);
}
return FileUniquePtr(file);
}
! C++ , C . , ( ) , IDE .
, — , .
fopen4
- , mode C, , C, WinAPI, CURL OpenGL .
C++ Russia 2016 C++ Russia 2017 , :
, 2013 "C++ Seasoning" Sean Parent. :
, C++ . ---. - C.
. :
C/C++. .