You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

156 lines
4.3 KiB

/**
* Platform compatibility layer for POSIX functions on Windows
*/
#ifndef PLATFORM_COMPAT_H
#define PLATFORM_COMPAT_H
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <io.h>
#include <time.h>
// POSIX functions missing on Windows
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
// poll() implementation for Windows
#ifndef POLLIN
#define POLLIN 0x0001
#endif
#ifndef POLLOUT
#define POLLOUT 0x0004
#endif
#ifndef POLLERR
#define POLLERR 0x0008
#endif
#ifndef POLLHUP
#define POLLHUP 0x0010
#endif
#ifndef POLLNVAL
#define POLLNVAL 0x0020
#endif
#ifndef POLLPRI
#define POLLPRI 0x0002
#endif
struct pollfd {
int fd;
short events;
short revents;
};
// gettimeofday for Windows
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
(void)tz;
if (tv) {
FILETIME ft;
ULARGE_INTEGER ull;
GetSystemTimeAsFileTime(&ft);
ull.LowPart = ft.dwLowDateTime;
ull.HighPart = ft.dwHighDateTime;
// Convert from 100-nanosecond intervals since 1601 to Unix epoch
tv->tv_sec = (long)(ull.QuadPart / 10000000ULL - 11644473600ULL);
tv->tv_usec = (long)((ull.QuadPart % 10000000ULL) / 10);
}
return 0;
}
// Pipe creation for Windows
static inline int pipe(int pipefd[2]) {
return _pipe(pipefd, 4096, _O_BINARY);
}
// poll() using select() for Windows
static inline int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
fd_set readfds, writefds, exceptfds;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
int max_fd = -1;
for (nfds_t i = 0; i < nfds; i++) {
if (fds[i].fd < 0) continue;
if (fds[i].events & POLLIN) FD_SET(fds[i].fd, &readfds);
if (fds[i].events & POLLOUT) FD_SET(fds[i].fd, &writefds);
FD_SET(fds[i].fd, &exceptfds);
if (fds[i].fd > max_fd) max_fd = fds[i].fd;
}
struct timeval tv, *ptv = NULL;
if (timeout >= 0) {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ptv = &tv;
}
int ret = select(max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
if (ret < 0) return ret;
// Set revents
for (nfds_t i = 0; i < nfds; i++) {
fds[i].revents = 0;
if (fds[i].fd < 0) continue;
if (FD_ISSET(fds[i].fd, &readfds)) fds[i].revents |= POLLIN;
if (FD_ISSET(fds[i].fd, &writefds)) fds[i].revents |= POLLOUT;
if (FD_ISSET(fds[i].fd, &exceptfds)) fds[i].revents |= POLLERR;
}
return ret;
}
// fcntl replacement for Windows (simplified - only supports F_GETFL/F_SETFL with O_NONBLOCK)
#define F_GETFL 3
#define F_SETFL 4
#define O_NONBLOCK 0x4000
static inline int fcntl(int fd, int cmd, ... /* arg */ ) {
va_list ap;
va_start(ap, cmd);
if (cmd == F_GETFL) {
va_end(ap);
// Return current flags (always 0 on Windows, can't query easily)
return 0;
} else if (cmd == F_SETFL) {
int flags = va_arg(ap, int);
va_end(ap);
if (flags & O_NONBLOCK) {
// Set non-blocking mode
u_long mode = 1;
return ioctlsocket(fd, FIONBIO, &mode);
}
return 0;
}
va_end(ap);
errno = EINVAL;
return -1;
}
// nanosleep replacement
static inline int nanosleep(const struct timespec *req, struct timespec *rem) {
(void)rem;
Sleep((DWORD)(req->tv_sec * 1000 + req->tv_nsec / 1000000));
return 0;
}
#else
// POSIX - include standard headers
#include <sys/time.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#endif
#endif // PLATFORM_COMPAT_H