1 | // [Blend2D] |
2 | // 2D Vector Graphics Powered by a JIT Compiler. |
3 | // |
4 | // [License] |
5 | // Zlib - See LICENSE.md file in the package. |
6 | |
7 | #include "./blapi-build_p.h" |
8 | #include "./blruntime_p.h" |
9 | #include "./blsupport_p.h" |
10 | |
11 | #ifndef BL_BUILD_NO_JIT |
12 | #include <asmjit/asmjit.h> |
13 | #endif |
14 | |
15 | // ============================================================================ |
16 | // [Global Variables] |
17 | // ============================================================================ |
18 | |
19 | BLRuntimeContext blRuntimeContext; |
20 | |
21 | // ============================================================================ |
22 | // [BLRuntime - Build Information] |
23 | // ============================================================================ |
24 | |
25 | #define BL_STRINGIFY_WRAP(N) #N |
26 | #define BL_STRINGIFY(N) BL_STRINGIFY_WRAP(N) |
27 | |
28 | static const BLRuntimeBuildInfo blRuntimeBuildInfo = { |
29 | // Library Version. |
30 | { BL_VERSION }, |
31 | |
32 | // Build Type. |
33 | #ifdef BL_BUILD_DEBUG |
34 | BL_RUNTIME_BUILD_TYPE_DEBUG, |
35 | #else |
36 | BL_RUNTIME_BUILD_TYPE_RELEASE, |
37 | #endif |
38 | |
39 | // Baseline CPU features. |
40 | 0 |
41 | #ifdef BL_TARGET_OPT_SSE2 |
42 | | BL_RUNTIME_CPU_FEATURE_X86_SSE2 |
43 | #endif |
44 | #ifdef BL_TARGET_OPT_SSE3 |
45 | | BL_RUNTIME_CPU_FEATURE_X86_SSE3 |
46 | #endif |
47 | #ifdef BL_TARGET_OPT_SSSE3 |
48 | | BL_RUNTIME_CPU_FEATURE_X86_SSSE3 |
49 | #endif |
50 | #ifdef BL_TARGET_OPT_SSE4_1 |
51 | | BL_RUNTIME_CPU_FEATURE_X86_SSE4_1 |
52 | #endif |
53 | #ifdef BL_TARGET_OPT_SSE4_2 |
54 | | BL_RUNTIME_CPU_FEATURE_X86_SSE4_2 |
55 | #endif |
56 | #ifdef BL_TARGET_OPT_AVX |
57 | | BL_RUNTIME_CPU_FEATURE_X86_AVX |
58 | #endif |
59 | #ifdef BL_TARGET_OPT_AVX2 |
60 | | BL_RUNTIME_CPU_FEATURE_X86_AVX2 |
61 | #endif |
62 | , |
63 | |
64 | // Supported CPU features. |
65 | 0 |
66 | #ifdef BL_BUILD_OPT_SSE2 |
67 | | BL_RUNTIME_CPU_FEATURE_X86_SSE2 |
68 | #endif |
69 | #ifdef BL_BUILD_OPT_SSE3 |
70 | | BL_RUNTIME_CPU_FEATURE_X86_SSE3 |
71 | #endif |
72 | #ifdef BL_BUILD_OPT_SSSE3 |
73 | | BL_RUNTIME_CPU_FEATURE_X86_SSSE3 |
74 | #endif |
75 | #ifdef BL_BUILD_OPT_SSE4_1 |
76 | | BL_RUNTIME_CPU_FEATURE_X86_SSE4_1 |
77 | #endif |
78 | #ifdef BL_BUILD_OPT_SSE4_2 |
79 | | BL_RUNTIME_CPU_FEATURE_X86_SSE4_2 |
80 | #endif |
81 | #ifdef BL_BUILD_OPT_AVX |
82 | | BL_RUNTIME_CPU_FEATURE_X86_AVX |
83 | #endif |
84 | #ifdef BL_BUILD_OPT_AVX2 |
85 | | BL_RUNTIME_CPU_FEATURE_X86_AVX2 |
86 | #endif |
87 | , |
88 | |
89 | // Maximum image size. |
90 | BL_RUNTIME_MAX_IMAGE_SIZE, |
91 | |
92 | // Maximum thread count. |
93 | BL_RUNTIME_MAX_THREAD_COUNT, |
94 | |
95 | // Reserved |
96 | { 0 }, |
97 | |
98 | // Compiler Info. |
99 | #if defined(__INTEL_COMPILER) |
100 | "ICC" |
101 | #elif defined(__clang_minor__) |
102 | "Clang " BL_STRINGIFY(__clang_major__) "." BL_STRINGIFY(__clang_minor__) |
103 | #elif defined(__GNUC_MINOR__) |
104 | "GCC " BL_STRINGIFY(__GNUC__) "." BL_STRINGIFY(__GNUC_MINOR__) |
105 | #elif defined(_MSC_VER) |
106 | "MSC" |
107 | #else |
108 | "Unknown" |
109 | #endif |
110 | }; |
111 | |
112 | // ============================================================================ |
113 | // [BLRuntime - System Information] |
114 | // ============================================================================ |
115 | |
116 | #ifndef BL_BUILD_NO_JIT |
117 | static BL_INLINE uint32_t blRuntimeDetectCpuFeatures(const asmjit::CpuInfo& asmCpuInfo) noexcept { |
118 | uint32_t features = 0; |
119 | |
120 | #if BL_TARGET_ARCH_X86 |
121 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE2 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE2; |
122 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE3 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE3; |
123 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSSE3 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSSE3; |
124 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE4_1)) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE4_1; |
125 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE4_2)) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE4_2; |
126 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kAVX )) features |= BL_RUNTIME_CPU_FEATURE_X86_AVX; |
127 | if (asmCpuInfo.hasFeature(asmjit::x86::Features::kAVX2 )) features |= BL_RUNTIME_CPU_FEATURE_X86_AVX2; |
128 | #endif |
129 | |
130 | return features; |
131 | } |
132 | #endif |
133 | |
134 | static BL_INLINE void blRuntimeInitSystemInfo(BLRuntimeSystemInfo& info) noexcept { |
135 | info.cpuArch = BL_TARGET_ARCH_X86 ? BL_RUNTIME_CPU_ARCH_X86 : |
136 | BL_TARGET_ARCH_ARM ? BL_RUNTIME_CPU_ARCH_ARM : |
137 | BL_TARGET_ARCH_MIPS ? BL_RUNTIME_CPU_ARCH_MIPS : BL_RUNTIME_CPU_ARCH_UNKNOWN; |
138 | |
139 | #ifndef BL_BUILD_NO_JIT |
140 | const asmjit::CpuInfo& asmCpuInfo = asmjit::CpuInfo::host(); |
141 | info.cpuFeatures = blRuntimeDetectCpuFeatures(asmCpuInfo); |
142 | info.coreCount = asmCpuInfo.hwThreadCount(); |
143 | info.threadCount = asmCpuInfo.hwThreadCount(); |
144 | #endif |
145 | |
146 | #ifdef _WIN32 |
147 | SYSTEM_INFO si; |
148 | GetSystemInfo(&si); |
149 | info.minThreadStackSize = si.dwAllocationGranularity; |
150 | info.allocationGranularity = si.dwAllocationGranularity; |
151 | #else |
152 | #if defined(_SC_PAGESIZE) |
153 | info.allocationGranularity = uint32_t(sysconf(_SC_PAGESIZE)); |
154 | #else |
155 | info.allocationGranularity = uint32_t(getpagesize()); |
156 | #endif |
157 | |
158 | #if defined(PTHREAD_STACK_MIN) |
159 | info.minThreadStackSize = uint32_t(PTHREAD_STACK_MIN); |
160 | #elif defined(_SC_THREAD_STACK_MIN) |
161 | info.minThreadStackSize = uint32_t(sysconf(_SC_THREAD_STACK_MIN)); |
162 | #else |
163 | #pragma message("Missing 'BLRuntimeSystemInfo::minStackSize' implementation") |
164 | info.minThreadStackSize = blMax<uint32_t>(info.allocationGranularity, 65536u); |
165 | #endif |
166 | #endif |
167 | |
168 | info.minWorkerStackSize = blAlignUp(blMax<uint32_t>(info.minThreadStackSize, 4096u), info.allocationGranularity); |
169 | } |
170 | |
171 | // ============================================================================ |
172 | // [BLRuntime - Initialization & Shutdown] |
173 | // ============================================================================ |
174 | |
175 | BLResult blRuntimeInit() noexcept { |
176 | BLRuntimeContext* rt = &blRuntimeContext; |
177 | if (blAtomicFetchAdd(&rt->refCount) != 0) |
178 | return BL_SUCCESS; |
179 | |
180 | // Initialize system information - we need this first so we can properly |
181 | // initialize everything that relies on system info (thread-pool, optimized |
182 | // functions, etc...). |
183 | blRuntimeInitSystemInfo(rt->systemInfo); |
184 | |
185 | // Call "Runtime Initialization" handlers. |
186 | // - These would automatically install shutdown handlers when necessary. |
187 | blThreadingRtInit(rt); |
188 | blThreadPoolRtInit(rt); |
189 | blZeroAllocatorRtInit(rt); |
190 | blMatrix2DRtInit(rt); |
191 | blArrayRtInit(rt); |
192 | blStringRtInit(rt); |
193 | blPathRtInit(rt); |
194 | blRegionRtInit(rt); |
195 | blImageRtInit(rt); |
196 | blImageScalerRtInit(rt); |
197 | blPatternRtInit(rt); |
198 | blGradientRtInit(rt); |
199 | blFontRtInit(rt); |
200 | |
201 | #if !defined(BL_BUILD_NO_FIXED_PIPE) |
202 | blFixedPipeRtInit(rt); |
203 | #endif |
204 | |
205 | #if !defined(BL_BUILD_NO_JIT) |
206 | blPipeGenRtInit(rt); |
207 | #endif |
208 | |
209 | blContextRtInit(rt); |
210 | |
211 | return BL_SUCCESS; |
212 | } |
213 | |
214 | BLResult blRuntimeShutdown() noexcept { |
215 | BLRuntimeContext* rt = &blRuntimeContext; |
216 | if (blAtomicFetchSub(&rt->refCount) != 1) |
217 | return BL_SUCCESS; |
218 | |
219 | rt->shutdownHandlers.callInReverseOrder(rt); |
220 | rt->shutdownHandlers.reset(); |
221 | |
222 | return BL_SUCCESS; |
223 | } |
224 | |
225 | // Static instance that calls `blRuntimeInit()` and `blRuntimeShutdown()`. |
226 | class BLRuntimeAutoInit { |
227 | public: |
228 | inline BLRuntimeAutoInit() noexcept { blRuntimeInit(); } |
229 | inline ~BLRuntimeAutoInit() noexcept { blRuntimeShutdown(); } |
230 | }; |
231 | static BLRuntimeAutoInit blRuntimeAutoInit; |
232 | |
233 | // ============================================================================ |
234 | // [BLRuntime - Cleanup] |
235 | // ============================================================================ |
236 | |
237 | BLResult blRuntimeCleanup(uint32_t cleanupFlags) noexcept { |
238 | BLRuntimeContext* rt = &blRuntimeContext; |
239 | rt->cleanupHandlers.call(rt, cleanupFlags); |
240 | return BL_SUCCESS; |
241 | } |
242 | |
243 | // ============================================================================ |
244 | // [BLRuntime - Query Info] |
245 | // ============================================================================ |
246 | |
247 | BLResult blRuntimeQueryInfo(uint32_t infoType, void* infoOut) noexcept { |
248 | BLRuntimeContext* rt = &blRuntimeContext; |
249 | |
250 | switch (infoType) { |
251 | case BL_RUNTIME_INFO_TYPE_BUILD: { |
252 | BLRuntimeBuildInfo* buildInfo = static_cast<BLRuntimeBuildInfo*>(infoOut); |
253 | memcpy(buildInfo, &blRuntimeBuildInfo, sizeof(BLRuntimeBuildInfo)); |
254 | return BL_SUCCESS; |
255 | } |
256 | |
257 | case BL_RUNTIME_INFO_TYPE_SYSTEM: { |
258 | BLRuntimeSystemInfo* systemInfo = static_cast<BLRuntimeSystemInfo*>(infoOut); |
259 | memcpy(systemInfo, &rt->systemInfo, sizeof(BLRuntimeSystemInfo)); |
260 | return BL_SUCCESS; |
261 | } |
262 | |
263 | case BL_RUNTIME_INFO_TYPE_MEMORY: { |
264 | BLRuntimeMemoryInfo* memoryInfo = static_cast<BLRuntimeMemoryInfo*>(infoOut); |
265 | memoryInfo->reset(); |
266 | rt->memoryInfoHandlers.call(rt, memoryInfo); |
267 | return BL_SUCCESS; |
268 | } |
269 | |
270 | default: |
271 | return blTraceError(BL_ERROR_INVALID_VALUE); |
272 | } |
273 | } |
274 | |
275 | // ============================================================================ |
276 | // [BLRuntime - Message] |
277 | // ============================================================================ |
278 | |
279 | BLResult blRuntimeMessageOut(const char* msg) noexcept { |
280 | #if defined(_WIN32) |
281 | // Support both Console and GUI applications on Windows. |
282 | OutputDebugStringA(msg); |
283 | #endif |
284 | |
285 | fputs(msg, stderr); |
286 | return BL_SUCCESS; |
287 | } |
288 | |
289 | BLResult blRuntimeMessageFmt(const char* fmt, ...) noexcept { |
290 | va_list ap; |
291 | va_start(ap, fmt); |
292 | BLResult result = blRuntimeMessageVFmt(fmt, ap); |
293 | va_end(ap); |
294 | |
295 | return result; |
296 | } |
297 | |
298 | BLResult blRuntimeMessageVFmt(const char* fmt, va_list ap) noexcept { |
299 | char buf[1024]; |
300 | vsnprintf(buf, BL_ARRAY_SIZE(buf), fmt, ap); |
301 | return blRuntimeMessageOut(buf); |
302 | } |
303 | |
304 | // ============================================================================ |
305 | // [BLRuntime - GetCpuTicks] |
306 | // ============================================================================ |
307 | |
308 | uint32_t blRuntimeGetTickCount(void) noexcept { |
309 | #ifndef BL_BUILD_NO_JIT |
310 | return asmjit::OSUtils::getTickCount(); |
311 | #else |
312 | return 0; |
313 | #endif |
314 | } |
315 | |
316 | // ============================================================================ |
317 | // [BLRuntime - Failure] |
318 | // ============================================================================ |
319 | |
320 | void blRuntimeFailure(const char* fmt, ...) noexcept { |
321 | va_list ap; |
322 | va_start(ap, fmt); |
323 | blRuntimeMessageVFmt(fmt, ap); |
324 | va_end(ap); |
325 | |
326 | abort(); |
327 | } |
328 | |
329 | void blRuntimeAssertionFailure(const char* file, int line, const char* msg) noexcept { |
330 | blRuntimeMessageFmt("[Blend2D] ASSERTION FAILURE: '%s' at '%s' [line %d]\n" , msg, file, line); |
331 | abort(); |
332 | } |
333 | |
334 | // ============================================================================ |
335 | // [BLRuntime - Alloc / Free] |
336 | // ============================================================================ |
337 | |
338 | // We use 'malloc/free' implementation at the moment. |
339 | |
340 | void* blRuntimeAllocImpl(size_t implSize, uint16_t* memPoolDataOut) noexcept { |
341 | *memPoolDataOut = 0; |
342 | return malloc(implSize); |
343 | } |
344 | |
345 | BLResult blRuntimeFreeImpl(void* impl_, size_t implSize, uint32_t memPoolData) noexcept { |
346 | BL_UNUSED(implSize); |
347 | BL_UNUSED(memPoolData); |
348 | |
349 | free(impl_); |
350 | return BL_SUCCESS; |
351 | } |
352 | |
353 | void BL_CDECL blRuntimeDummyDestroyImplFunc(void* impl, void* destroyData) noexcept { |
354 | BL_UNUSED(impl); |
355 | BL_UNUSED(destroyData); |
356 | } |
357 | |
358 | // ============================================================================ |
359 | // [BLRuntime - ResultFrom{Win|Posix}Error] |
360 | // ============================================================================ |
361 | |
362 | #ifdef _WIN32 |
363 | |
364 | // Fix possible problems with MinGW not defining these. |
365 | #ifndef ERROR_DISK_QUOTA_EXCEEDED |
366 | #define ERROR_DISK_QUOTA_EXCEEDED 0x0000050F |
367 | #endif |
368 | |
369 | BLResult blResultFromWinError(uint32_t e) noexcept { |
370 | switch (e) { |
371 | case ERROR_SUCCESS : return BL_SUCCESS; // 0x00000000 |
372 | case ERROR_INVALID_FUNCTION : return BL_ERROR_NOT_PERMITTED; // 0x00000001 |
373 | case ERROR_FILE_NOT_FOUND : return BL_ERROR_NO_ENTRY; // 0x00000002 |
374 | case ERROR_PATH_NOT_FOUND : return BL_ERROR_NO_ENTRY; // 0x00000003 |
375 | case ERROR_TOO_MANY_OPEN_FILES : return BL_ERROR_TOO_MANY_OPEN_FILES; // 0x00000004 |
376 | case ERROR_ACCESS_DENIED : return BL_ERROR_ACCESS_DENIED; // 0x00000005 |
377 | case ERROR_INVALID_HANDLE : return BL_ERROR_INVALID_HANDLE; // 0x00000006 |
378 | case ERROR_NOT_ENOUGH_MEMORY : return BL_ERROR_OUT_OF_MEMORY; // 0x00000008 |
379 | case ERROR_OUTOFMEMORY : return BL_ERROR_OUT_OF_MEMORY; // 0x0000000E |
380 | case ERROR_INVALID_DRIVE : return BL_ERROR_NO_ENTRY; // 0x0000000F |
381 | case ERROR_CURRENT_DIRECTORY : return BL_ERROR_NOT_PERMITTED; // 0x00000010 |
382 | case ERROR_NOT_SAME_DEVICE : return BL_ERROR_NOT_SAME_DEVICE; // 0x00000011 |
383 | case ERROR_NO_MORE_FILES : return BL_ERROR_NO_MORE_FILES; // 0x00000012 |
384 | case ERROR_WRITE_PROTECT : return BL_ERROR_READ_ONLY_FS; // 0x00000013 |
385 | case ERROR_NOT_READY : return BL_ERROR_NO_MEDIA; // 0x00000015 |
386 | case ERROR_CRC : return BL_ERROR_IO; // 0x00000017 |
387 | case ERROR_SEEK : return BL_ERROR_INVALID_SEEK; // 0x00000019 |
388 | case ERROR_WRITE_FAULT : return BL_ERROR_IO; // 0x0000001D |
389 | case ERROR_READ_FAULT : return BL_ERROR_IO; // 0x0000001E |
390 | case ERROR_GEN_FAILURE : return BL_ERROR_IO; // 0x0000001F |
391 | case ERROR_SHARING_BUFFER_EXCEEDED: return BL_ERROR_TOO_MANY_OPEN_FILES; // 0x00000024 |
392 | case ERROR_HANDLE_EOF : return BL_ERROR_NO_MORE_DATA; // 0x00000026 |
393 | case ERROR_HANDLE_DISK_FULL : return BL_ERROR_NO_SPACE_LEFT; // 0x00000027 |
394 | case ERROR_NOT_SUPPORTED : return BL_ERROR_NOT_IMPLEMENTED; // 0x00000032 |
395 | case ERROR_FILE_EXISTS : return BL_ERROR_ALREADY_EXISTS; // 0x00000050 |
396 | case ERROR_CANNOT_MAKE : return BL_ERROR_NOT_PERMITTED; // 0x00000052 |
397 | case ERROR_INVALID_PARAMETER : return BL_ERROR_INVALID_VALUE; // 0x00000057 |
398 | case ERROR_NET_WRITE_FAULT : return BL_ERROR_IO; // 0x00000058 |
399 | case ERROR_DRIVE_LOCKED : return BL_ERROR_BUSY; // 0x0000006C |
400 | case ERROR_BROKEN_PIPE : return BL_ERROR_BROKEN_PIPE; // 0x0000006D |
401 | case ERROR_OPEN_FAILED : return BL_ERROR_OPEN_FAILED; // 0x0000006E |
402 | case ERROR_BUFFER_OVERFLOW : return BL_ERROR_FILE_NAME_TOO_LONG; // 0x0000006F |
403 | case ERROR_DISK_FULL : return BL_ERROR_NO_SPACE_LEFT; // 0x00000070 |
404 | case ERROR_CALL_NOT_IMPLEMENTED : return BL_ERROR_NOT_IMPLEMENTED; // 0x00000078 |
405 | case ERROR_INVALID_NAME : return BL_ERROR_INVALID_FILE_NAME; // 0x0000007B |
406 | case ERROR_NEGATIVE_SEEK : return BL_ERROR_INVALID_SEEK; // 0x00000083 |
407 | case ERROR_SEEK_ON_DEVICE : return BL_ERROR_INVALID_SEEK; // 0x00000084 |
408 | case ERROR_BUSY_DRIVE : return BL_ERROR_BUSY; // 0x0000008E |
409 | case ERROR_DIR_NOT_ROOT : return BL_ERROR_NOT_ROOT_DEVICE; // 0x00000090 |
410 | case ERROR_DIR_NOT_EMPTY : return BL_ERROR_NOT_EMPTY; // 0x00000091 |
411 | case ERROR_PATH_BUSY : return BL_ERROR_BUSY; // 0x00000094 |
412 | case ERROR_TOO_MANY_TCBS : return BL_ERROR_TOO_MANY_THREADS; // 0x0000009B |
413 | case ERROR_BAD_ARGUMENTS : return BL_ERROR_INVALID_VALUE; // 0x000000A0 |
414 | case ERROR_BAD_PATHNAME : return BL_ERROR_INVALID_FILE_NAME; // 0x000000A1 |
415 | case ERROR_SIGNAL_PENDING : return BL_ERROR_BUSY; // 0x000000A2 |
416 | case ERROR_MAX_THRDS_REACHED : return BL_ERROR_TOO_MANY_THREADS; // 0x000000A4 |
417 | case ERROR_BUSY : return BL_ERROR_BUSY; // 0x000000AA |
418 | case ERROR_ALREADY_EXISTS : return BL_ERROR_ALREADY_EXISTS; // 0x000000B7 |
419 | case ERROR_BAD_PIPE : return BL_ERROR_BROKEN_PIPE; // 0x000000E6 |
420 | case ERROR_PIPE_BUSY : return BL_ERROR_BUSY; // 0x000000E7 |
421 | case ERROR_NO_MORE_ITEMS : return BL_ERROR_NO_MORE_FILES; // 0x00000103 |
422 | case ERROR_FILE_INVALID : return BL_ERROR_NO_ENTRY; // 0x000003EE |
423 | case ERROR_NO_DATA_DETECTED : return BL_ERROR_IO; // 0x00000450 |
424 | case ERROR_MEDIA_CHANGED : return BL_ERROR_MEDIA_CHANGED; // 0x00000456 |
425 | case ERROR_IO_DEVICE : return BL_ERROR_NO_DEVICE; // 0x0000045D |
426 | case ERROR_NO_MEDIA_IN_DRIVE : return BL_ERROR_NO_MEDIA; // 0x00000458 |
427 | case ERROR_DISK_OPERATION_FAILED : return BL_ERROR_IO; // 0x00000467 |
428 | case ERROR_TOO_MANY_LINKS : return BL_ERROR_TOO_MANY_LINKS; // 0x00000476 |
429 | case ERROR_DISK_QUOTA_EXCEEDED : return BL_ERROR_NO_SPACE_LEFT; // 0x0000050F |
430 | case ERROR_INVALID_USER_BUFFER : return BL_ERROR_BUSY; // 0x000006F8 |
431 | case ERROR_UNRECOGNIZED_MEDIA : return BL_ERROR_IO; // 0x000006F9 |
432 | case ERROR_NOT_ENOUGH_QUOTA : return BL_ERROR_OUT_OF_MEMORY; // 0x00000718 |
433 | case ERROR_CANT_ACCESS_FILE : return BL_ERROR_NOT_PERMITTED; // 0x00000780 |
434 | case ERROR_CANT_RESOLVE_FILENAME : return BL_ERROR_NO_ENTRY; // 0x00000781 |
435 | case ERROR_OPEN_FILES : return BL_ERROR_TRY_AGAIN; // 0x00000961 |
436 | } |
437 | |
438 | // Pass the system error if it's below our error indexing. |
439 | if (e < BL_ERROR_START_INDEX) |
440 | return e; |
441 | |
442 | // Otherwise this is an unmapped system error code. |
443 | return BL_ERROR_UNKNOWN_SYSTEM_ERROR; |
444 | } |
445 | |
446 | #else |
447 | |
448 | BLResult blResultFromPosixError(int e) noexcept { |
449 | #define MAP(C_ERROR, BL_ERROR) case C_ERROR: return BL_ERROR |
450 | |
451 | switch (e) { |
452 | #ifdef EACCES |
453 | MAP(EACCES, BL_ERROR_ACCESS_DENIED); |
454 | #endif |
455 | #ifdef EAGAIN |
456 | MAP(EAGAIN, BL_ERROR_TRY_AGAIN); |
457 | #endif |
458 | #ifdef EBADF |
459 | MAP(EBADF, BL_ERROR_INVALID_HANDLE); |
460 | #endif |
461 | #ifdef EBUSY |
462 | MAP(EBUSY, BL_ERROR_BUSY); |
463 | #endif |
464 | #ifdef EDQUOT |
465 | MAP(EDQUOT, BL_ERROR_NO_SPACE_LEFT); |
466 | #endif |
467 | #ifdef EEXIST |
468 | MAP(EEXIST, BL_ERROR_ALREADY_EXISTS); |
469 | #endif |
470 | #ifdef EFAULT |
471 | MAP(EFAULT, BL_ERROR_INVALID_STATE); |
472 | #endif |
473 | #ifdef EFBIG |
474 | MAP(EFBIG, BL_ERROR_FILE_TOO_LARGE); |
475 | #endif |
476 | #ifdef EINTR |
477 | MAP(EINTR, BL_ERROR_INTERRUPTED); |
478 | #endif |
479 | #ifdef EINVAL |
480 | MAP(EINVAL, BL_ERROR_INVALID_VALUE); |
481 | #endif |
482 | #ifdef EIO |
483 | MAP(EIO, BL_ERROR_IO); |
484 | #endif |
485 | #ifdef EISDIR |
486 | MAP(EISDIR, BL_ERROR_NOT_FILE); |
487 | #endif |
488 | #ifdef ELOOP |
489 | MAP(ELOOP, BL_ERROR_SYMLINK_LOOP); |
490 | #endif |
491 | #ifdef EMFILE |
492 | MAP(EMFILE, BL_ERROR_TOO_MANY_OPEN_FILES); |
493 | #endif |
494 | #ifdef ENAMETOOLONG |
495 | MAP(ENAMETOOLONG, BL_ERROR_FILE_NAME_TOO_LONG); |
496 | #endif |
497 | #ifdef ENFILE |
498 | MAP(ENFILE, BL_ERROR_TOO_MANY_OPEN_FILES_BY_OS); |
499 | #endif |
500 | #ifdef ENMFILE |
501 | MAP(ENMFILE, BL_ERROR_NO_MORE_FILES); |
502 | #endif |
503 | #ifdef ENODATA |
504 | MAP(ENODATA, BL_ERROR_NO_MORE_DATA); |
505 | #endif |
506 | #ifdef ENODEV |
507 | MAP(ENODEV, BL_ERROR_NO_DEVICE); |
508 | #endif |
509 | #ifdef ENOENT |
510 | MAP(ENOENT, BL_ERROR_NO_ENTRY); |
511 | #endif |
512 | #ifdef ENOMEDIUM |
513 | MAP(ENOMEDIUM, BL_ERROR_NO_MEDIA); |
514 | #endif |
515 | #ifdef ENOMEM |
516 | MAP(ENOMEM, BL_ERROR_OUT_OF_MEMORY); |
517 | #endif |
518 | #ifdef ENOSPC |
519 | MAP(ENOSPC, BL_ERROR_NO_SPACE_LEFT); |
520 | #endif |
521 | #ifdef ENOSYS |
522 | MAP(ENOSYS, BL_ERROR_NOT_IMPLEMENTED); |
523 | #endif |
524 | #ifdef ENOTBLK |
525 | MAP(ENOTBLK, BL_ERROR_NOT_BLOCK_DEVICE); |
526 | #endif |
527 | #ifdef ENOTDIR |
528 | MAP(ENOTDIR, BL_ERROR_NOT_DIRECTORY); |
529 | #endif |
530 | #ifdef ENOTEMPTY |
531 | MAP(ENOTEMPTY, BL_ERROR_NOT_EMPTY); |
532 | #endif |
533 | #ifdef ENXIO |
534 | MAP(ENXIO, BL_ERROR_NO_DEVICE); |
535 | #endif |
536 | #ifdef EOVERFLOW |
537 | MAP(EOVERFLOW, BL_ERROR_VALUE_TOO_LARGE); |
538 | #endif |
539 | #ifdef EPERM |
540 | MAP(EPERM, BL_ERROR_NOT_PERMITTED); |
541 | #endif |
542 | #ifdef EROFS |
543 | MAP(EROFS, BL_ERROR_READ_ONLY_FS); |
544 | #endif |
545 | #ifdef ESPIPE |
546 | MAP(ESPIPE, BL_ERROR_INVALID_SEEK); |
547 | #endif |
548 | #ifdef ETIMEDOUT |
549 | MAP(ETIMEDOUT, BL_ERROR_TIMED_OUT); |
550 | #endif |
551 | #ifdef EXDEV |
552 | MAP(EXDEV, BL_ERROR_NOT_SAME_DEVICE); |
553 | #endif |
554 | } |
555 | |
556 | #undef MAP |
557 | |
558 | // Pass the system error if it's below our error indexing. |
559 | if (e != 0 && unsigned(e) < BL_ERROR_START_INDEX) |
560 | return uint32_t(unsigned(e)); |
561 | else |
562 | return BL_ERROR_UNKNOWN_SYSTEM_ERROR; |
563 | } |
564 | #endif |
565 | |