| 1 | #pragma once
|
|---|
| 2 |
|
|---|
| 3 | #include <cerrno>
|
|---|
| 4 | #include <cstdlib>
|
|---|
| 5 | #include <cstring>
|
|---|
| 6 | #include <limits>
|
|---|
| 7 |
|
|---|
| 8 | namespace mol
|
|---|
| 9 | {
|
|---|
| 10 | namespace msccrt
|
|---|
| 11 | {
|
|---|
| 12 | template <typename Char>
|
|---|
| 13 | inline static size_t basic_strnlen_s(const Char* str, size_t numberOfElements)
|
|---|
| 14 | {
|
|---|
| 15 | using namespace std;
|
|---|
| 16 |
|
|---|
| 17 | if (str == NULL)
|
|---|
| 18 | {
|
|---|
| 19 | return 0;
|
|---|
| 20 | }
|
|---|
| 21 | if (numberOfElements == 0)
|
|---|
| 22 | {
|
|---|
| 23 | return 0;
|
|---|
| 24 | }
|
|---|
| 25 | if (str + numberOfElements < str) {
|
|---|
| 26 | return numberOfElements; //TODO
|
|---|
| 27 | }
|
|---|
| 28 | size_t size = 0;
|
|---|
| 29 | for (; size != numberOfElements &&
|
|---|
| 30 | str[size] &&
|
|---|
| 31 | size < (numeric_limits<size_t>::max)(); size++) {}
|
|---|
| 32 | return size;
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| 35 | template <typename Char>
|
|---|
| 36 | inline static int basic_strcpy_s(Char* strDestination,
|
|---|
| 37 | size_t numberOfElements,
|
|---|
| 38 | const Char* strSource)
|
|---|
| 39 | {
|
|---|
| 40 | using namespace std;
|
|---|
| 41 |
|
|---|
| 42 | if (strDestination == 0)
|
|---|
| 43 | {
|
|---|
| 44 | return EINVAL;
|
|---|
| 45 | }
|
|---|
| 46 | if (strSource == 0)
|
|---|
| 47 | {
|
|---|
| 48 | return EINVAL;
|
|---|
| 49 | }
|
|---|
| 50 | if (numberOfElements == 0)
|
|---|
| 51 | {
|
|---|
| 52 | return ERANGE;
|
|---|
| 53 | }
|
|---|
| 54 | if (strSource[0] == 0) {
|
|---|
| 55 | strDestination[0] = 0;
|
|---|
| 56 | return 0;
|
|---|
| 57 | }
|
|---|
| 58 | size_t strSourceElements = basic_strnlen_s<Char>(strSource, numberOfElements);
|
|---|
| 59 | if (strSourceElements == numberOfElements)
|
|---|
| 60 | {
|
|---|
| 61 | return ERANGE;
|
|---|
| 62 | }
|
|---|
| 63 | size_t memcpyBytes = sizeof(Char) * (strSourceElements);
|
|---|
| 64 | if (memcpyBytes < sizeof(Char) ||
|
|---|
| 65 | memcpyBytes < strSourceElements) {
|
|---|
| 66 | return ERANGE; //TODO
|
|---|
| 67 | }
|
|---|
| 68 | if (reinterpret_cast<char*>(strDestination) + memcpyBytes <
|
|---|
| 69 | reinterpret_cast<char*>(strDestination)) {
|
|---|
| 70 | return ERANGE; //TODO
|
|---|
| 71 | }
|
|---|
| 72 | memcpy(reinterpret_cast<void*>(strDestination),
|
|---|
| 73 | reinterpret_cast<const void*>(strSource),
|
|---|
| 74 | memcpyBytes);
|
|---|
| 75 | strDestination[strSourceElements] = 0;
|
|---|
| 76 | return 0;
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | template <typename Char>
|
|---|
| 80 | inline static int basic_strcat_s(Char* strDestination,
|
|---|
| 81 | size_t numberOfElements,
|
|---|
| 82 | const Char* strSource)
|
|---|
| 83 | {
|
|---|
| 84 | using namespace std;
|
|---|
| 85 |
|
|---|
| 86 | if (strDestination == 0)
|
|---|
| 87 | {
|
|---|
| 88 | return EINVAL;
|
|---|
| 89 | }
|
|---|
| 90 | if (strSource == 0)
|
|---|
| 91 | {
|
|---|
| 92 | return EINVAL;
|
|---|
| 93 | }
|
|---|
| 94 | if (numberOfElements == 0)
|
|---|
| 95 | {
|
|---|
| 96 | return ERANGE;
|
|---|
| 97 | }
|
|---|
| 98 | size_t strDestinationElements = basic_strnlen_s<Char>(strDestination,
|
|---|
| 99 | numberOfElements);
|
|---|
| 100 | if (strDestinationElements == numberOfElements)
|
|---|
| 101 | {
|
|---|
| 102 | return EINVAL;
|
|---|
| 103 | }
|
|---|
| 104 | if (numberOfElements < strDestinationElements) {
|
|---|
| 105 | return EINVAL; //TODO
|
|---|
| 106 | }
|
|---|
| 107 | size_t strDestinationElementsLeft =
|
|---|
| 108 | numberOfElements - strDestinationElements;
|
|---|
| 109 | size_t strSourceElements =
|
|---|
| 110 | basic_strnlen_s<Char>(strSource, strDestinationElementsLeft);
|
|---|
| 111 | if (strSourceElements == strDestinationElementsLeft)
|
|---|
| 112 | {
|
|---|
| 113 | return ERANGE;
|
|---|
| 114 | }
|
|---|
| 115 | if (strDestination + strDestinationElements < strDestination) {
|
|---|
| 116 | return ERANGE; //TODO
|
|---|
| 117 | }
|
|---|
| 118 | if (strSourceElements + 1 < strSourceElements) {
|
|---|
| 119 | return ERANGE; //TODO
|
|---|
| 120 | }
|
|---|
| 121 | return basic_strcpy_s<Char>(
|
|---|
| 122 | strDestination + strDestinationElements,
|
|---|
| 123 | strSourceElements + 1,
|
|---|
| 124 | strSource
|
|---|
| 125 | );
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | template <typename Char, size_t size>
|
|---|
| 129 | inline static int basic_strcpy_s(Char (&strDestination)[size],
|
|---|
| 130 | const Char* strSource)
|
|---|
| 131 | {
|
|---|
| 132 | return basic_strcpy_s(strDestination, size, strSource);
|
|---|
| 133 | }
|
|---|
| 134 |
|
|---|
| 135 | template <typename Char, size_t size>
|
|---|
| 136 | inline static int basic_strcat_s(Char (&strDestination)[size],
|
|---|
| 137 | const Char* strSource)
|
|---|
| 138 | {
|
|---|
| 139 | return basic_strcat_s(strDestination, size, strSource);
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | }
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 | using mol::msccrt::basic_strnlen_s;
|
|---|
| 147 | using mol::msccrt::basic_strcpy_s;
|
|---|
| 148 | using mol::msccrt::basic_strcat_s;
|
|---|
| 149 |
|
|---|
| 150 | #if !defined(_MSC_VER)
|
|---|
| 151 |
|
|---|
| 152 | #define strnlen_s basic_strnlen_s<char>
|
|---|
| 153 | #define strcpy_s basic_strcpy_s<char>
|
|---|
| 154 | #define strcat_s basic_strcat_s<char>
|
|---|
| 155 |
|
|---|
| 156 | #define wcsnlen_s basic_strnlen_s<wchar_t>
|
|---|
| 157 | #define wcscpy_s basic_strcpy_s<wchar_t>
|
|---|
| 158 | #define wcscat_s basic_strcat_s<wchar_t>
|
|---|
| 159 |
|
|---|
| 160 | #define _tcsnlen basic_strnlen_s<TCHAR>
|
|---|
| 161 | #define _tcscpy_s basic_strcpy_s<TCHAR>
|
|---|
| 162 | #define _tcscat_s basic_strcat_s<TCHAR>
|
|---|
| 163 |
|
|---|
| 164 | #include <time.h>
|
|---|
| 165 | #include <string.h>
|
|---|
| 166 | #include <errno.h>
|
|---|
| 167 |
|
|---|
| 168 | #ifndef _countof
|
|---|
| 169 | #define _countof(array) (sizeof(array)/sizeof(array[0]))
|
|---|
| 170 | #endif
|
|---|
| 171 |
|
|---|
| 172 | namespace mol
|
|---|
| 173 | {
|
|---|
| 174 | namespace msccrt
|
|---|
| 175 | {
|
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 | #ifndef _T
|
|---|
| 179 | #define _T TEXT
|
|---|
| 180 | #endif
|
|---|
| 181 |
|
|---|
| 182 | #if defined(UNICODE) || defined(_UNICODE)
|
|---|
| 183 |
|
|---|
| 184 | #ifndef TEXT
|
|---|
| 185 | #define TEXT(x) L##x
|
|---|
| 186 | #endif
|
|---|
| 187 |
|
|---|
| 188 | #define _tprintf wprintf
|
|---|
| 189 | #define _stprintf_s swprintf_s
|
|---|
| 190 |
|
|---|
| 191 | #else
|
|---|
| 192 |
|
|---|
| 193 | #ifndef TEXT
|
|---|
| 194 | #define TEXT(x) x
|
|---|
| 195 | #endif
|
|---|
| 196 |
|
|---|
| 197 | #define _tprintf printf
|
|---|
| 198 | #define _stprintf_s sprintf_s
|
|---|
| 199 |
|
|---|
| 200 | #endif
|
|---|
| 201 |
|
|---|
| 202 | // XXX ???
|
|---|
| 203 | typedef int errno_t;
|
|---|
| 204 |
|
|---|
| 205 | #ifndef __GNUC__
|
|---|
| 206 |
|
|---|
| 207 | template <size_t size>
|
|---|
| 208 | inline static int swprintf_s(wchar_t (&buffer)[size],
|
|---|
| 209 | const wchar_t *format, ...)
|
|---|
| 210 | {
|
|---|
| 211 | va_list ap;
|
|---|
| 212 | va_start(ap, format);
|
|---|
| 213 | int result = vswprintf(buffer,size,format,ap);
|
|---|
| 214 | va_end(ap);
|
|---|
| 215 | return result;
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 | template <size_t size>
|
|---|
| 220 | inline static int sprintf_s(char (&buffer)[size],
|
|---|
| 221 | const char *format, ...)
|
|---|
| 222 | {
|
|---|
| 223 | va_list ap;
|
|---|
| 224 | va_start(ap, format);
|
|---|
| 225 | int result = snprintf(buffer,size,format,ap);
|
|---|
| 226 | va_end(ap);
|
|---|
| 227 | return result;
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | #endif
|
|---|
| 231 |
|
|---|
| 232 | inline static errno_t localtime_s(struct tm* tm_, const time_t *time_)
|
|---|
| 233 | {
|
|---|
| 234 | *tm_ = *localtime(time_); // XXX localtime is not thread safe !
|
|---|
| 235 | return !EINVAL;
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | #ifdef __CYGWIN__
|
|---|
| 239 | #define wcsdup _wcsdup
|
|---|
| 240 | inline static wchar_t* _wcsdup(const wchar_t *str)
|
|---|
| 241 | {
|
|---|
| 242 | size_t len = 0;
|
|---|
| 243 | for (; len<str[len]; len++);
|
|---|
| 244 | if (len == 0)
|
|---|
| 245 | {
|
|---|
| 246 | return NULL;
|
|---|
| 247 | }
|
|---|
| 248 | size_t memory_size = sizeof(wchar_t)*(len+1);
|
|---|
| 249 | wchar_t* d = reinterpret_cast<wchar_t*>(malloc(memory_size));
|
|---|
| 250 | if (!d)
|
|---|
| 251 | {
|
|---|
| 252 | return NULL;
|
|---|
| 253 | }
|
|---|
| 254 | memcpy(d, str, memory_size);
|
|---|
| 255 | return d;
|
|---|
| 256 | }
|
|---|
| 257 | #endif
|
|---|
| 258 |
|
|---|
| 259 | #if (defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)) && !defined(__CYGWIN__)
|
|---|
| 260 | #include <windows.h>
|
|---|
| 261 | #include <tchar.h>
|
|---|
| 262 |
|
|---|
| 263 | template <size_t drivesize, size_t dirsize, size_t fnamesize, size_t extsize>
|
|---|
| 264 | inline static errno_t _tsplitpath_s(
|
|---|
| 265 | const TCHAR *path,
|
|---|
| 266 | TCHAR (&drive)[drivesize],
|
|---|
| 267 | TCHAR (&dir)[dirsize],
|
|---|
| 268 | TCHAR (&fname)[fnamesize],
|
|---|
| 269 | TCHAR (&ext)[extsize])
|
|---|
| 270 | {
|
|---|
| 271 | _tsplitpath(path, drive, dir, fname, ext);
|
|---|
| 272 | return !EINVAL;
|
|---|
| 273 | }
|
|---|
| 274 |
|
|---|
| 275 | template <size_t size>
|
|---|
| 276 | inline static errno_t _tmakepath_s(
|
|---|
| 277 | TCHAR (&path)[size],
|
|---|
| 278 | const TCHAR *drive,
|
|---|
| 279 | const TCHAR *dir,
|
|---|
| 280 | const TCHAR *fname,
|
|---|
| 281 | const TCHAR *ext)
|
|---|
| 282 | {
|
|---|
| 283 | _tmakepath(path, drive, dir, fname, ext);
|
|---|
| 284 | return !EINVAL;
|
|---|
| 285 | }
|
|---|
| 286 |
|
|---|
| 287 | #endif
|
|---|
| 288 |
|
|---|
| 289 | }
|
|---|
| 290 | }
|
|---|
| 291 |
|
|---|
| 292 | #endif
|
|---|