DWORD ComIface::write(byte* data, int count) {
DWORD NumOfWritten, status;
OVERLAPPED overlap = { 0 };
overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!overlap.hEvent) {
printf("CreateEvent failed with error %d.\n", GetLastError());
return 0;
}
if (!WriteFile(port_handle, data, count, &NumOfWritten, &overlap)) {
status = GetLastError();
if (status != ERROR_IO_PENDING) {
printf("WriteFile failed with error %d.\n", status);
CloseHandle(overlap.hEvent);
return 0;
}
status = WaitForSingleObject(overlap.hEvent, read_delay);
if (status == WAIT_ABANDONED || status == WAIT_FAILED) {
printf("WaitForSingleObject failed with error %d.\n", GetLastError());
}
if (!GetOverlappedResult(port_handle, &overlap, &NumOfWritten, TRUE)) {
printf("GetOverlappedResult failed with error %d.\n", GetLastError());
}
}
CloseHandle(overlap.hEvent);
return NumOfWritten;
}
DWORD ComIface::read(byte* buffer, int size) {
DWORD NumberOfBytesReaded = 0, status = 0;
OVERLAPPED overlap = { 0 };
overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!overlap.hEvent) {
printf("CreateEvent failed with error %d.\n", GetLastError());
return 0;
}
if (!ReadFile(port_handle, buffer, size, NULL, &overlap)) {
status = GetLastError();
if (status != ERROR_IO_PENDING) {
printf("ReadFile failed with error %d.\n", status);
CloseHandle(overlap.hEvent);
return 0;
}
status = WaitForSingleObject(overlap.hEvent, read_delay);
if (status == WAIT_ABANDONED || status == WAIT_FAILED) {
printf("WaitForSingleObject failed with error %d.\n", GetLastError());
}
if (!GetOverlappedResult(port_handle, &overlap, &NumberOfBytesReaded, TRUE)) {
printf("GetOverlappedResult failed with error %d.\n", GetLastError());
}
}
CloseHandle(overlap.hEvent);
return NumberOfBytesReaded;
}
bool ComIface::open(int _port_num, bool log) {
//create port name
wchar_t strbuffer[11];
swprintf_s(strbuffer, 11, L"\\\\.\\COM%d", _port_num);
//create port handle
port_handle = CreateFileW(
strbuffer,
GENERIC_READ | GENERIC_WRITE,
0, //must be opened with exclusive-access
NULL, //default security attributes
OPEN_EXISTING, //must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, //async I/O
NULL //hTemplate must be NULL for comm devices
);
//check if handle is valid
if (port_handle == INVALID_HANDLE_VALUE) {
if (log) {
printf("CreateFileW failed with error %d.\n", GetLastError());
}
return false;
}
//set port settings
if (!SetCommState(port_handle, &dcb)) {
if (log) {
printf("SetCommState failed with error %d.\n", GetLastError());
}
close();
return false;
}
//set port timings
COMMTIMEOUTS timings{
10, /* Maximum time between read chars. */
10, /* Multiplier of characters. */
10, /* Constant in milliseconds. */
10, /* Multiplier of characters. */
10 /* Constant in milliseconds. */
};
SetCommTimeouts(port_handle, &timings);
PurgeComm(port_handle, PURGE_RXCLEAR | PURGE_TXCLEAR);
//set port state
port_num = _port_num;
return true;
}
это не значит, что ReadFile гарантированно завершиться синхронно
#pragma once
#include "type_info.h"
namespace utils {
//template for iterable hashes, where iteration is independannt result
template<typename IN, typename OUT> constexpr inline
OUT iterable_hash(const IN* in, size_t in_size, auto iterable_hash_lamda) {
static_assert(
!(sizeof(OUT) < sizeof(IN)),
"iterable_hash can`t generate output type smaller than input type"
);
static_assert(
!type_in_type_wholes<IN, OUT>(),
"iterable_hash can`t input type must fil entirely output type"
);
//to do "static warning", when sizeof(in)*in_size=OUT
OUT result;
IN* out_pointer = (IN*)&result;
//make result = 0, supports arrays with constant legth (like int[2])
size_t i = type_in_type_capasity<IN, OUT>(), ii = 0;
while (i) {
out_pointer[--i] = 0;
}
//calculate hash, IN size is already a STEP size
i = type_in_type_capasity<IN, OUT>();
while (in_size) {
out_pointer[ii] = iterable_hash_lamda(out_pointer[ii], in[--in_size]);
if (++ii == i) {
ii = 0;
}
}
return result;
}
template<typename IN, typename OUT> constexpr inline
OUT pearson_hash(const IN* in, size_t in_size) {
return iterable_hash<IN, OUT>(
in, in_size,
[](IN& out_step, const IN& in_step) {
return out_step ^ in_step;
}
);
};
}
#pragma once
#include "utils/include/hash.h"
#include <stdint.h>
#include <xstring>
namespace tokenoperator::dte_token {
#define TOKEN_NAME(lpwstr) token_name(lpwstr, std::char_traits<wchar_t>::length(lpwstr))
struct object {
public:
object(uint64_t ID) : ID(ID){}
virtual ~object() {}
uint64_t getID() const {
return ID;
}
protected:
uint64_t ID;
};
constexpr inline uint64_t token_name(const wchar_t* wstr, size_t wstr_len) {
return utils::pearson_hash<wchar_t, uint64_t>(wstr, wstr_len);
}
}
#pragma once
#include "type.h"
namespace tokenoperator::dte_token::data {
template<typename T>
struct value : object {
template <typename U> friend struct value;
public:
value(uint64_t ID = 0) : object(ID), t(ID) {}
template<typename U>
value(const U& v, uint64_t ID = 0) : object(ID), t(ID), v(v) {}
value(const T& v, uint64_t ID = 0) : object(ID), t(ID), v(v) {}
T& get_value() {
return v;
}
type<T> get_type() const {
return t;
}
protected:
T v;
type<T> t;
};
}
constexpr inline uint64_t token_name(const wchar_t* wstr, size_t wstr_len) {
return utils::pearson_hash<wchar_t, uint64_t>(wstr, wstr_len);
}
template<typename IN, typename OUT> constexpr inline
OUT pearson_hash(const IN* in, size_t in_size) {
return iterable_hash<IN, OUT>(
in, in_size,
[](IN& out_step, const IN& in_step) {
return out_step ^ in_step;
}
);
};