SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
linux_adapter.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2016-2019, SLikeSoft UG (haftungsbeschränkt)
3 *
4 * This source code is licensed under the MIT-style license found in the
5 * license.txt file in the root directory of this source tree.
6 *
7 *
8 * This file defines adapters for all MS-specific functions used throughout SLikeNet.
9 */
10
11 #ifdef __linux__
12 #include "slikenet/linux_adapter.h"
13
14 #include <algorithm> // for std::max, std::min
15 #include <cerrno> // for errno
16 #include <cstdio> // for FILE, fopen, vsnprintf
17 #include <cstdlib> // for mbstowcs
18 #include <cstring> // for strcat, strcpy, strerror, strncat, strncpy
19 #include <cstdarg> // for va_start, va_end, va_list
20 #include <ctime> // for localtime, time_t
21 #include <cwchar> // for wcscat, wcscpy, wcslen
22
23 errno_t fopen_s(FILE **pfile, const char *filename, const char *mode)
24 {
25 if ((pfile == nullptr) || (filename == nullptr) || (mode == nullptr)) {
26 return 22; // error: EINVAL
27 }
28
29 FILE *file = fopen(filename, mode);
30 if (file == nullptr) {
31 return errno;
32 }
33
34 *pfile = file;
35 return 0;
36 }
37
38 errno_t localtime_s(struct tm *_tm, const time_t *time)
39 {
40 // #med - should actually also check for _*time > _MAX_TIME64_T according to MSDN, but can't seem to find the
41 // definition of _MAX_TIME64_T
42 if ((_tm == nullptr) || (time == nullptr) || (*time == 0)) {
43 if (_tm != nullptr) {
44 _tm->tm_hour = -1;
45 _tm->tm_isdst = -1;
46 _tm->tm_mday = -1;
47 _tm->tm_min = -1;
48 _tm->tm_mon = -1;
49 _tm->tm_sec = -1;
50 _tm->tm_wday = -1;
51 _tm->tm_yday = -1;
52 _tm->tm_year = -1;
53 }
54 return 22; // error: EINVAL
55 }
56
57 struct tm *curTime = localtime(time);
58 *_tm = *curTime;
59
60 return 0;
61 }
62
63 errno_t mbstowcs_s(size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count)
64 {
65 if ((mbstr == nullptr) || ((wcstr == nullptr) && (sizeInWords > 0)) || ((wcstr != nullptr) && (sizeInWords != 0))) {
66 if (wcstr != nullptr) {
67 wcstr[0] = L'\0'; // ensure 0-termination
68 }
69 return 22; // error: EINVAL
70 }
71
72 size_t numMaxChars = sizeInWords;
73 if (count != _TRUNCATE) {
74 numMaxChars = std::min(numMaxChars, count);
75 }
76
77 size_t numCharsWritten = mbstowcs(wcstr, mbstr, numMaxChars);
78 if (numCharsWritten == (size_t)-1) {
79 // invalid multibyte character encountered
80 if (pReturnValue != nullptr) {
81 *pReturnValue = 0;
82 }
83 if (wcstr != nullptr) {
84 wcstr[0] = L'\0'; // ensure 0-termination
85 }
86 return 42; // error: EILSEQ
87 }
88
89 if (numCharsWritten == numMaxChars) {
90 if (wcstr != nullptr) {
91 wcstr[0] = L'\0'; // ensure 0-termination
92 }
93 return 34; // error: ERANGE
94 }
95
96 if (pReturnValue != nullptr) {
97 *pReturnValue = numCharsWritten + 1; // chars written, including terminating null character
98 }
99
100 // ensure we write a terminating null character (in case there was none in the original converted string)
101 if (wcstr != nullptr) {
102 wcstr[numCharsWritten] = L'\0'; // ensure 0-termination
103 }
104
105 return 0;
106 }
107
108 int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
109 {
110 if ((buffer == nullptr) || (sizeOfBuffer == 0) || (format == nullptr)) {
111 return -1;
112 }
113
114 va_list arglist;
115 va_start(arglist, format);
116 int numCharsWritten = vsnprintf(buffer, sizeOfBuffer, format, arglist);
117 va_end(arglist);
118
119 if (numCharsWritten == -1) {
120 buffer[0] = '\0'; // error occurred ensure terminating \0-character
121 return -1;
122 }
123
124 if (numCharsWritten >= sizeOfBuffer) {
125 buffer[0] = '\0'; // buffer too small, write empty string to ensure terminating \0-char
126 }
127
128 return numCharsWritten;
129 }
130
131 errno_t strcat_s(char *strDestination, size_t numberOfElements, const char *strSource)
132 {
133 if ((strDestination == nullptr) || (strSource == nullptr)) {
134 if (strDestination != nullptr) {
135 strDestination[0] = '\0'; // ensure trailing \0 is written
136 }
137 return 22; // error: EINVAL
138 }
139
140 if (numberOfElements == 0) {
141 strDestination[0] = '\0'; // ensure trailing \0 is written
142 return 34; // error: ERANGE
143 }
144
145 const size_t destLen = strlen(strDestination);
146 const size_t sourceLen = strlen(strSource);
147 if ((destLen > numberOfElements - 1) || ((sourceLen > 0) && (destLen == numberOfElements - 1)) || (sourceLen > numberOfElements - destLen - 1)) {
148 strDestination[0] = '\0'; // ensure trailing \0 is written
149 return 34; // error: ERANGE
150 }
151
152 (void)strcat(strDestination, strSource);
153 return 0;
154 }
155
156 errno_t strcpy_s(char* strDestination, size_t numberOfElements, const char *strSource)
157 {
158 if ((strDestination == nullptr) || (strSource == nullptr)) {
159 if (strDestination != nullptr) {
160 strDestination[0] = '\0'; // ensure trailing \0 is written
161 }
162 return 22; // error: EINVAL
163 }
164
165 if ((numberOfElements == 0) || (strlen(strSource) >= numberOfElements)) {
166 strDestination[0] = '\0'; // ensure trailing \0 is written
167 return 34; // error: ERANGE
168 }
169
170 (void)strcpy(strDestination, strSource);
171 return 0;
172 }
173
174 errno_t strerror_s(char* buffer, size_t numberOfElements, int errnum)
175 {
176 // check valid parameters
177 if ((buffer == nullptr) || (numberOfElements == 0)) {
178 return 22; // error: EINVAL
179 }
180
181 const char *errorMessage = strerror(errnum);
182 return strcpy_s(buffer, numberOfElements, errorMessage);
183 }
184
185 errno_t strncat_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
186 {
187 // check valid parameters
188 if ((strDest == nullptr) || (strSource == nullptr)) {
189 return 22; // error: EINVAL
190 }
191
192 if (numberOfElements == 0) {
193 return 34; // error: ERANGE
194 }
195
196 size_t charsToWrite;
197 const size_t sourceLen = strlen(strSource);
198 if (count == _TRUNCATE) {
199 charsToWrite = sourceLen;
200 }
201 else {
202 charsToWrite = std::min(count, sourceLen);
203 }
204
205 const size_t destLen = strlen(strDest);
206 const size_t sizeLeft = numberOfElements - destLen;
207
208 if (((count != _TRUNCATE) && (charsToWrite > sizeLeft - 1)) || ((sourceLen > 0) && (destLen == numberOfElements - 1))) {
209 strDest[0] = '\0'; // ensure trailing \0 is written
210 return 34; // error: ERANGE
211 }
212
213 (void)strncat(strDest, strSource, charsToWrite);
214 return 0;
215 }
216
217 errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
218 {
219 // check valid parameters
220 if ((numberOfElements == 0) || (strDest == nullptr) || (strSource == nullptr)) {
221 if (strDest != nullptr) {
222 strDest[0] = '\0'; // ensure trailing \0 is written
223 }
224 return 22; // error: EINVAL
225 }
226
227 size_t numChars;
228 bool truncated = false;
229 if (count == _TRUNCATE) {
230 // if count == _TRUNCATE use the length of the source string
231 numChars = strlen(strSource);
232
233 // ensure we are not exceeding numberOfElements
234 if (numChars >= numberOfElements) {
235 numChars = numberOfElements - 1;
236 truncated = true; // we are going to truncate the copied string
237 }
238 }
239 else {
240 // otherwise we use count, but have to check that the destination buffer is of sufficient size
241 if ((count > numberOfElements) || ((count == numberOfElements) && (strSource[count] != '\0'))) {
242 strDest[0] = '\0'; // ensure trailing \0 is written
243 return 34; // error: ERANGE
244 }
245 numChars = count;
246 }
247
248 (void)strncpy(strDest, strSource, numChars);
249
250 // enforce the trailing \0
251 strDest[numChars] = '\0';
252
253 return truncated ? 80 : 0; // STRUNCATE, if we truncated the string, 0 otherwise
254 }
255
256 int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr)
257 {
258 if ((buffer == nullptr) || (format == nullptr) || (sizeOfBuffer == 0)) {
259 return -1;
260 }
261
262 size_t maxChars = sizeOfBuffer;
263 if (count != _TRUNCATE) {
264 if (count >= sizeOfBuffer) {
265 buffer[0] = '\0'; // ensure trailing \0 is written
266 return -1;
267 }
268 maxChars = count;
269 }
270
271 int numCharsWritten = vsnprintf(buffer, maxChars, format, argptr);
272 if (numCharsWritten >= maxChars) {
273 if (count != _TRUNCATE) {
274 buffer[0] = '\0'; // buffer set to empty string
275 return -1;
276 }
277
278 // truncation occurred, add terminating \0
279 buffer[sizeOfBuffer] = '\0';
280 }
281
282 return numCharsWritten;
283 }
284
285 errno_t wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource)
286 {
287 if ((strDestination == nullptr) || (strSource == nullptr)) {
288 if (strDestination != nullptr) {
289 strDestination[0] = L'\0'; // ensure trailing \0 is written
290 }
291 return 22; // error: EINVAL
292 }
293
294 if (numberOfElements == 0) {
295 strDestination[0] = L'\0'; // ensure trailing \0 is written
296 return 34; // error: ERANGE
297 }
298
299 const size_t destLen = wcslen(strDestination);
300 const size_t sourceLen = wcslen(strSource);
301 if ((destLen > numberOfElements - 1) || ((sourceLen > 0) && (destLen == numberOfElements)) || (sourceLen > numberOfElements - destLen - 1)) {
302 strDestination[0] = L'\0'; // ensure trailing \0 is written
303 return 34; // error: ERANGE
304 }
305
306 (void)wcscat(strDestination, strSource);
307 return 0;
308 }
309
310 errno_t wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t *strSource)
311 {
312 if ((strDestination == nullptr) || (strSource == nullptr)) {
313 if (strDestination != nullptr) {
314 strDestination[0] = L'\0'; // ensure trailing \0 is written
315 }
316 return 22; // error: EINVAL
317 }
318
319 if ((numberOfElements == 0) || (wcslen(strSource) >= numberOfElements)) {
320 strDestination[0] = L'\0'; // ensure trailing \0 is written
321 return 34; // error: ERANGE
322 }
323
324 (void)wcscpy(strDestination, strSource);
325 return 0;
326 }
327
328 #endif