extlzham 0.0.1.PROTOTYPE3-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +27 -0
  3. data/README.md +74 -0
  4. data/Rakefile +152 -0
  5. data/contrib/lzham/LICENSE +22 -0
  6. data/contrib/lzham/README.md +209 -0
  7. data/contrib/lzham/include/lzham.h +781 -0
  8. data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
  9. data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
  10. data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
  11. data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
  12. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
  13. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
  14. data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
  15. data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
  16. data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
  17. data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
  18. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
  19. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
  20. data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
  21. data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
  22. data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
  23. data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
  24. data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
  25. data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
  26. data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
  27. data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
  28. data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
  29. data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
  30. data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
  31. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
  32. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
  33. data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
  34. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
  35. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
  36. data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
  37. data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
  38. data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
  39. data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
  40. data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
  41. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
  42. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
  43. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
  44. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
  45. data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
  46. data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
  47. data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
  48. data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
  49. data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
  50. data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
  51. data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
  52. data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
  53. data/examples/basic.rb +48 -0
  54. data/ext/constants.c +64 -0
  55. data/ext/decoder.c +313 -0
  56. data/ext/depend +5 -0
  57. data/ext/encoder.c +372 -0
  58. data/ext/error.c +80 -0
  59. data/ext/extconf.rb +29 -0
  60. data/ext/extlzham.c +34 -0
  61. data/ext/extlzham.h +62 -0
  62. data/gemstub.rb +22 -0
  63. data/lib/2.0/extlzham.so +0 -0
  64. data/lib/2.1/extlzham.so +0 -0
  65. data/lib/2.2/extlzham.so +0 -0
  66. data/lib/extlzham.rb +158 -0
  67. data/lib/extlzham/version.rb +5 -0
  68. data/test/test_extlzham.rb +35 -0
  69. metadata +156 -0
@@ -0,0 +1,12 @@
1
+ // File: lzham_threading.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+
4
+ #if LZHAM_USE_WIN32_API
5
+ #include "lzham_win32_threading.h"
6
+ #elif LZHAM_USE_PTHREADS_API
7
+ #include "lzham_pthreads_threading.h"
8
+ #else
9
+ #include "lzham_null_threading.h"
10
+ #endif
11
+
12
+
@@ -0,0 +1,220 @@
1
+ // File: lzham_task_pool_win32.cpp
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #include "lzham_core.h"
4
+ #include "lzham_win32_threading.h"
5
+ #include "lzham_timer.h"
6
+ #include <process.h>
7
+
8
+ #if LZHAM_USE_WIN32_API
9
+
10
+ namespace lzham
11
+ {
12
+ task_pool::task_pool() :
13
+ m_num_threads(0),
14
+ m_tasks_available(0, 32767),
15
+ m_num_outstanding_tasks(0),
16
+ m_exit_flag(false)
17
+ {
18
+ utils::zero_object(m_threads);
19
+ }
20
+
21
+ task_pool::task_pool(uint num_threads) :
22
+ m_num_threads(0),
23
+ m_tasks_available(0, 32767),
24
+ m_num_outstanding_tasks(0),
25
+ m_exit_flag(false)
26
+ {
27
+ utils::zero_object(m_threads);
28
+
29
+ bool status = init(num_threads);
30
+ LZHAM_VERIFY(status);
31
+ }
32
+
33
+ task_pool::~task_pool()
34
+ {
35
+ deinit();
36
+ }
37
+
38
+ bool task_pool::init(uint num_threads)
39
+ {
40
+ LZHAM_ASSERT(num_threads <= cMaxThreads);
41
+ num_threads = math::minimum<uint>(num_threads, cMaxThreads);
42
+
43
+ deinit();
44
+
45
+ bool succeeded = true;
46
+
47
+ m_num_threads = 0;
48
+ while (m_num_threads < num_threads)
49
+ {
50
+ m_threads[m_num_threads] = (HANDLE)_beginthreadex(NULL, 32768, thread_func, this, 0, NULL);
51
+ LZHAM_ASSERT(m_threads[m_num_threads] != 0);
52
+
53
+ if (!m_threads[m_num_threads])
54
+ {
55
+ succeeded = false;
56
+ break;
57
+ }
58
+
59
+ m_num_threads++;
60
+ }
61
+
62
+ if (!succeeded)
63
+ {
64
+ deinit();
65
+ return false;
66
+ }
67
+
68
+ return true;
69
+ }
70
+
71
+ void task_pool::deinit()
72
+ {
73
+ if (m_num_threads)
74
+ {
75
+ join();
76
+
77
+ atomic_exchange32(&m_exit_flag, true);
78
+
79
+ m_tasks_available.release(m_num_threads);
80
+
81
+ for (uint i = 0; i < m_num_threads; i++)
82
+ {
83
+ if (m_threads[i])
84
+ {
85
+ for ( ; ; )
86
+ {
87
+ DWORD result = WaitForSingleObject(m_threads[i], 30000);
88
+ if ((result == WAIT_OBJECT_0) || (result == WAIT_ABANDONED))
89
+ break;
90
+ }
91
+
92
+ CloseHandle(m_threads[i]);
93
+ m_threads[i] = NULL;
94
+ }
95
+ }
96
+
97
+ m_num_threads = 0;
98
+
99
+ atomic_exchange32(&m_exit_flag, false);
100
+ }
101
+
102
+ m_task_stack.clear();
103
+ m_num_outstanding_tasks = 0;
104
+ }
105
+
106
+ bool task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
107
+ {
108
+ LZHAM_ASSERT(m_num_threads);
109
+ LZHAM_ASSERT(pFunc);
110
+
111
+ task tsk;
112
+ tsk.m_callback = pFunc;
113
+ tsk.m_data = data;
114
+ tsk.m_pData_ptr = pData_ptr;
115
+ tsk.m_flags = 0;
116
+
117
+ if (!m_task_stack.try_push(tsk))
118
+ return false;
119
+
120
+ atomic_increment32(&m_num_outstanding_tasks);
121
+
122
+ m_tasks_available.release(1);
123
+
124
+ return true;
125
+ }
126
+
127
+ // It's the object's responsibility to delete pObj within the execute_task() method, if needed!
128
+ bool task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
129
+ {
130
+ LZHAM_ASSERT(m_num_threads);
131
+ LZHAM_ASSERT(pObj);
132
+
133
+ task tsk;
134
+ tsk.m_pObj = pObj;
135
+ tsk.m_data = data;
136
+ tsk.m_pData_ptr = pData_ptr;
137
+ tsk.m_flags = cTaskFlagObject;
138
+
139
+ if (!m_task_stack.try_push(tsk))
140
+ return false;
141
+
142
+ atomic_increment32(&m_num_outstanding_tasks);
143
+
144
+ m_tasks_available.release(1);
145
+
146
+ return true;
147
+ }
148
+
149
+ void task_pool::process_task(task& tsk)
150
+ {
151
+ if (tsk.m_flags & cTaskFlagObject)
152
+ tsk.m_pObj->execute_task(tsk.m_data, tsk.m_pData_ptr);
153
+ else
154
+ tsk.m_callback(tsk.m_data, tsk.m_pData_ptr);
155
+
156
+ atomic_decrement32(&m_num_outstanding_tasks);
157
+ }
158
+
159
+ void task_pool::join()
160
+ {
161
+ while (atomic_add32(&m_num_outstanding_tasks, 0) > 0)
162
+ {
163
+ task tsk;
164
+ if (m_task_stack.pop(tsk))
165
+ {
166
+ process_task(tsk);
167
+ }
168
+ else
169
+ {
170
+ lzham_sleep(1);
171
+ }
172
+ }
173
+ }
174
+
175
+ unsigned __stdcall task_pool::thread_func(void* pContext)
176
+ {
177
+ task_pool* pPool = static_cast<task_pool*>(pContext);
178
+
179
+ for ( ; ; )
180
+ {
181
+ if (!pPool->m_tasks_available.wait())
182
+ break;
183
+
184
+ if (pPool->m_exit_flag)
185
+ break;
186
+
187
+ task tsk;
188
+ if (pPool->m_task_stack.pop(tsk))
189
+ {
190
+ pPool->process_task(tsk);
191
+ }
192
+ }
193
+
194
+ _endthreadex(0);
195
+ return 0;
196
+ }
197
+
198
+ static uint g_num_processors;
199
+
200
+ uint lzham_get_max_helper_threads()
201
+ {
202
+ if (!g_num_processors)
203
+ {
204
+ SYSTEM_INFO system_info;
205
+ GetSystemInfo(&system_info);
206
+ g_num_processors = system_info.dwNumberOfProcessors;
207
+ }
208
+
209
+ if (g_num_processors > 1)
210
+ {
211
+ // use all CPU's
212
+ return LZHAM_MIN(task_pool::cMaxThreads, g_num_processors - 1);
213
+ }
214
+
215
+ return 0;
216
+ }
217
+
218
+ } // namespace lzham
219
+
220
+ #endif // LZHAM_USE_WIN32_API
@@ -0,0 +1,368 @@
1
+ // File: lzham_task_pool_win32.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+
5
+ #if LZHAM_USE_WIN32_API
6
+
7
+ #if LZHAM_NO_ATOMICS
8
+ #error No atomic operations defined in lzham_platform.h!
9
+ #endif
10
+
11
+ namespace lzham
12
+ {
13
+ class semaphore
14
+ {
15
+ LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
16
+
17
+ public:
18
+ semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
19
+ {
20
+ m_handle = CreateSemaphoreA(NULL, initialCount, maximumCount, pName);
21
+ if (NULL == m_handle)
22
+ {
23
+ LZHAM_FAIL("semaphore: CreateSemaphore() failed");
24
+ }
25
+ }
26
+
27
+ ~semaphore()
28
+ {
29
+ if (m_handle)
30
+ {
31
+ CloseHandle(m_handle);
32
+ m_handle = NULL;
33
+ }
34
+ }
35
+
36
+ inline HANDLE get_handle(void) const { return m_handle; }
37
+
38
+ void release(long releaseCount = 1)
39
+ {
40
+ if (0 == ReleaseSemaphore(m_handle, releaseCount, NULL))
41
+ {
42
+ LZHAM_FAIL("semaphore: ReleaseSemaphore() failed");
43
+ }
44
+ }
45
+
46
+ bool wait(uint32 milliseconds = UINT32_MAX)
47
+ {
48
+ LZHAM_ASSUME(INFINITE == UINT32_MAX);
49
+
50
+ DWORD result = WaitForSingleObject(m_handle, milliseconds);
51
+
52
+ if (WAIT_FAILED == result)
53
+ {
54
+ LZHAM_FAIL("semaphore: WaitForSingleObject() failed");
55
+ }
56
+
57
+ return WAIT_OBJECT_0 == result;
58
+ }
59
+
60
+ private:
61
+ HANDLE m_handle;
62
+ };
63
+
64
+ template<typename T>
65
+ class tsstack
66
+ {
67
+ public:
68
+ inline tsstack(bool use_freelist = true) :
69
+ m_use_freelist(use_freelist)
70
+ {
71
+ LZHAM_VERIFY(((ptr_bits_t)this & (LZHAM_GET_ALIGNMENT(tsstack) - 1)) == 0);
72
+ InitializeSListHead(&m_stack_head);
73
+ InitializeSListHead(&m_freelist_head);
74
+ }
75
+
76
+ inline ~tsstack()
77
+ {
78
+ clear();
79
+ }
80
+
81
+ inline void clear()
82
+ {
83
+ for ( ; ; )
84
+ {
85
+ node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
86
+ if (!pNode)
87
+ break;
88
+
89
+ LZHAM_MEMORY_IMPORT_BARRIER
90
+
91
+ helpers::destruct(&pNode->m_obj);
92
+
93
+ lzham_free(pNode);
94
+ }
95
+
96
+ flush_freelist();
97
+ }
98
+
99
+ inline void flush_freelist()
100
+ {
101
+ if (!m_use_freelist)
102
+ return;
103
+
104
+ for ( ; ; )
105
+ {
106
+ node* pNode = (node*)InterlockedPopEntrySList(&m_freelist_head);
107
+ if (!pNode)
108
+ break;
109
+
110
+ LZHAM_MEMORY_IMPORT_BARRIER
111
+
112
+ lzham_free(pNode);
113
+ }
114
+ }
115
+
116
+ inline bool try_push(const T& obj)
117
+ {
118
+ node* pNode = alloc_node();
119
+ if (!pNode)
120
+ return false;
121
+
122
+ helpers::construct(&pNode->m_obj, obj);
123
+
124
+ LZHAM_MEMORY_EXPORT_BARRIER
125
+
126
+ InterlockedPushEntrySList(&m_stack_head, &pNode->m_slist_entry);
127
+
128
+ return true;
129
+ }
130
+
131
+ inline bool pop(T& obj)
132
+ {
133
+ node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
134
+ if (!pNode)
135
+ return false;
136
+
137
+ LZHAM_MEMORY_IMPORT_BARRIER
138
+
139
+ obj = pNode->m_obj;
140
+
141
+ helpers::destruct(&pNode->m_obj);
142
+
143
+ free_node(pNode);
144
+
145
+ return true;
146
+ }
147
+
148
+ private:
149
+ SLIST_HEADER m_stack_head;
150
+ SLIST_HEADER m_freelist_head;
151
+
152
+ struct node
153
+ {
154
+ SLIST_ENTRY m_slist_entry;
155
+ T m_obj;
156
+ };
157
+
158
+ bool m_use_freelist;
159
+
160
+ inline node* alloc_node()
161
+ {
162
+ node* pNode = m_use_freelist ? (node*)InterlockedPopEntrySList(&m_freelist_head) : NULL;
163
+
164
+ if (!pNode)
165
+ pNode = (node*)lzham_malloc(sizeof(node));
166
+
167
+ return pNode;
168
+ }
169
+
170
+ inline void free_node(node* pNode)
171
+ {
172
+ if (m_use_freelist)
173
+ InterlockedPushEntrySList(&m_freelist_head, &pNode->m_slist_entry);
174
+ else
175
+ lzham_free(pNode);
176
+ }
177
+ };
178
+
179
+ class task_pool
180
+ {
181
+ public:
182
+ task_pool();
183
+ task_pool(uint num_threads);
184
+ ~task_pool();
185
+
186
+ enum { cMaxThreads = LZHAM_MAX_HELPER_THREADS };
187
+ bool init(uint num_threads);
188
+ void deinit();
189
+
190
+ inline uint get_num_threads() const { return m_num_threads; }
191
+ inline uint get_num_outstanding_tasks() const { return m_num_outstanding_tasks; }
192
+
193
+ // C-style task callback
194
+ typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
195
+ bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL);
196
+
197
+ class executable_task
198
+ {
199
+ public:
200
+ virtual void execute_task(uint64 data, void* pData_ptr) = 0;
201
+ };
202
+
203
+ // It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
204
+ bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL);
205
+
206
+ template<typename S, typename T>
207
+ inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL);
208
+
209
+ template<typename S, typename T>
210
+ inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL);
211
+
212
+ void join();
213
+
214
+ private:
215
+ struct task
216
+ {
217
+ //inline task() : m_data(0), m_pData_ptr(NULL), m_pObj(NULL), m_flags(0) { }
218
+
219
+ uint64 m_data;
220
+ void* m_pData_ptr;
221
+
222
+ union
223
+ {
224
+ task_callback_func m_callback;
225
+ executable_task* m_pObj;
226
+ };
227
+
228
+ uint m_flags;
229
+ };
230
+
231
+ tsstack<task> m_task_stack;
232
+
233
+ uint m_num_threads;
234
+ HANDLE m_threads[cMaxThreads];
235
+
236
+ semaphore m_tasks_available;
237
+
238
+ enum task_flags
239
+ {
240
+ cTaskFlagObject = 1
241
+ };
242
+
243
+ volatile atomic32_t m_num_outstanding_tasks;
244
+ volatile atomic32_t m_exit_flag;
245
+
246
+ void process_task(task& tsk);
247
+
248
+ static unsigned __stdcall thread_func(void* pContext);
249
+ };
250
+
251
+ enum object_task_flags
252
+ {
253
+ cObjectTaskFlagDefault = 0,
254
+ cObjectTaskFlagDeleteAfterExecution = 1
255
+ };
256
+
257
+ template<typename T>
258
+ class object_task : public task_pool::executable_task
259
+ {
260
+ public:
261
+ object_task(uint flags = cObjectTaskFlagDefault) :
262
+ m_pObject(NULL),
263
+ m_pMethod(NULL),
264
+ m_flags(flags)
265
+ {
266
+ }
267
+
268
+ typedef void (T::*object_method_ptr)(uint64 data, void* pData_ptr);
269
+
270
+ object_task(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault) :
271
+ m_pObject(pObject),
272
+ m_pMethod(pMethod),
273
+ m_flags(flags)
274
+ {
275
+ LZHAM_ASSERT(pObject && pMethod);
276
+ }
277
+
278
+ void init(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault)
279
+ {
280
+ LZHAM_ASSERT(pObject && pMethod);
281
+
282
+ m_pObject = pObject;
283
+ m_pMethod = pMethod;
284
+ m_flags = flags;
285
+ }
286
+
287
+ T* get_object() const { return m_pObject; }
288
+ object_method_ptr get_method() const { return m_pMethod; }
289
+
290
+ virtual void execute_task(uint64 data, void* pData_ptr)
291
+ {
292
+ (m_pObject->*m_pMethod)(data, pData_ptr);
293
+
294
+ if (m_flags & cObjectTaskFlagDeleteAfterExecution)
295
+ lzham_delete(this);
296
+ }
297
+
298
+ protected:
299
+ T* m_pObject;
300
+
301
+ object_method_ptr m_pMethod;
302
+
303
+ uint m_flags;
304
+ };
305
+
306
+ template<typename S, typename T>
307
+ inline bool task_pool::queue_object_task(S* pObject, T pObject_method, uint64 data, void* pData_ptr)
308
+ {
309
+ object_task<S> *pTask = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
310
+ if (!pTask)
311
+ return false;
312
+ return queue_task(pTask, data, pData_ptr);
313
+ }
314
+
315
+ template<typename S, typename T>
316
+ inline bool task_pool::queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr)
317
+ {
318
+ LZHAM_ASSERT(m_num_threads);
319
+ LZHAM_ASSERT(pObject);
320
+ LZHAM_ASSERT(num_tasks);
321
+ if (!num_tasks)
322
+ return true;
323
+
324
+ bool status = true;
325
+
326
+ uint i;
327
+ for (i = 0; i < num_tasks; i++)
328
+ {
329
+ task tsk;
330
+
331
+ tsk.m_pObj = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
332
+ if (!tsk.m_pObj)
333
+ {
334
+ status = false;
335
+ break;
336
+ }
337
+
338
+ tsk.m_data = first_data + i;
339
+ tsk.m_pData_ptr = pData_ptr;
340
+ tsk.m_flags = cTaskFlagObject;
341
+
342
+ if (!m_task_stack.try_push(tsk))
343
+ {
344
+ status = false;
345
+ break;
346
+ }
347
+ }
348
+
349
+ if (i)
350
+ {
351
+ atomic_add32(&m_num_outstanding_tasks, i);
352
+
353
+ m_tasks_available.release(i);
354
+ }
355
+
356
+ return status;
357
+ }
358
+
359
+ inline void lzham_sleep(unsigned int milliseconds)
360
+ {
361
+ Sleep(milliseconds);
362
+ }
363
+
364
+ uint lzham_get_max_helper_threads();
365
+
366
+ } // namespace lzham
367
+
368
+ #endif // LZHAM_USE_WIN32_API