/* * compat.cpp * swift * * Created by Arno Bakker, Victor Grishchenko * Copyright 2009-2016 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved. * */ #include "compat.h" #include "swift.h" #include <sys/stat.h> #include <stdio.h> #include <assert.h> #ifdef _WIN32 #include <tchar.h> #include <io.h> #include <sys/timeb.h> #include <vector> #include <stdexcept> #include <atlbase.h> #else #include <unistd.h> #include <sys/time.h> #endif #include <iostream> #include <sstream> namespace swift { #ifdef _WIN32 static HANDLE map_handles[1024]; #endif int64_t file_size (int fd) { #ifdef WIN32 struct _stat32i64 st; _fstat32i64(fd, &st); #else struct stat st; st.st_size = 0; fstat(fd, &st); #endif return st.st_size; } int file_seek (int fd, int64_t offset) { #ifndef _WIN32 return lseek(fd,offset,SEEK_SET); #else return _lseeki64(fd,offset,SEEK_SET); #endif } int file_resize (int fd, int64_t new_size) { #ifndef _WIN32 return ftruncate(fd, new_size); #else // Arno, 2011-10-27: Use 64-bit version if (_chsize_s(fd,new_size) != 0) return -1; else return 0; #endif } void print_error(const char* msg) { perror(msg); #ifdef _WIN32 int e = WSAGetLastError(); if (e) fprintf(stderr,"windows error #%u\n",e); #endif } void* memory_map (int fd, size_t size) { if (!size) size = file_size(fd); void *mapping; #ifndef _WIN32 mapping = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (mapping==MAP_FAILED) return NULL; return mapping; #else HANDLE fhandle = (HANDLE)_get_osfhandle(fd); HANDLE maphandle = CreateFileMapping( fhandle, NULL, PAGE_READWRITE, 0, 0, NULL ); if (maphandle == NULL) return NULL; map_handles[fd] = maphandle; mapping = MapViewOfFile ( maphandle, FILE_MAP_WRITE, 0, 0, 0 ); return mapping; #endif } void memory_unmap (int fd, void* mapping, size_t size) { #ifndef _WIN32 munmap(mapping,size); close(fd); #else UnmapViewOfFile(mapping); CloseHandle(map_handles[fd]); #endif } #ifdef _WIN32 size_t pread(int fildes, void *buf, size_t nbyte, __int64 offset) { int64_t ret = _lseeki64(fildes,offset,SEEK_SET); if (ret == -1L) return -1; else return read(fildes,buf,nbyte); } size_t pwrite(int fildes, const void *buf, size_t nbyte, __int64 offset) { int64_t ret = _lseeki64(fildes,offset,SEEK_SET); if (ret == -1L) return -1; else return write(fildes,buf,nbyte); } int inet_aton(const char *cp, struct in_addr *inp) { inp->S_un.S_addr = inet_addr(cp); return 1; } #endif #ifdef _WIN32 LARGE_INTEGER get_freq() { LARGE_INTEGER proc_freq; if (!::QueryPerformanceFrequency(&proc_freq)) print_error("HiResTimeOfDay: QueryPerformanceFrequency() failed"); return proc_freq; } tint usec_time(void) { static LARGE_INTEGER last_time; LARGE_INTEGER cur_time; QueryPerformanceCounter(&cur_time); if (cur_time.QuadPart<last_time.QuadPart) print_error("QueryPerformanceCounter wrapped"); // does this happen? last_time = cur_time; static float freq = 1000000.0/get_freq().QuadPart; tint usec = cur_time.QuadPart * freq; return usec; } #else tint usec_time(void) { struct timeval t; gettimeofday(&t,NULL); tint ret; ret = t.tv_sec; ret *= 1000000; ret += t.tv_usec; return ret; } #endif void LibraryInit(void) { #ifdef _WIN32 static WSADATA _WSAData; // win32 requires you to initialize the Winsock DLL with the desired // specification version WORD wVersionRequested; wVersionRequested = MAKEWORD(2, 2); WSAStartup(wVersionRequested, &_WSAData); #endif } /* * UNICODE */ wchar_t* utf8to16(std::string utf8str) { #ifdef _WIN32 CA2W utf16obj(utf8str.c_str(), CP_UTF8); size_t utf16bytelen = (wcslen(utf16obj.m_psz)+1) * sizeof(wchar_t); wchar_t *utf16str = (wchar_t *)malloc(utf16bytelen); wcscpy(utf16str,utf16obj.m_psz); //std::wcerr << "utf8to16: return <" << utf16str << ">" << std::endl; return utf16str; #else return NULL; #endif } std::string utf16to8(wchar_t* utf16str) { #ifdef _WIN32 //std::wcerr << "utf16to8: in " << utf16str << std::endl; CW2A utf8obj(utf16str, CP_UTF8); return std::string(utf8obj.m_psz); #else return "(nul)"; #endif } int open_utf8(const char *filename, int flags, mode_t mode) { #ifdef _WIN32 wchar_t *utf16fn = utf8to16(filename); int ret = _wopen(utf16fn,flags,mode); free(utf16fn); return ret; #else return open(filename,flags,mode); // TODO: UNIX with locale != UTF-8 #endif } FILE *fopen_utf8(const char *filename, const char *mode) { #ifdef _WIN32 wchar_t *utf16fn = utf8to16(filename); wchar_t *utf16mode = utf8to16(mode); FILE *fp = _wfopen(utf16fn,utf16mode); free(utf16fn); free(utf16mode); return fp; #else return fopen(filename,mode); // TODO: UNIX with locale != UTF-8 #endif } int64_t file_size_by_path_utf8(std::string pathname) { int ret = 0; #ifdef WIN32 struct __stat64 st; wchar_t *utf16c = utf8to16(pathname); ret = _wstat64(utf16c, &st); free(utf16c); #else struct stat st; ret = stat(pathname.c_str(), &st); // TODO: UNIX with locale != UTF-8 #endif if (ret < 0) return ret; else return st.st_size; } int file_exists_utf8(std::string pathname) { int ret = 0; #ifdef WIN32 struct __stat64 st; wchar_t *utf16c = utf8to16(pathname); ret = _wstat64(utf16c, &st); free(utf16c); #else struct stat st; ret = stat(pathname.c_str(), &st); // TODO: UNIX with locale != UTF-8 #endif if (ret < 0) { if (errno == ENOENT) return 0; else return ret; } else if (st.st_mode & S_IFDIR) return 2; else return 1; } int mkdir_utf8(std::string dirname) { #ifdef WIN32 wchar_t *utf16c = utf8to16(dirname); int ret = _wmkdir(utf16c); free(utf16c); #else int ret = mkdir(dirname.c_str(),S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); // TODO: UNIX with locale != UTF-8 #endif return ret; } int remove_utf8(std::string pathname) { #ifdef WIN32 wchar_t *utf16c = utf8to16(pathname); int ret = _wremove(utf16c); free(utf16c); #else int ret = remove(pathname.c_str()); // TODO: UNIX with locale != UTF-8 #endif return ret; } #if _DIR_ENT_HAVE_D_TYPE #define TEST_IS_DIR(unixde, st) ((bool)(unixde->d_type & DT_DIR)) #else #define TEST_IS_DIR(unixde, st) ((bool)(S_ISDIR(st.st_mode))) #endif DirEntry *opendir_utf8(std::string pathname) { #ifdef _WIN32 HANDLE hFind; WIN32_FIND_DATAW ffd; std::string pathsearch = pathname + "\\*.*"; wchar_t *pathsearch_utf16 = utf8to16(pathsearch); hFind = FindFirstFileW(pathsearch_utf16, &ffd); free(pathsearch_utf16); if (hFind != INVALID_HANDLE_VALUE) { std::string utf8fn = utf16to8(ffd.cFileName); DirEntry *de = new DirEntry(utf8fn,(bool)((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)); de->hFind_ = hFind; return de; } else return NULL; #else DIR *dirp = opendir( pathname.c_str() ); // TODO: UNIX with locale != UTF-8 if (dirp == NULL) return NULL; struct dirent *unixde = readdir(dirp); if (unixde == NULL) return NULL; else { #if _DIR_ENT_HAVE_D_TYPE if( unixde->d_type == DT_UNKNOWN ) { #endif std::string fullpath = pathname + FILE_SEP; struct stat st; st.st_mode = 0; int ret = stat(fullpath.append(unixde->d_name).c_str(), &st); if (ret < 0) { print_error("failed to stat file in directory"); return NULL; } #if _DIR_ENT_HAVE_D_TYPE if( S_ISDIR(st.st_mode) ) unixde->d_type = DT_DIR; } #endif DirEntry *de = new DirEntry(unixde->d_name,TEST_IS_DIR(unixde, st)); de->dirp_ = dirp; de->basename_ = pathname; return de; } #endif } DirEntry *readdir_utf8(DirEntry *prevde) { #ifdef _WIN32 WIN32_FIND_DATAW ffd; BOOL ret = FindNextFileW(prevde->hFind_, &ffd); if (!ret) { FindClose(prevde->hFind_); return NULL; } else { std::string utf8fn = utf16to8(ffd.cFileName); DirEntry *de = new DirEntry(utf8fn,(bool)((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)); de->hFind_ = prevde->hFind_; return de; } #else struct dirent *unixde = readdir(prevde->dirp_); if (unixde == NULL) { closedir(prevde->dirp_); return NULL; } else { #if _DIR_ENT_HAVE_D_TYPE if( unixde->d_type == DT_UNKNOWN ) { #endif std::string fullpath = prevde->basename_ + FILE_SEP; struct stat st; st.st_mode = 0; int ret = stat(fullpath.append(unixde->d_name).c_str(), &st); if (ret < 0) { print_error("failed to stat file in directory"); return NULL; } #if _DIR_ENT_HAVE_D_TYPE if( S_ISDIR(st.st_mode) ) unixde->d_type = DT_DIR; } #endif DirEntry *de = new DirEntry(unixde->d_name,TEST_IS_DIR(unixde, st)); de->dirp_ = prevde->dirp_; de->basename_ = prevde->basename_; return de; } #endif } std::string gettmpdir_utf8(void) { #ifdef _WIN32 DWORD ret = 0; wchar_t utf16c[MAX_PATH]; ret = GetTempPathW(MAX_PATH,utf16c); if (ret == 0 || ret > MAX_PATH) { return "./"; } else { return utf16to8(utf16c); } #else return "/tmp/"; #endif } int chdir_utf8(std::string dirname) { #ifdef _WIN32 wchar_t *utf16c = utf8to16(dirname); int ret = !::SetCurrentDirectoryW(utf16c); free(utf16c); return ret; #else return chdir(dirname.c_str()); // TODO: UNIX with locale != UTF-8 #endif } std::string getcwd_utf8(void) { #ifdef _WIN32 wchar_t szDirectory[MAX_PATH]; !::GetCurrentDirectoryW(sizeof(szDirectory) - 1, szDirectory); return utf16to8(szDirectory); #else char *cwd = getcwd(NULL,0); std::string cwdstr(cwd); free(cwd); return cwdstr; #endif } std::string dirname_utf8(std::string pathname) { int idx = pathname.rfind(FILE_SEP); if (idx != std::string::npos) { return pathname.substr(0,idx); } else return ""; } bool make_socket_nonblocking(evutil_socket_t fd) { #ifdef _WIN32 u_long enable = 1; return 0==ioctlsocket(fd, FIONBIO, &enable); #else return 0==fcntl(fd, F_SETFL, O_NONBLOCK); #endif } bool close_socket (evutil_socket_t sock) { #ifdef _WIN32 return 0==closesocket(sock); #else return 0==::close(sock); #endif } // Arno: not thread safe! struct timeval* tint2tv (tint t) { static struct timeval tv; tv.tv_usec = t%TINT_SEC; tv.tv_sec = t/TINT_SEC; return &tv; } std::string hex2bin(std::string input) { std::string res; res.reserve(input.size() / 2); for (int i = 0; i < input.size(); i += 2) { std::istringstream iss(input.substr(i, 2)); int temp; iss >> std::hex >> temp; res += static_cast<char>(temp); } return res; } } //E-O-Swift