-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from deadem/pr34
Pr34
- Loading branch information
Showing
17 changed files
with
468 additions
and
422 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ ipch | |
.vs/ | ||
*.aps | ||
linter.vcxproj.user | ||
enc_temp_folder/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include "stdafx.h" | ||
#include "FilePipe.h" | ||
|
||
#include "SystemError.h" | ||
|
||
Linter::FilePipe::Pipe Linter::FilePipe::create() | ||
{ | ||
SECURITY_ATTRIBUTES security; | ||
|
||
security.nLength = sizeof(SECURITY_ATTRIBUTES); | ||
security.bInheritHandle = TRUE; | ||
security.lpSecurityDescriptor = nullptr; | ||
|
||
HANDLE parent; | ||
HANDLE child; | ||
if (!CreatePipe(&parent, &child, &security, 0)) | ||
{ | ||
throw SystemError(GetLastError()); | ||
} | ||
|
||
return {HandleWrapper(parent), HandleWrapper(child)}; | ||
} | ||
|
||
void Linter::FilePipe::detachFromParent(const HandleWrapper &handle) | ||
{ | ||
if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0)) | ||
{ | ||
throw SystemError(GetLastError()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
#include "HandleWrapper.h" | ||
|
||
namespace Linter | ||
{ | ||
class FilePipe | ||
{ | ||
public: | ||
struct Pipe | ||
{ | ||
HandleWrapper m_reader; | ||
HandleWrapper m_writer; | ||
}; | ||
|
||
static Pipe create(); | ||
static void detachFromParent(const HandleWrapper &handle); | ||
}; | ||
} // namespace Linter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#include "stdafx.h" | ||
#include "HandleWrapper.h" | ||
|
||
#include "SystemError.h" | ||
|
||
using namespace Linter; | ||
|
||
HandleWrapper::HandleWrapper(HANDLE h) : m_handle(h) | ||
{ | ||
if (h == INVALID_HANDLE_VALUE) | ||
{ | ||
throw SystemError(); | ||
} | ||
} | ||
|
||
HandleWrapper::HandleWrapper(HandleWrapper &&other) noexcept : m_handle(std::exchange(other.m_handle, INVALID_HANDLE_VALUE)) | ||
{ | ||
} | ||
|
||
void HandleWrapper::close() const | ||
{ | ||
if (m_handle != INVALID_HANDLE_VALUE) | ||
{ | ||
HANDLE h{std::exchange(m_handle, INVALID_HANDLE_VALUE)}; | ||
CloseHandle(h); | ||
} | ||
} | ||
|
||
HandleWrapper::operator HANDLE() const noexcept | ||
{ | ||
return m_handle; | ||
} | ||
|
||
HandleWrapper::~HandleWrapper() | ||
{ | ||
close(); | ||
} | ||
|
||
void HandleWrapper::writeFile(std::string const &str) const | ||
{ | ||
static_assert(sizeof(str[0]) == 1, "Invalid byte size"); | ||
|
||
char const *start = str.c_str(); | ||
char const *end = start + str.size(); | ||
while (start != end) | ||
{ | ||
const auto toWrite = static_cast<DWORD>(end - start); | ||
DWORD written; | ||
if (!WriteFile(m_handle, start, toWrite, &written, nullptr)) | ||
{ | ||
const DWORD err = GetLastError(); | ||
throw SystemError(err); | ||
} | ||
start += written; | ||
} | ||
} | ||
|
||
std::string HandleWrapper::readFile() const | ||
{ | ||
std::string result; | ||
|
||
std::string buffer; | ||
buffer.resize(0x4000); | ||
|
||
for (;;) | ||
{ | ||
DWORD readBytes; | ||
//The API suggests when the other end closes the pipe, you should get 0. What appears to happen | ||
//is that you get broken pipe. | ||
if (!ReadFile(m_handle, &buffer[0], static_cast<DWORD>(buffer.size()), &readBytes, nullptr)) | ||
{ | ||
DWORD err = GetLastError(); | ||
if (err != ERROR_BROKEN_PIPE) | ||
{ | ||
throw SystemError(err); | ||
} | ||
} | ||
|
||
if (readBytes == 0) | ||
{ | ||
break; | ||
} | ||
|
||
result += std::string(&buffer[0], readBytes); | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
namespace Linter | ||
{ | ||
class HandleWrapper | ||
{ | ||
public: | ||
explicit HandleWrapper(HANDLE h); | ||
HandleWrapper(HandleWrapper const &) = delete; | ||
HandleWrapper(HandleWrapper &&other) noexcept; | ||
HandleWrapper &operator=(HandleWrapper const &) = delete; | ||
HandleWrapper &operator=(HandleWrapper &&other) = delete; | ||
~HandleWrapper(); | ||
|
||
void close() const; | ||
|
||
operator HANDLE() const noexcept; | ||
|
||
/** Write a string to the handle | ||
* | ||
* @param str - string to write | ||
*/ | ||
void writeFile(std::string const &str) const; | ||
|
||
/** Read the entire file */ | ||
std::string readFile() const; | ||
|
||
private: | ||
mutable HANDLE m_handle; | ||
}; | ||
} // namespace Linter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#pragma once | ||
#include <string> | ||
|
||
#if __cplusplus >= 202002L | ||
#include <source_location> | ||
#endif | ||
|
||
namespace Linter | ||
{ | ||
#if __cplusplus >= 202002L | ||
using SourceLocation = std::source_location; | ||
#else | ||
struct SourceLocation | ||
{ | ||
struct Location | ||
{ | ||
unsigned int line() const noexcept | ||
{ | ||
return 0; | ||
} | ||
const char *file_name() const noexcept | ||
{ | ||
return ""; | ||
} | ||
const char *function_name() const noexcept | ||
{ | ||
return ""; | ||
} | ||
}; | ||
static Location current() | ||
{ | ||
return {}; | ||
} | ||
}; | ||
#endif | ||
|
||
using SourceLocationCurrent = decltype(SourceLocation::current()); | ||
} // namespace Linter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include "StdAfx.h" | ||
|
||
#include "SystemError.h" | ||
|
||
#include "encoding.h" | ||
|
||
#include <cstdio> | ||
#include <system_error> | ||
|
||
#include <comdef.h> | ||
#include <winbase.h> | ||
|
||
using namespace Linter; | ||
|
||
SystemError::SystemError(const SourceLocationCurrent &location) : SystemError(GetLastError(), location) | ||
{ | ||
} | ||
|
||
SystemError::SystemError(std::string const &info, const SourceLocationCurrent &location) : SystemError(GetLastError(), info, location) | ||
{ | ||
} | ||
|
||
SystemError::SystemError(DWORD err, const SourceLocationCurrent &location) | ||
{ | ||
// Note: Technically, the message function could fail. | ||
std::snprintf(m_buff, sizeof(m_buff), "%s", std::system_category().message(err).c_str()); | ||
addLocationToMessage(location); | ||
} | ||
|
||
SystemError::SystemError(DWORD err, std::string const &info, const SourceLocationCurrent &location) | ||
{ | ||
// Note: Technically, the message function could fail. | ||
std::snprintf(m_buff, sizeof(m_buff), "%s - %s", info.c_str(), std::system_category().message(err).c_str()); | ||
addLocationToMessage(location); | ||
} | ||
|
||
SystemError::SystemError(HRESULT err, const SourceLocationCurrent &location) | ||
{ | ||
IErrorInfo *err_info{nullptr}; | ||
(void)GetErrorInfo(0, &err_info); | ||
_com_error error{err, err_info}; | ||
std::snprintf(m_buff, sizeof(m_buff), "%s", Encoding::toUTF(std::wstring(error.ErrorMessage())).c_str()); | ||
addLocationToMessage(location); | ||
} | ||
|
||
SystemError::SystemError(HRESULT err, std::string const &info, const SourceLocationCurrent &location) | ||
{ | ||
IErrorInfo *err_info{nullptr}; | ||
(void)GetErrorInfo(0, &err_info); | ||
_com_error error{err, err_info}; | ||
std::snprintf(m_buff, sizeof(m_buff), "%s - %s", info.c_str(), Encoding::toUTF(std::wstring(error.ErrorMessage())).c_str()); | ||
addLocationToMessage(location); | ||
} | ||
|
||
SystemError::~SystemError() = default; | ||
|
||
char const *Linter::SystemError::what() const noexcept | ||
{ | ||
return &m_buff[0]; | ||
} | ||
|
||
void SystemError::addLocationToMessage(const SourceLocationCurrent &location) | ||
{ | ||
const char *fullPath = location.file_name(); | ||
if (fullPath == nullptr || fullPath[0] == 0) | ||
{ | ||
return; | ||
} | ||
|
||
const char *fileName = std::strrchr(fullPath, '\\'); | ||
const std::size_t used{std::strlen(m_buff)}; | ||
std::snprintf(m_buff + used, | ||
sizeof(m_buff) - used, | ||
" at %s:%d %s", | ||
(fileName ? fileName + 1 : fullPath), | ||
location.line(), | ||
location.function_name()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#pragma once | ||
#include "SourceLocation.h" | ||
|
||
#include <exception> | ||
#include <string> | ||
|
||
namespace Linter | ||
{ | ||
class SystemError : public std::exception | ||
{ | ||
|
||
public: | ||
/** Creates an exception object from the current system error */ | ||
explicit SystemError(const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
/** Creates an exception object from the current system error, appends string */ | ||
explicit SystemError(std::string const &, const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
/** Creates an exception object given a system error number */ | ||
explicit SystemError(DWORD err, const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
/** Creates an exception object from specified error with addition information string */ | ||
SystemError(DWORD err, std::string const &, const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
/** Creates an exception object given an HRESULT */ | ||
explicit SystemError(HRESULT err, const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
/** Creates an exception object from specified error with addition information string */ | ||
SystemError(HRESULT err, std::string const &, const SourceLocationCurrent &location = SourceLocation::current()); | ||
|
||
~SystemError(); | ||
|
||
char const *what() const noexcept override; | ||
|
||
private: | ||
char m_buff[2048]; | ||
|
||
void addLocationToMessage(const SourceLocationCurrent &location); | ||
}; | ||
} // namespace Linter |
Oops, something went wrong.