Skip to content

Commit

Permalink
Merge pull request #35 from deadem/pr34
Browse files Browse the repository at this point in the history
Pr34
  • Loading branch information
deadem authored Oct 16, 2023
2 parents 49586fd + 2f81e34 commit 6cf521d
Show file tree
Hide file tree
Showing 17 changed files with 468 additions and 422 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ ipch
.vs/
*.aps
linter.vcxproj.user
enc_temp_folder/
30 changes: 30 additions & 0 deletions FilePipe.cpp
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());
}
}
19 changes: 19 additions & 0 deletions FilePipe.h
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
88 changes: 88 additions & 0 deletions HandleWrapper.cpp
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;
}
33 changes: 33 additions & 0 deletions HandleWrapper.h
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ Optional attribute `stdin`="1" can be used to lint from stdin instead of temp fi
<linter stdin="1" extension=".js" command="C:\Users\deadem\AppData\Roaming\npm\eslint.cmd --stdin --format checkstyle"/>
```

To handle spaces in names, you should use the &quot; quote character, as follows:

```xml
<linter extension=".none" command="&quot;C:\a command with spaces\thing&quot; --stuff" />
```

Optional parameter

You can change default colors by an optional "style" tag. "color" attribute is a RGB hex color value, "alpha" value can range from 0 (completely transparent) to 255 (no transparency).
Expand Down
38 changes: 38 additions & 0 deletions SourceLocation.h
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
78 changes: 78 additions & 0 deletions SystemError.cpp
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());
}
40 changes: 40 additions & 0 deletions SystemError.h
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
Loading

0 comments on commit 6cf521d

Please sign in to comment.