1 /*
2  *  compat.h
3  *  compatibility wrappers
4  *
5  *  Created by Arno Bakker, Victor Grishchenko
6  *  Copyright 2009-2016 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved.
7  *
8  */
9 #ifndef SWIFT_COMPAT_H
10 #define SWIFT_COMPAT_H
11 
12 #ifdef _MSC_VER
13 typedef unsigned char uint8_t;
14 typedef signed char int8_t;
15 typedef unsigned short uint16_t;
16 typedef short int16_t;
17 typedef unsigned int uint32_t;
18 typedef int int32_t;
19 typedef __int64 int64_t;
20 typedef unsigned __int64 uint64_t;
21 #else
22 // Arno, 2013-06-11: Must be defined to get SIZE_MAX in C++
23 #define  __STDC_LIMIT_MACROS
24 #include <stdint.h>
25 #endif
26 
27 #ifdef _WIN32
28 #define NOMINMAX
29 #include <winsock2.h>
30 #include <sys/stat.h>
31 #include <io.h>
32 #include <algorithm> // for std::min/max
33 #include <direct.h>
34 #include <In6addr.h>
35 #include <Ws2tcpip.h>
36 // Arno: PRIu32 stuff for Windows. From http://hg.rabbitmq.com/rabbitmq-c/file/73f65df29956/msinttypes/inttypes.h
37 // Apparently MS VS 2013 has inttypes.h TODO
38 #ifndef PRIu16
39 #define PRIu16       "hu"
40 #define PRId32       "I32d"
41 #define PRIi32       "I32i"
42 #define PRIu32       "I32u"
43 #define PRId64       "I64d"
44 #define PRIi64       "I64i"
45 #define PRIu64       "I64u"
46 #define SCNd32       "ld"
47 #define SCNi32       "li"
48 #define SCNd64       "I64d"
49 #define SCNi64       "I64i"
50 #define SCNx64       "I64x"
51 #endif
52 #else
53 #include <sys/mman.h>
54 #include <arpa/inet.h>
55 #include <sys/select.h>
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <unistd.h>
59 #include <dirent.h>
60 #include <sys/stat.h>
61 // Ric: get rid of printing warnings.. using ISO C99 standard for exact-width integer types
62 #define __STDC_FORMAT_MACROS
63 #include <inttypes.h>
64 #endif
65 
66 #include <limits.h>
67 #include <fcntl.h>
68 #include <cstdio>
69 #include <cstdlib>
70 #include <string>
71 #include <errno.h>
72 #include <math.h>
73 #include <signal.h>
74 
75 #ifdef _MSC_VER
76 #include "getopt_win.h"
77 #else
78 #include <getopt.h>
79 #endif
80 
81 #ifdef _WIN32
82 #define strcasecmp     stricmp
83 #define strtok_r       strtok_s
84 #endif
85 #ifndef S_IRUSR
86 #define S_IRUSR _S_IREAD
87 #endif
88 #ifndef S_IWUSR
89 #define S_IWUSR _S_IWRITE
90 #endif
91 #ifndef S_IRGRP
92 #define S_IRGRP _S_IREAD
93 #endif
94 #ifndef S_IROTH
95 #define S_IROTH _S_IREAD
96 #endif
97 
98 #ifdef _WIN32
99 typedef char* setsockoptptr_t;
100 typedef int socklen_t;
101 #else
102 typedef void* setsockoptptr_t;
103 #endif
104 
105 // libevent2 assumes WIN32 is defined
106 #ifdef _WIN32
107 #ifndef WIN32
108 #define WIN32   _WIN32
109 #endif
110 #endif
111 #include <event2/util.h>
112 
113 #ifndef _WIN32
114 #define INVALID_SOCKET -1
115 #endif
116 
117 #ifndef LONG_MAX
118 #define LONG_MAX    numeric_limits<int>::max()
119 #endif
120 
121 #ifndef log2
122 // log2 is C99 which is not fully supported by MS VS
123 #define log2(x)     (log(x)/log(2.0))
124 #endif
125 
126 
127 // Arno, 2012-01-05: Handle 64-bit size_t & printf+scanf
128 #ifndef SIZE_MAX
129 #error SIZE_MAX undefined, check stdint.h and __STDC_LIMIT_MACROS
130 #endif
131 
132 #ifdef _WIN32
133 #if SIZE_MAX > UINT_MAX
134 #define PRISIZET    "%llu"
135 #else
136 #define PRISIZET    "%u"
137 #endif
138 #else
139 #define PRISIZET    "%zu"
140 #endif
141 
142 #ifdef _WIN32
143 #define ssize_t     SSIZE_T
144 #endif
145 
146 #ifdef _WIN32
147 #define mode_t      int
148 #endif
149 
150 
151 
152 #ifdef _WIN32
153 #define OPENFLAGS         O_RDWR|O_CREAT|_O_BINARY
154 #define ROOPENFLAGS       O_RDONLY|_O_BINARY
155 #else
156 #define OPENFLAGS         O_RDWR|O_CREAT
157 #define ROOPENFLAGS       O_RDONLY
158 #endif
159 
160 #ifdef _WIN32
161 #define FILE_SEP          "\\"
162 #else
163 #define FILE_SEP      "/"
164 #endif
165 
166 namespace swift
167 {
168 
169     /** tint is the time integer type; microsecond-precise. */
170     typedef int64_t tint;
171 #define TINT_HOUR ((swift::tint)1000000*60*60)
172 #define TINT_MIN ((swift::tint)1000000*60)
173 #define TINT_SEC ((swift::tint)1000000)
174 #define TINT_MSEC ((swift::tint)1000)
175 #define TINT_uSEC ((swift::tint)1)
176 #define TINT_NEVER ((swift::tint)0x3fffffffffffffffLL)
177 
178 #ifdef _WIN32
179 #define tintabs _abs64
180 #else
181 #define tintabs ::abs
182 #endif
183 
184 
185     /*
186      * UNICODE
187      *
188      * All filenames, etc. are stored internally as UTF-8 encoded std::strings
189      * which are converted when used to UTF-16 (Windows) or the locale (UNIX).
190      */
191 
192     void print_backtrace(void);
193 
194 // Return UTF-16 representation of utf8str. Caller must free returned value.
195     wchar_t* utf8to16(std::string utf8str);
196     std::string utf16to8(wchar_t* utf16str);
197 
198 // open with filename in UTF-8
199     int open_utf8(const char *pathname, int flags, mode_t mode);
200 
201 // fopen with filename in UTF-8
202     FILE *fopen_utf8(const char *filename, const char *mode);
203 
204 // Returns OS temporary directory in UTF-8 encoding
205     std::string gettmpdir_utf8(void);
206 
207 // Changes current working dir to dirname in UTF-8
208     int chdir_utf8(std::string dirname);
209 
210 // Returns current working directory in UTF-8.
211     std::string getcwd_utf8(void);
212 
213 // Returns the 64-bit size of a filename in UTF-8.
214     int64_t file_size_by_path_utf8(std::string pathname);
215 
216     /* Returns -1 on error, 0 on non-existence, 1 on existence and being a non-dir, 2 on existence and being a dir */
217     int file_exists_utf8(std::string pathname);
218 
219 // mkdir with filename in UTF-8
220     int mkdir_utf8(std::string dirname);
221 
222 // remove with filename in UTF-8
223     int remove_utf8(std::string pathname);
224 
225 // opendir() + readdir() UTF-8 versions
226     class DirEntry
227     {
228     public:
229 #ifdef _WIN32
DirEntry(std::string filename,bool isdir)230         DirEntry(std::string filename, bool isdir) : filename_(filename), isdir_(isdir), hFind_(0) {}
231 #else
232         DirEntry(std::string filename, bool isdir) : filename_(filename), isdir_(isdir), dirp_(NULL) {}
233 #endif
234         std::string filename_;
235         bool isdir_;
236 
237 #ifdef _WIN32
238         HANDLE hFind_;
239 #else
240         DIR *dirp_;
241         std::string basename_;
242 #endif
243     };
244 
245 // Returns NULL on error.
246     DirEntry *opendir_utf8(std::string pathname);
247 
248 // Returns NULL on error, last entry. Automatically does closedir()
249     DirEntry *readdir_utf8(DirEntry *prevde);
250 
251 // return directory part of filename or ""
252     std::string dirname_utf8(std::string pathname);
253 // return non-directory part of filename
254     std::string basename_utf8(std::string pathname);
255 
256     /*
257      * Other filename-less functions
258      */
259 
260     int64_t file_size(int fd);
261 
262     int file_seek(int fd, int64_t offset);
263 
264     int file_resize(int fd, int64_t new_size);
265 
266     void* memory_map(int fd, size_t size=0);
267     void memory_unmap(int fd, void*, size_t size);
268 
269     void print_error(const char* msg);
270 
271 #ifdef _WIN32
272 
273     /** UNIX pread approximation. Does change file pointer. Is not thread-safe */
274     size_t pread(int fildes, void *buf, size_t nbyte, __int64 offset); // off_t not 64-bit dynamically on Win32
275 
276     /** UNIX pwrite approximation. Does change file pointer. Is not thread-safe */
277     size_t pwrite(int fildes, const void *buf, size_t nbyte, __int64 offset);
278 
279     int inet_aton(const char *cp, struct in_addr *inp);
280 
281 #endif
282 
283     tint usec_time();
284 
285     bool make_socket_nonblocking(evutil_socket_t s);
286 
287     bool close_socket(evutil_socket_t sock);
288 
289     struct timeval* tint2tv(tint t);
290 
291 
stringreplace(std::string & source,const std::string & find,const std::string & replace)292     int inline stringreplace(std::string& source, const std::string& find, const std::string& replace)
293     {
294         int num=0;
295         std::string::size_type fLen = find.size();
296         std::string::size_type rLen = replace.size();
297         for (std::string::size_type pos=0; (pos=source.find(find, pos))!=std::string::npos; pos+=rLen) {
298             num++;
299             source.replace(pos, fLen, replace);
300         }
301         return num;
302     }
303 
304     std::string hex2bin(std::string input);
305 
306 };
307 
308 #endif
309 
310