koffi 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/ChangeLog.md +6 -0
  2. package/build/qemu/2.1.2/koffi_darwin_arm64.tar.gz +0 -0
  3. package/build/qemu/2.1.2/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/2.1.2/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/2.1.2/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/2.1.2/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/2.1.2/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/build/qemu/2.1.2/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/2.1.2/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/2.1.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/build/qemu/2.1.2/koffi_linux_x64.tar.gz +0 -0
  12. package/build/qemu/2.1.2/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/build/qemu/2.1.2/koffi_openbsd_x64.tar.gz +0 -0
  14. package/build/qemu/2.1.2/koffi_win32_arm64.tar.gz +0 -0
  15. package/build/qemu/2.1.2/koffi_win32_ia32.tar.gz +0 -0
  16. package/build/qemu/2.1.2/koffi_win32_x64.tar.gz +0 -0
  17. package/doc/templates/badges.html +3 -0
  18. package/package.json +2 -2
  19. package/src/abi_arm64.cc +35 -1
  20. package/src/abi_x64_win.cc +2 -8
  21. package/src/abi_x86.cc +1 -7
  22. package/src/ffi.hh +1 -1
  23. package/src/util.hh +6 -0
  24. package/test/raylib.js +37 -5
  25. package/vendor/libcc/libcc.cc +430 -196
  26. package/vendor/libcc/libcc.hh +1417 -1283
  27. package/vendor/raylib/BINDINGS.md +87 -70
  28. package/vendor/raylib/CHANGELOG +263 -50
  29. package/vendor/raylib/CMakeLists.txt +12 -0
  30. package/vendor/raylib/CMakeOptions.txt +8 -1
  31. package/vendor/raylib/CONVENTIONS.md +2 -3
  32. package/vendor/raylib/FAQ.md +137 -0
  33. package/vendor/raylib/HISTORY.md +62 -29
  34. package/vendor/raylib/LICENSE +1 -1
  35. package/vendor/raylib/README.md +22 -17
  36. package/vendor/raylib/ROADMAP.md +8 -7
  37. package/vendor/raylib/cmake/CompileDefinitions.cmake +19 -15
  38. package/vendor/raylib/cmake/GlfwImport.cmake +2 -0
  39. package/vendor/raylib/cmake/LibraryConfigurations.cmake +22 -16
  40. package/vendor/raylib/cmake/raylib-config.cmake +52 -49
  41. package/vendor/raylib/examples/CMakeLists.txt +14 -9
  42. package/vendor/raylib/examples/Makefile +112 -125
  43. package/vendor/raylib/examples/Makefile.Android +1 -1
  44. package/vendor/raylib/examples/Makefile.Web +145 -158
  45. package/vendor/raylib/examples/README.md +141 -141
  46. package/vendor/raylib/examples/audio/audio_module_playing.c +9 -4
  47. package/vendor/raylib/examples/audio/audio_multichannel_sound.c +8 -3
  48. package/vendor/raylib/examples/audio/audio_music_stream.c +16 -11
  49. package/vendor/raylib/examples/audio/audio_raw_stream.c +57 -9
  50. package/vendor/raylib/examples/audio/audio_sound_loading.c +8 -3
  51. package/vendor/raylib/examples/audio/audio_stream_effects.c +179 -0
  52. package/vendor/raylib/examples/audio/audio_stream_effects.png +0 -0
  53. package/vendor/raylib/examples/build.zig +17 -6
  54. package/vendor/raylib/examples/core/core_2d_camera.c +8 -4
  55. package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.c +105 -0
  56. package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.png +0 -0
  57. package/vendor/raylib/examples/core/core_2d_camera_platformer.c +11 -6
  58. package/vendor/raylib/examples/core/core_3d_camera_first_person.c +9 -4
  59. package/vendor/raylib/examples/core/core_3d_camera_free.c +9 -4
  60. package/vendor/raylib/examples/core/core_3d_camera_mode.c +8 -3
  61. package/vendor/raylib/examples/core/core_3d_picking.c +9 -4
  62. package/vendor/raylib/examples/core/core_basic_screen_manager.c +9 -7
  63. package/vendor/raylib/examples/core/core_basic_window.c +8 -3
  64. package/vendor/raylib/examples/core/core_basic_window_web.c +13 -11
  65. package/vendor/raylib/examples/core/core_custom_frame_control.c +9 -4
  66. package/vendor/raylib/examples/core/core_custom_logging.c +12 -8
  67. package/vendor/raylib/examples/core/core_drop_files.c +20 -12
  68. package/vendor/raylib/examples/core/core_input_gamepad.c +20 -15
  69. package/vendor/raylib/examples/core/core_input_gestures.c +19 -15
  70. package/vendor/raylib/examples/core/core_input_keys.c +8 -3
  71. package/vendor/raylib/examples/core/core_input_mouse.c +8 -3
  72. package/vendor/raylib/examples/core/core_input_mouse_wheel.c +8 -3
  73. package/vendor/raylib/examples/core/core_input_multitouch.c +8 -3
  74. package/vendor/raylib/examples/core/core_loading_thread.c +10 -6
  75. package/vendor/raylib/examples/core/core_random_values.c +8 -3
  76. package/vendor/raylib/examples/core/core_scissor_test.c +8 -3
  77. package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +9 -4
  78. package/vendor/raylib/examples/core/core_split_screen.c +8 -3
  79. package/vendor/raylib/examples/core/core_storage_values.c +109 -3
  80. package/vendor/raylib/examples/core/core_vr_simulator.c +15 -7
  81. package/vendor/raylib/examples/core/core_window_flags.c +8 -3
  82. package/vendor/raylib/examples/core/core_window_letterbox.c +13 -18
  83. package/vendor/raylib/examples/core/core_window_should_close.c +77 -0
  84. package/vendor/raylib/examples/core/core_window_should_close.png +0 -0
  85. package/vendor/raylib/examples/core/core_world_screen.c +9 -4
  86. package/vendor/raylib/examples/examples_template.c +8 -3
  87. package/vendor/raylib/examples/models/models_animation.c +11 -7
  88. package/vendor/raylib/examples/models/models_billboard.c +9 -4
  89. package/vendor/raylib/examples/models/models_box_collisions.c +8 -3
  90. package/vendor/raylib/examples/models/models_cubicmap.c +9 -4
  91. package/vendor/raylib/examples/models/models_first_person_maze.c +9 -4
  92. package/vendor/raylib/examples/models/models_geometric_shapes.c +8 -3
  93. package/vendor/raylib/examples/models/models_heightmap.c +9 -4
  94. package/vendor/raylib/examples/models/models_loading.c +21 -17
  95. package/vendor/raylib/examples/models/models_loading_gltf.c +15 -41
  96. package/vendor/raylib/examples/models/models_loading_vox.c +9 -4
  97. package/vendor/raylib/examples/models/models_mesh_generation.c +71 -58
  98. package/vendor/raylib/examples/models/models_mesh_picking.c +25 -7
  99. package/vendor/raylib/examples/models/models_orthographic_projection.c +8 -5
  100. package/vendor/raylib/examples/models/models_rlgl_solar_system.c +6 -4
  101. package/vendor/raylib/examples/models/models_skybox.c +16 -12
  102. package/vendor/raylib/examples/models/models_waving_cubes.c +9 -4
  103. package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +12 -7
  104. package/vendor/raylib/examples/models/resources/LICENSE.md +9 -10
  105. package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +2 -23
  106. package/vendor/raylib/examples/models/resources/models/gltf/{raylib_32x32.glb → raylib_logo_3d.glb} +0 -0
  107. package/vendor/raylib/examples/models/resources/models/gltf/robot.blend +0 -0
  108. package/vendor/raylib/examples/models/resources/models/gltf/robot.glb +0 -0
  109. package/vendor/raylib/examples/others/easings_testbed.c +10 -8
  110. package/vendor/raylib/examples/others/easings_testbed.png +0 -0
  111. package/vendor/raylib/examples/others/embedded_files_loading.c +10 -5
  112. package/vendor/raylib/examples/others/embedded_files_loading.png +0 -0
  113. package/vendor/raylib/examples/others/raylib_opengl_interop.c +10 -6
  114. package/vendor/raylib/{src/extras/easings.h → examples/others/reasings.h} +38 -38
  115. package/vendor/raylib/examples/others/rlgl_compute_shader.c +21 -20
  116. package/vendor/raylib/examples/others/rlgl_compute_shader.png +0 -0
  117. package/vendor/raylib/examples/others/rlgl_standalone.c +4 -4
  118. package/vendor/raylib/examples/others/rlgl_standalone.png +0 -0
  119. package/vendor/raylib/examples/raylib_compile_execute.bat +2 -2
  120. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +1 -1
  121. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/{base_lighting_instanced.vs → lighting_instancing.vs} +2 -2
  122. package/vendor/raylib/examples/shaders/rlights.h +14 -27
  123. package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +24 -26
  124. package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +10 -5
  125. package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +13 -8
  126. package/vendor/raylib/examples/shaders/shaders_fog.c +8 -12
  127. package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +10 -5
  128. package/vendor/raylib/examples/shaders/shaders_julia_set.c +9 -4
  129. package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +45 -119
  130. package/vendor/raylib/examples/shaders/shaders_model_shader.c +10 -5
  131. package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +8 -3
  132. package/vendor/raylib/examples/shaders/shaders_palette_switch.c +8 -3
  133. package/vendor/raylib/examples/shaders/shaders_postprocessing.c +9 -4
  134. package/vendor/raylib/examples/shaders/shaders_raymarching.c +14 -11
  135. package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +8 -3
  136. package/vendor/raylib/examples/shaders/shaders_simple_mask.c +10 -5
  137. package/vendor/raylib/examples/shaders/shaders_spotlight.c +10 -6
  138. package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +9 -4
  139. package/vendor/raylib/examples/shaders/shaders_texture_outline.c +8 -3
  140. package/vendor/raylib/examples/shaders/shaders_texture_waves.c +8 -3
  141. package/vendor/raylib/{src/extras → examples/shapes}/raygui.h +1290 -1141
  142. package/vendor/raylib/examples/{others/easings.h → shapes/reasings.h} +40 -40
  143. package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +8 -3
  144. package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +8 -3
  145. package/vendor/raylib/examples/shapes/shapes_collision_area.c +10 -4
  146. package/vendor/raylib/examples/shapes/shapes_colors_palette.c +8 -3
  147. package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +9 -4
  148. package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +9 -4
  149. package/vendor/raylib/examples/shapes/shapes_draw_ring.c +10 -6
  150. package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +9 -4
  151. package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +9 -4
  152. package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +9 -4
  153. package/vendor/raylib/examples/shapes/shapes_following_eyes.c +8 -3
  154. package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +8 -3
  155. package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +8 -3
  156. package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +8 -3
  157. package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +14 -5
  158. package/vendor/raylib/examples/shapes/shapes_top_down_lights.c +355 -0
  159. package/vendor/raylib/examples/shapes/shapes_top_down_lights.png +0 -0
  160. package/vendor/raylib/examples/text/resources/DotGothic16-Regular.ttf +0 -0
  161. package/vendor/raylib/examples/text/resources/DotGothic16-Regular_OFL.txt +93 -0
  162. package/vendor/raylib/examples/text/resources/LICENSE.md +1 -1
  163. package/vendor/raylib/examples/text/text_codepoints_loading.c +138 -0
  164. package/vendor/raylib/examples/text/text_codepoints_loading.png +0 -0
  165. package/vendor/raylib/examples/text/text_draw_3d.c +42 -33
  166. package/vendor/raylib/examples/text/text_font_filters.c +14 -11
  167. package/vendor/raylib/examples/text/text_font_loading.c +9 -4
  168. package/vendor/raylib/examples/text/text_font_sdf.c +9 -4
  169. package/vendor/raylib/examples/text/text_font_spritefont.c +12 -6
  170. package/vendor/raylib/examples/text/text_format_text.c +8 -3
  171. package/vendor/raylib/examples/text/text_input_box.c +8 -3
  172. package/vendor/raylib/examples/text/text_raylib_fonts.c +9 -4
  173. package/vendor/raylib/examples/text/text_rectangle_bounds.c +9 -5
  174. package/vendor/raylib/examples/text/text_unicode.c +9 -7
  175. package/vendor/raylib/examples/text/text_writing_anim.c +8 -3
  176. package/vendor/raylib/examples/textures/resources/scarfy_run.gif +0 -0
  177. package/vendor/raylib/examples/textures/textures_background_scrolling.c +8 -3
  178. package/vendor/raylib/examples/textures/textures_blend_modes.c +8 -3
  179. package/vendor/raylib/examples/textures/textures_bunnymark.c +8 -3
  180. package/vendor/raylib/examples/textures/textures_draw_tiled.c +14 -10
  181. package/vendor/raylib/examples/textures/textures_fog_of_war.c +154 -0
  182. package/vendor/raylib/examples/textures/textures_fog_of_war.png +0 -0
  183. package/vendor/raylib/examples/textures/textures_gif_player.c +121 -0
  184. package/vendor/raylib/examples/textures/textures_gif_player.png +0 -0
  185. package/vendor/raylib/examples/textures/textures_image_drawing.c +8 -3
  186. package/vendor/raylib/examples/textures/textures_image_generation.c +8 -3
  187. package/vendor/raylib/examples/textures/textures_image_loading.c +8 -3
  188. package/vendor/raylib/examples/textures/textures_image_processing.c +8 -3
  189. package/vendor/raylib/examples/textures/textures_image_text.c +8 -3
  190. package/vendor/raylib/examples/textures/textures_logo_raylib.c +8 -3
  191. package/vendor/raylib/examples/textures/textures_mouse_painting.c +9 -4
  192. package/vendor/raylib/examples/textures/textures_npatch_drawing.c +8 -3
  193. package/vendor/raylib/examples/textures/textures_particles_blending.c +8 -3
  194. package/vendor/raylib/examples/textures/textures_polygon.c +9 -5
  195. package/vendor/raylib/examples/textures/textures_raw_data.c +8 -3
  196. package/vendor/raylib/examples/textures/{textures_rectangle.c → textures_sprite_anim.c} +11 -5
  197. package/vendor/raylib/examples/textures/{textures_rectangle.png → textures_sprite_anim.png} +0 -0
  198. package/vendor/raylib/examples/textures/textures_sprite_button.c +8 -3
  199. package/vendor/raylib/examples/textures/textures_sprite_explosion.c +8 -3
  200. package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +8 -3
  201. package/vendor/raylib/examples/textures/textures_to_image.c +8 -3
  202. package/vendor/raylib/parser/LICENSE +1 -1
  203. package/vendor/raylib/parser/Makefile +28 -0
  204. package/vendor/raylib/parser/README.md +49 -5
  205. package/vendor/raylib/parser/output/raylib_api.json +10717 -0
  206. package/vendor/raylib/parser/output/raylib_api.lua +7435 -0
  207. package/vendor/raylib/parser/{raylib_api.txt → output/raylib_api.txt} +1371 -824
  208. package/vendor/raylib/parser/{raylib_api.xml → output/raylib_api.xml} +827 -595
  209. package/vendor/raylib/parser/raylib_parser.c +1174 -196
  210. package/vendor/raylib/projects/4coder/Makefile +2 -4
  211. package/vendor/raylib/projects/4coder/main.c +0 -1
  212. package/vendor/raylib/projects/CMake/CMakeLists.txt +13 -16
  213. package/vendor/raylib/projects/CMake/README.md +27 -0
  214. package/vendor/raylib/projects/CMake/core_basic_window.c +52 -31
  215. package/vendor/raylib/projects/CodeBlocks/README.md +4 -4
  216. package/vendor/raylib/projects/Geany/core_basic_window.c +1 -1
  217. package/vendor/raylib/projects/Notepad++/c_raylib.xml +168 -128
  218. package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
  219. package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
  220. package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
  221. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +168 -84
  222. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +67 -51
  223. package/vendor/raylib/projects/README.md +1 -1
  224. package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +1 -1
  225. package/vendor/raylib/projects/VSCode/Makefile +8 -11
  226. package/vendor/raylib/projects/VSCode/main.c +53 -26
  227. package/vendor/raylib/projects/VSCode/resources/LICENSE +1 -0
  228. package/vendor/raylib/projects/scripts/build-linux.sh +6 -6
  229. package/vendor/raylib/projects/scripts/build-osx.sh +6 -6
  230. package/vendor/raylib/projects/scripts/build-rpi.sh +6 -6
  231. package/vendor/raylib/projects/scripts/build-windows.bat +2 -2
  232. package/vendor/raylib/src/CMakeLists.txt +6 -7
  233. package/vendor/raylib/src/Makefile +209 -103
  234. package/vendor/raylib/src/build.zig +56 -20
  235. package/vendor/raylib/src/config.h +32 -27
  236. package/vendor/raylib/src/external/cgltf.h +342 -104
  237. package/vendor/raylib/src/external/dr_wav.h +487 -225
  238. package/vendor/raylib/src/external/glfw/src/posix_time.c +1 -3
  239. package/vendor/raylib/src/external/glfw/src/wl_init.c +1 -3
  240. package/vendor/raylib/src/external/jar_xm.h +2 -1
  241. package/vendor/raylib/src/external/miniaudio.h +62251 -42061
  242. package/vendor/raylib/src/external/qoi.h +671 -0
  243. package/vendor/raylib/src/external/stb_vorbis.h +1 -1
  244. package/vendor/raylib/src/external/vox_loader.h +30 -25
  245. package/vendor/raylib/src/minshell.html +82 -0
  246. package/vendor/raylib/src/raudio.c +359 -201
  247. package/vendor/raylib/src/raylib.dll.rc +5 -5
  248. package/vendor/raylib/src/raylib.dll.rc.data +0 -0
  249. package/vendor/raylib/src/raylib.h +95 -63
  250. package/vendor/raylib/src/raylib.rc +5 -5
  251. package/vendor/raylib/src/raylib.rc.data +0 -0
  252. package/vendor/raylib/src/raymath.h +391 -133
  253. package/vendor/raylib/src/rcamera.h +32 -41
  254. package/vendor/raylib/src/rcore.c +775 -471
  255. package/vendor/raylib/src/rgestures.h +5 -5
  256. package/vendor/raylib/src/rglfw.c +3 -3
  257. package/vendor/raylib/src/rlgl.h +184 -144
  258. package/vendor/raylib/src/rmodels.c +207 -144
  259. package/vendor/raylib/src/rshapes.c +105 -47
  260. package/vendor/raylib/src/rtext.c +255 -38
  261. package/vendor/raylib/src/rtextures.c +167 -71
  262. package/vendor/raylib/src/shell.html +63 -63
  263. package/vendor/raylib/src/utils.c +49 -3
  264. package/vendor/raylib/src/utils.h +3 -3
  265. package/build/qemu/2.1.1/koffi_darwin_arm64.tar.gz +0 -0
  266. package/build/qemu/2.1.1/koffi_darwin_x64.tar.gz +0 -0
  267. package/build/qemu/2.1.1/koffi_freebsd_arm64.tar.gz +0 -0
  268. package/build/qemu/2.1.1/koffi_freebsd_ia32.tar.gz +0 -0
  269. package/build/qemu/2.1.1/koffi_freebsd_x64.tar.gz +0 -0
  270. package/build/qemu/2.1.1/koffi_linux_arm32hf.tar.gz +0 -0
  271. package/build/qemu/2.1.1/koffi_linux_arm64.tar.gz +0 -0
  272. package/build/qemu/2.1.1/koffi_linux_ia32.tar.gz +0 -0
  273. package/build/qemu/2.1.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  274. package/build/qemu/2.1.1/koffi_linux_x64.tar.gz +0 -0
  275. package/build/qemu/2.1.1/koffi_openbsd_ia32.tar.gz +0 -0
  276. package/build/qemu/2.1.1/koffi_openbsd_x64.tar.gz +0 -0
  277. package/build/qemu/2.1.1/koffi_win32_arm64.tar.gz +0 -0
  278. package/build/qemu/2.1.1/koffi_win32_ia32.tar.gz +0 -0
  279. package/build/qemu/2.1.1/koffi_win32_x64.tar.gz +0 -0
  280. package/vendor/raylib/CONTRIBUTORS.md +0 -63
  281. package/vendor/raylib/SPONSORS.md +0 -68
  282. package/vendor/raylib/examples/core/core_quat_conversion.c +0 -132
  283. package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
  284. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
  285. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +0 -118
  286. package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
  287. package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
  288. package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
  289. package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
  290. package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
  291. package/vendor/raylib/examples/models/rlights.h +0 -183
  292. package/vendor/raylib/examples/others/raudio_standalone.c +0 -152
  293. package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
  294. package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
  295. package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
  296. package/vendor/raylib/examples/physics/physics_demo.c +0 -128
  297. package/vendor/raylib/examples/physics/physics_demo.png +0 -0
  298. package/vendor/raylib/examples/physics/physics_friction.c +0 -142
  299. package/vendor/raylib/examples/physics/physics_friction.png +0 -0
  300. package/vendor/raylib/examples/physics/physics_movement.c +0 -128
  301. package/vendor/raylib/examples/physics/physics_movement.png +0 -0
  302. package/vendor/raylib/examples/physics/physics_restitution.c +0 -129
  303. package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
  304. package/vendor/raylib/examples/physics/physics_shatter.c +0 -111
  305. package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
  306. package/vendor/raylib/parser/raylib_api.json +0 -6668
  307. package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
  308. package/vendor/raylib/projects/VS2019/raylib/resource.h +0 -14
  309. package/vendor/raylib/src/extras/physac.h +0 -1977
  310. package/vendor/raylib/src/extras/rmem.h +0 -751
  311. package/vendor/raylib/src/raudio.h +0 -198
@@ -87,19 +87,11 @@
87
87
  #ifdef __APPLE__
88
88
  #include <sys/random.h>
89
89
  #include <mach-o/dyld.h>
90
-
91
- #define off64_t off_t
92
- #define fseeko64 fseeko
93
- #define ftello64 ftello
94
90
  #endif
95
91
  #if defined(__OpenBSD__) || defined(__FreeBSD__)
96
92
  #include <pthread_np.h>
97
93
  #include <sys/param.h>
98
94
  #include <sys/sysctl.h>
99
-
100
- #define off64_t off_t
101
- #define fseeko64 fseeko
102
- #define ftello64 ftello
103
95
  #endif
104
96
  #include <chrono>
105
97
  #include <random>
@@ -141,7 +133,7 @@ protected:
141
133
  void *ptr = malloc((size_t)size);
142
134
  RG_CRITICAL(ptr, "Failed to allocate %1 of memory", FmtMemSize(size));
143
135
 
144
- if (flags & (int)Allocator::Flag::Zero) {
136
+ if (flags & (int)AllocFlag::Zero) {
145
137
  memset_safe(ptr, 0, (size_t)size);
146
138
  }
147
139
 
@@ -158,7 +150,7 @@ protected:
158
150
  RG_CRITICAL(new_ptr || !new_size, "Failed to resize %1 memory block to %2",
159
151
  FmtMemSize(old_size), FmtMemSize(new_size));
160
152
 
161
- if ((flags & (int)Allocator::Flag::Zero) && new_size > old_size) {
153
+ if ((flags & (int)AllocFlag::Zero) && new_size > old_size) {
162
154
  memset_safe((uint8_t *)new_ptr + old_size, 0, (size_t)(new_size - old_size));
163
155
  }
164
156
 
@@ -168,9 +160,9 @@ protected:
168
160
  return ptr;
169
161
  }
170
162
 
171
- void Release(void *ptr, Size) override
163
+ void Release(const void *ptr, Size) override
172
164
  {
173
- free(ptr);
165
+ free((void *)ptr);
174
166
  }
175
167
  };
176
168
 
@@ -178,7 +170,7 @@ class NullAllocator: public Allocator {
178
170
  protected:
179
171
  void *Allocate(Size, unsigned int) override { RG_UNREACHABLE(); }
180
172
  void *Resize(void *, Size, Size, unsigned int) override { RG_UNREACHABLE(); }
181
- void Release(void *, Size) override {}
173
+ void Release(const void *, Size) override {}
182
174
  };
183
175
 
184
176
  Allocator *GetDefaultAllocator()
@@ -262,10 +254,10 @@ void *LinkedAllocator::Resize(void *ptr, Size old_size, Size new_size, unsigned
262
254
  return ptr;
263
255
  }
264
256
 
265
- void LinkedAllocator::Release(void *ptr, Size size)
257
+ void LinkedAllocator::Release(const void *ptr, Size size)
266
258
  {
267
259
  if (ptr) {
268
- Bucket *bucket = PointerToBucket(ptr);
260
+ Bucket *bucket = PointerToBucket((void *)ptr);
269
261
 
270
262
  if (bucket->head.next) {
271
263
  bucket->head.next->prev = bucket->head.prev;
@@ -303,14 +295,14 @@ void *BlockAllocatorBase::Allocate(Size size, unsigned int flags)
303
295
  } else {
304
296
  if (!current_bucket || (current_bucket->used + aligned_size) > block_size) {
305
297
  current_bucket = (Bucket *)AllocateRaw(alloc, RG_SIZE(Bucket) + block_size,
306
- flags & ~(int)Allocator::Flag::Zero);
298
+ flags & ~(int)AllocFlag::Zero);
307
299
  current_bucket->used = 0;
308
300
  }
309
301
 
310
302
  uint8_t *ptr = current_bucket->data + current_bucket->used;
311
303
  current_bucket->used += aligned_size;
312
304
 
313
- if (flags & (int)Allocator::Flag::Zero) {
305
+ if (flags & (int)AllocFlag::Zero) {
314
306
  memset_safe(ptr, 0, size);
315
307
  }
316
308
 
@@ -342,18 +334,18 @@ void *BlockAllocatorBase::Resize(void *ptr, Size old_size, Size new_size, unsign
342
334
  !AllocateSeparately(aligned_new_size)) {
343
335
  current_bucket->used += aligned_delta;
344
336
 
345
- if ((flags & (int)Allocator::Flag::Zero) && new_size > old_size) {
337
+ if ((flags & (int)AllocFlag::Zero) && new_size > old_size) {
346
338
  memset_safe((uint8_t *)ptr + old_size, 0, new_size - old_size);
347
339
  }
348
340
  } else if (AllocateSeparately(aligned_old_size)) {
349
341
  LinkedAllocator *alloc = GetAllocator();
350
342
  ptr = ResizeRaw(alloc, ptr, old_size, new_size, flags);
351
343
  } else {
352
- void *new_ptr = Allocate(new_size, flags & ~(int)Allocator::Flag::Zero);
344
+ void *new_ptr = Allocate(new_size, flags & ~(int)AllocFlag::Zero);
353
345
  if (new_size > old_size) {
354
346
  memcpy_safe(new_ptr, ptr, old_size);
355
347
 
356
- if (flags & (int)Allocator::Flag::Zero) {
348
+ if (flags & (int)AllocFlag::Zero) {
357
349
  memset_safe((uint8_t *)ptr + old_size, 0, new_size - old_size);
358
350
  }
359
351
  } else {
@@ -367,7 +359,7 @@ void *BlockAllocatorBase::Resize(void *ptr, Size old_size, Size new_size, unsign
367
359
  return ptr;
368
360
  }
369
361
 
370
- void BlockAllocatorBase::Release(void *ptr, Size size)
362
+ void BlockAllocatorBase::Release(const void *ptr, Size size)
371
363
  {
372
364
  RG_ASSERT(size >= 0);
373
365
 
@@ -428,6 +420,7 @@ IndirectBlockAllocator& IndirectBlockAllocator::operator=(IndirectBlockAllocator
428
420
 
429
421
  void IndirectBlockAllocator::ReleaseAll()
430
422
  {
423
+ ForgetCurrentBlock();
431
424
  allocator->ReleaseAll();
432
425
  }
433
426
 
@@ -695,7 +688,7 @@ TimeSpec DecomposeTime(int64_t time, TimeMode mode)
695
688
  switch (mode) {
696
689
  case TimeMode::Local: {
697
690
  localtime_r(&time64, &ti);
698
- offset = ti.tm_gmtoff + ti.tm_isdst * 3600;
691
+ offset = ti.tm_gmtoff;
699
692
  } break;
700
693
 
701
694
  case TimeMode::UTC: {
@@ -833,7 +826,7 @@ static Span<char> FormatUnsignedToDecimal(uint64_t value, char out_buf[32])
833
826
  return MakeSpan(out_buf + offset, 32 - offset);
834
827
  }
835
828
 
836
- static Span<char> FormatUnsignedToHex(uint64_t value, char out_buf[32])
829
+ static Span<char> FormatUnsignedToBigHex(uint64_t value, char out_buf[32])
837
830
  {
838
831
  static const char literals[] = "0123456789ABCDEF";
839
832
 
@@ -847,6 +840,20 @@ static Span<char> FormatUnsignedToHex(uint64_t value, char out_buf[32])
847
840
  return MakeSpan(out_buf + offset, 32 - offset);
848
841
  }
849
842
 
843
+ static Span<char> FormatUnsignedToSmallHex(uint64_t value, char out_buf[32])
844
+ {
845
+ static const char literals[] = "0123456789abcdef";
846
+
847
+ Size offset = 32;
848
+ do {
849
+ uint64_t digit = value & 0xF;
850
+ value >>= 4;
851
+ out_buf[--offset] = literals[digit];
852
+ } while (value);
853
+
854
+ return MakeSpan(out_buf + offset, 32 - offset);
855
+ }
856
+
850
857
  static Span<char> FormatUnsignedToBinary(uint64_t value, char out_buf[64])
851
858
  {
852
859
  Size msb = 64 - (Size)CountLeadingZeros(value);
@@ -1138,8 +1145,11 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1138
1145
  case FmtType::Binary: {
1139
1146
  out = FormatUnsignedToBinary(arg.u.u, num_buf);
1140
1147
  } break;
1141
- case FmtType::Hexadecimal: {
1142
- out = FormatUnsignedToHex(arg.u.u, num_buf);
1148
+ case FmtType::BigHex: {
1149
+ out = FormatUnsignedToBigHex(arg.u.u, num_buf);
1150
+ } break;
1151
+ case FmtType::SmallHex: {
1152
+ out = FormatUnsignedToSmallHex(arg.u.u, num_buf);
1143
1153
  } break;
1144
1154
 
1145
1155
  case FmtType::MemorySize: {
@@ -1249,42 +1259,69 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1249
1259
  } break;
1250
1260
 
1251
1261
  case FmtType::TimeISO: {
1252
- if (arg.u.time.offset) {
1253
- int offset_h = arg.u.time.offset / 60;
1254
- int offset_m = arg.u.time.offset % 60;
1262
+ const TimeSpec &spec = arg.u.time.spec;
1263
+
1264
+ if (spec.offset && arg.u.time.ms) {
1265
+ int offset_h = spec.offset / 60;
1266
+ int offset_m = spec.offset % 60;
1255
1267
 
1256
1268
  out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6.%7%8%9%10",
1257
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1258
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1259
- FmtArg(arg.u.time.min).Pad0(-2), FmtArg(arg.u.time.sec).Pad0(-2), FmtArg(arg.u.time.msec).Pad0(-3),
1269
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1270
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1271
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2), FmtArg(spec.msec).Pad0(-3),
1260
1272
  offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1261
- } else {
1273
+ } else if (spec.offset) {
1274
+ int offset_h = spec.offset / 60;
1275
+ int offset_m = spec.offset % 60;
1276
+
1277
+ out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6%7%8%9",
1278
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1279
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1280
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2),
1281
+ offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1282
+ } else if (arg.u.time.ms) {
1262
1283
  out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6.%7Z",
1263
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1264
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1265
- FmtArg(arg.u.time.min).Pad0(-2), FmtArg(arg.u.time.sec).Pad0(-2), FmtArg(arg.u.time.msec).Pad0(-3)).len;
1284
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1285
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1286
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2), FmtArg(spec.msec).Pad0(-3)).len;
1287
+ } else {
1288
+ out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6Z",
1289
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1290
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1291
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2)).len;
1266
1292
  }
1267
1293
  out = out_buf;
1268
1294
  } break;
1269
1295
  case FmtType::TimeNice: {
1270
- int offset_h = arg.u.time.offset / 60;
1271
- int offset_m = arg.u.time.offset % 60;
1272
-
1273
- out_buf.len = Fmt(out_buf.data, "%1-%2-%3 %4:%5:%6.%7 %8%9%10",
1274
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1275
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1276
- FmtArg(arg.u.time.min).Pad0(-2), FmtArg(arg.u.time.sec).Pad0(-2), FmtArg(arg.u.time.msec).Pad0(-3),
1277
- offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1296
+ const TimeSpec &spec = arg.u.time.spec;
1297
+
1298
+ int offset_h = spec.offset / 60;
1299
+ int offset_m = spec.offset % 60;
1300
+
1301
+ if (arg.u.time.ms) {
1302
+ out_buf.len = Fmt(out_buf.data, "%1-%2-%3 %4:%5:%6.%7 %8%9%10",
1303
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1304
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1305
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2), FmtArg(spec.msec).Pad0(-3),
1306
+ offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1307
+ } else {
1308
+ out_buf.len = Fmt(out_buf.data, "%1-%2-%3 %4:%5:%6 %7%8%9",
1309
+ FmtArg(spec.year).Pad0(-2), FmtArg(spec.month).Pad0(-2),
1310
+ FmtArg(spec.day).Pad0(-2), FmtArg(spec.hour).Pad0(-2),
1311
+ FmtArg(spec.min).Pad0(-2), FmtArg(spec.sec).Pad0(-2),
1312
+ offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1313
+ }
1278
1314
  out = out_buf;
1279
1315
  } break;
1280
1316
 
1281
1317
  case FmtType::Random: {
1282
- RG_ASSERT(arg.u.random_len <= RG_SIZE(out_buf.data));
1318
+ static const char *const DefaultChars = "abcdefghijklmnopqrstuvwxyz0123456789";
1319
+ Span<const char> chars = arg.u.random.chars ? arg.u.random.chars : DefaultChars;
1283
1320
 
1284
- for (Size j = 0; j < arg.u.random_len; j++) {
1285
- static const char *chars = "abcdefghijklmnopqrstuvwxyz0123456789";
1321
+ RG_ASSERT(arg.u.random.len <= RG_SIZE(out_buf.data));
1286
1322
 
1287
- int rnd = GetRandomIntSafe(0, (int)strlen(chars));
1323
+ for (Size j = 0; j < arg.u.random.len; j++) {
1324
+ int rnd = GetRandomIntSafe(0, (int)chars.len);
1288
1325
  out_buf.Append(chars[rnd]);
1289
1326
  }
1290
1327
 
@@ -1338,7 +1375,8 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1338
1375
  case FmtType::Integer:
1339
1376
  case FmtType::Unsigned:
1340
1377
  case FmtType::Binary:
1341
- case FmtType::Hexadecimal: {
1378
+ case FmtType::BigHex:
1379
+ case FmtType::SmallHex: {
1342
1380
  switch (arg.u.span.type_len) {
1343
1381
  case 8: { arg2.u.u = *(const uint64_t *)ptr; } break;
1344
1382
  case 4: { arg2.u.u = *(const uint32_t *)ptr; } break;
@@ -1361,7 +1399,7 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1361
1399
  case FmtType::DiskSize: { arg2.u.i = *(const int64_t *)ptr; } break;
1362
1400
  case FmtType::Date: { arg2.u.date = *(const LocalDate *)ptr; } break;
1363
1401
  case FmtType::TimeISO:
1364
- case FmtType::TimeNice: { arg2.u.time = *(const TimeSpec *)ptr; } break;
1402
+ case FmtType::TimeNice: { arg2.u.time = *(decltype(FmtArg::u.time) *)ptr; } break;
1365
1403
  case FmtType::Random: { RG_UNREACHABLE(); } break;
1366
1404
  case FmtType::FlagNames: { RG_UNREACHABLE(); } break;
1367
1405
  case FmtType::FlagOptions: { RG_UNREACHABLE(); } break;
@@ -1680,6 +1718,20 @@ void PrintLnFmt(const char *fmt, Span<const FmtArg> args, FILE *fp)
1680
1718
  fputc('\n', fp);
1681
1719
  }
1682
1720
 
1721
+ // PrintLn variants without format strings
1722
+ void PrintLn(StreamWriter *out_st)
1723
+ {
1724
+ out_st->Write('\n');
1725
+ }
1726
+ void PrintLn(FILE *out_fp)
1727
+ {
1728
+ fputc('\n', out_fp);
1729
+ }
1730
+ void PrintLn()
1731
+ {
1732
+ putchar('\n');
1733
+ }
1734
+
1683
1735
  // ------------------------------------------------------------------------
1684
1736
  // Debug and errors
1685
1737
  // ------------------------------------------------------------------------
@@ -2030,7 +2082,7 @@ static FileType FileAttributesToType(uint32_t attr)
2030
2082
  }
2031
2083
  }
2032
2084
 
2033
- bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2085
+ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2034
2086
  {
2035
2087
  // We don't detect symbolic links, but since they are much less of a hazard
2036
2088
  // than on POSIX systems we care a lot less about them.
@@ -2042,40 +2094,54 @@ bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2042
2094
  } else {
2043
2095
  wchar_t filename_w[4096];
2044
2096
  if (ConvertUtf8ToWin32Wide(filename, filename_w) < 0)
2045
- return false;
2097
+ return StatResult::OtherError;
2046
2098
 
2047
2099
  h = CreateFileW(filename_w, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2048
2100
  nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
2049
2101
  }
2050
2102
  if (h == INVALID_HANDLE_VALUE) {
2051
2103
  DWORD err = GetLastError();
2052
- if (!(flags & (int)StatFlag::IgnoreMissing) ||
2053
- (err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND)) {
2054
- LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString(err));
2104
+
2105
+ switch (err) {
2106
+ case ERROR_FILE_NOT_FOUND:
2107
+ case ERROR_PATH_NOT_FOUND: {
2108
+ if (!(flags & (int)StatFlag::IgnoreMissing)) {
2109
+ LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString(err));
2110
+ }
2111
+ return StatResult::MissingPath;
2112
+ } break;
2113
+ case ERROR_ACCESS_DENIED: {
2114
+ LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString(err));
2115
+ return StatResult::AccessDenied;
2116
+ }
2117
+ default: {
2118
+ LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString(err));
2119
+ return StatResult::OtherError;
2120
+ } break;
2055
2121
  }
2056
- return false;
2057
2122
  }
2058
2123
  RG_DEFER { CloseHandle(h); };
2059
2124
 
2060
2125
  BY_HANDLE_FILE_INFORMATION attr;
2061
2126
  if (!GetFileInformationByHandle(h, &attr)) {
2062
2127
  LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString());
2063
- return false;
2128
+ return StatResult::OtherError;
2064
2129
  }
2065
2130
 
2066
2131
  out_info->type = FileAttributesToType(attr.dwFileAttributes);
2067
2132
  out_info->size = ((uint64_t)attr.nFileSizeHigh << 32) | attr.nFileSizeLow;
2068
2133
  out_info->mtime = FileTimeToUnixTime(attr.ftLastWriteTime);
2134
+ out_info->mode = (out_info->type == FileType::Directory) ? 0755 : 0644;
2069
2135
 
2070
- return true;
2136
+ return StatResult::Success;
2071
2137
  }
2072
2138
 
2073
- bool RenameFile(const char *src_filename, const char *dest_filename, bool overwrite, bool)
2139
+ bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
2074
2140
  {
2075
- DWORD flags = overwrite ? MOVEFILE_REPLACE_EXISTING : 0;
2141
+ DWORD move_flags = (flags & (int)RenameFlag::Overwrite) ? MOVEFILE_REPLACE_EXISTING : 0;
2076
2142
 
2077
2143
  if (win32_utf8) {
2078
- if (!MoveFileExA(src_filename, dest_filename, flags))
2144
+ if (!MoveFileExA(src_filename, dest_filename, move_flags))
2079
2145
  goto error;
2080
2146
  } else {
2081
2147
  wchar_t src_filename_w[4096];
@@ -2085,7 +2151,7 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2085
2151
  if (ConvertUtf8ToWin32Wide(dest_filename, dest_filename_w) < 0)
2086
2152
  return false;
2087
2153
 
2088
- if (!MoveFileExW(src_filename_w, dest_filename_w, flags))
2154
+ if (!MoveFileExW(src_filename_w, dest_filename_w, move_flags))
2089
2155
  goto error;
2090
2156
  }
2091
2157
 
@@ -2096,7 +2162,7 @@ error:
2096
2162
  return false;
2097
2163
  }
2098
2164
 
2099
- EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2165
+ EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2100
2166
  FunctionRef<bool(const char *, FileType)> func)
2101
2167
  {
2102
2168
  if (filter) {
@@ -2110,18 +2176,20 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2110
2176
  char find_filter[4096];
2111
2177
  if (snprintf(find_filter, RG_SIZE(find_filter), "%s\\%s", dirname, filter) >= RG_SIZE(find_filter)) {
2112
2178
  LogError("Cannot enumerate directory '%1': Path too long", dirname);
2113
- return EnumStatus::Error;
2179
+ return EnumResult::OtherError;
2114
2180
  }
2115
2181
 
2116
2182
  if (ConvertUtf8ToWin32Wide(find_filter, find_filter_w) < 0)
2117
- return EnumStatus::Error;
2183
+ return EnumResult::OtherError;
2118
2184
  }
2119
2185
 
2120
2186
  WIN32_FIND_DATAW find_data;
2121
2187
  HANDLE handle = FindFirstFileExW(find_filter_w, FindExInfoBasic, &find_data,
2122
2188
  FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
2123
2189
  if (handle == INVALID_HANDLE_VALUE) {
2124
- if (GetLastError() == ERROR_FILE_NOT_FOUND) {
2190
+ DWORD err = GetLastError();
2191
+
2192
+ if (err == ERROR_FILE_NOT_FOUND) {
2125
2193
  // Erase the filter part from the buffer, we are about to exit anyway.
2126
2194
  // And no, I don't want to include wchar.h
2127
2195
  Size len = 0;
@@ -2131,12 +2199,17 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2131
2199
 
2132
2200
  DWORD attrib = GetFileAttributesW(find_filter_w);
2133
2201
  if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY))
2134
- return EnumStatus::Complete;
2202
+ return EnumResult::Success;
2135
2203
  }
2136
2204
 
2137
- LogError("Cannot enumerate directory '%1': %2", dirname,
2138
- GetWin32ErrorString());
2139
- return EnumStatus::Error;
2205
+ LogError("Cannot enumerate directory '%1': %2", dirname, GetWin32ErrorString());
2206
+
2207
+ switch (err) {
2208
+ case ERROR_FILE_NOT_FOUND:
2209
+ case ERROR_PATH_NOT_FOUND: return EnumResult::MissingPath;
2210
+ case ERROR_ACCESS_DENIED: return EnumResult::AccessDenied;
2211
+ default: return EnumResult::OtherError;
2212
+ }
2140
2213
  }
2141
2214
  RG_DEFER { FindClose(handle); };
2142
2215
 
@@ -2148,26 +2221,26 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2148
2221
 
2149
2222
  if (RG_UNLIKELY(count++ >= max_files && max_files >= 0)) {
2150
2223
  LogError("Partial enumation of directory '%1'", dirname);
2151
- return EnumStatus::Partial;
2224
+ return EnumResult::PartialEnum;
2152
2225
  }
2153
2226
 
2154
2227
  char filename[512];
2155
2228
  if (ConvertWin32WideToUtf8(find_data.cFileName, filename) < 0)
2156
- return EnumStatus::Error;
2229
+ return EnumResult::OtherError;
2157
2230
 
2158
2231
  FileType file_type = FileAttributesToType(find_data.dwFileAttributes);
2159
2232
 
2160
2233
  if (!func(filename, file_type))
2161
- return EnumStatus::Stopped;
2234
+ return EnumResult::CallbackFail;
2162
2235
  } while (FindNextFileW(handle, &find_data));
2163
2236
 
2164
2237
  if (GetLastError() != ERROR_NO_MORE_FILES) {
2165
2238
  LogError("Error while enumerating directory '%1': %2", dirname,
2166
2239
  GetWin32ErrorString());
2167
- return EnumStatus::Error;
2240
+ return EnumResult::OtherError;
2168
2241
  }
2169
2242
 
2170
- return EnumStatus::Complete;
2243
+ return EnumResult::Success;
2171
2244
  }
2172
2245
 
2173
2246
  #else
@@ -2206,16 +2279,28 @@ static FileType FileModeToType(mode_t mode)
2206
2279
  }
2207
2280
  }
2208
2281
 
2209
- bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2282
+ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2210
2283
  {
2211
2284
  int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
2212
2285
 
2213
2286
  struct stat sb;
2214
2287
  if (fstatat(AT_FDCWD, filename, &sb, stat_flags) < 0) {
2215
- if (!(flags & (int)StatFlag::IgnoreMissing) || errno != ENOENT) {
2216
- LogError("Cannot stat '%1': %2", filename, strerror(errno));
2288
+ switch (errno) {
2289
+ case ENOENT: {
2290
+ if (!(flags & (int)StatFlag::IgnoreMissing)) {
2291
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2292
+ }
2293
+ return StatResult::MissingPath;
2294
+ } break;
2295
+ case EACCES: {
2296
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2297
+ return StatResult::AccessDenied;
2298
+ } break;
2299
+ default: {
2300
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2301
+ return StatResult::OtherError;
2302
+ } break;
2217
2303
  }
2218
- return false;
2219
2304
  }
2220
2305
 
2221
2306
  out_info->type = FileModeToType(sb.st_mode);
@@ -2229,8 +2314,9 @@ bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2229
2314
  #else
2230
2315
  out_info->mtime = (int64_t)sb.st_mtime * 1000;
2231
2316
  #endif
2317
+ out_info->mode = (unsigned int)sb.st_mode;
2232
2318
 
2233
- return true;
2319
+ return StatResult::Success;
2234
2320
  }
2235
2321
 
2236
2322
  static bool SyncFileDirectory(const char *filename)
@@ -2260,10 +2346,10 @@ static bool SyncFileDirectory(const char *filename)
2260
2346
  return true;
2261
2347
  }
2262
2348
 
2263
- bool RenameFile(const char *src_filename, const char *dest_filename, bool overwrite, bool sync)
2349
+ bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
2264
2350
  {
2265
2351
  int fd = -1;
2266
- if (!overwrite) {
2352
+ if (!(flags & (int)RenameFlag::Overwrite)) {
2267
2353
  fd = open(dest_filename, O_CREAT | O_EXCL, 0644);
2268
2354
  if (fd < 0) {
2269
2355
  if (errno == EEXIST) {
@@ -2284,7 +2370,7 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2284
2370
 
2285
2371
  // Not much we can do if fsync fails (I think), so ignore errors.
2286
2372
  // Hope for the best: that's the spirit behind the POSIX filesystem API (...).
2287
- if (sync) {
2373
+ if (flags & (int)RenameFlag::Sync) {
2288
2374
  SyncFileDirectory(src_filename);
2289
2375
  SyncFileDirectory(dest_filename);
2290
2376
  }
@@ -2292,13 +2378,18 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2292
2378
  return true;
2293
2379
  }
2294
2380
 
2295
- EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2381
+ EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2296
2382
  FunctionRef<bool(const char *, FileType)> func)
2297
2383
  {
2298
2384
  DIR *dirp = RG_POSIX_RESTART_EINTR(opendir(dirname), == nullptr);
2299
2385
  if (!dirp) {
2300
2386
  LogError("Cannot enumerate directory '%1': %2", dirname, strerror(errno));
2301
- return EnumStatus::Error;
2387
+
2388
+ switch (errno) {
2389
+ case ENOENT: return EnumResult::MissingPath;
2390
+ case EACCES: return EnumResult::AccessDenied;
2391
+ default: return EnumResult::OtherError;
2392
+ }
2302
2393
  }
2303
2394
  RG_DEFER { closedir(dirp); };
2304
2395
 
@@ -2315,7 +2406,7 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2315
2406
  if (!filter || !fnmatch(filter, dent->d_name, FNM_PERIOD)) {
2316
2407
  if (RG_UNLIKELY(count++ >= max_files && max_files >= 0)) {
2317
2408
  LogError("Partial enumation of directory '%1'", dirname);
2318
- return EnumStatus::Partial;
2409
+ return EnumResult::PartialEnum;
2319
2410
  }
2320
2411
 
2321
2412
  FileType file_type;
@@ -2348,7 +2439,7 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2348
2439
  }
2349
2440
 
2350
2441
  if (!func(dent->d_name, file_type))
2351
- return EnumStatus::Stopped;
2442
+ return EnumResult::CallbackFail;
2352
2443
  }
2353
2444
 
2354
2445
  errno = 0;
@@ -2356,10 +2447,10 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2356
2447
 
2357
2448
  if (errno) {
2358
2449
  LogError("Error while enumerating directory '%1': %2", dirname, strerror(errno));
2359
- return EnumStatus::Error;
2450
+ return EnumResult::OtherError;
2360
2451
  }
2361
2452
 
2362
- return EnumStatus::Complete;
2453
+ return EnumResult::Success;
2363
2454
  }
2364
2455
 
2365
2456
  #endif
@@ -2369,8 +2460,8 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2369
2460
  {
2370
2461
  RG_DEFER_NC(out_guard, len = out_files->len) { out_files->RemoveFrom(len); };
2371
2462
 
2372
- EnumStatus status = EnumerateDirectory(dirname, nullptr, max_files,
2373
- [&](const char *basename, FileType file_type) {
2463
+ EnumResult ret = EnumerateDirectory(dirname, nullptr, max_files,
2464
+ [&](const char *basename, FileType file_type) {
2374
2465
  switch (file_type) {
2375
2466
  case FileType::Directory: {
2376
2467
  if (max_depth) {
@@ -2395,7 +2486,7 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2395
2486
 
2396
2487
  return true;
2397
2488
  });
2398
- if (status == EnumStatus::Error)
2489
+ if (ret != EnumResult::Success && ret != EnumResult::PartialEnum)
2399
2490
  return false;
2400
2491
 
2401
2492
  out_guard.Disable();
@@ -2404,14 +2495,19 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2404
2495
 
2405
2496
  bool IsDirectoryEmpty(const char *dirname)
2406
2497
  {
2407
- EnumStatus status = EnumerateDirectory(dirname, nullptr, -1, [](const char *, FileType) { return false; });
2408
- return status == EnumStatus::Complete;
2498
+ EnumResult ret = EnumerateDirectory(dirname, nullptr, -1, [](const char *, FileType) { return false; });
2499
+
2500
+ bool empty = (ret == EnumResult::Success);
2501
+ return empty;
2409
2502
  }
2410
2503
 
2411
2504
  bool TestFile(const char *filename)
2412
2505
  {
2413
2506
  FileInfo file_info;
2414
- return StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info);
2507
+ StatResult ret = StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info);
2508
+
2509
+ bool exists = (ret == StatResult::Success);
2510
+ return exists;
2415
2511
  }
2416
2512
 
2417
2513
  bool TestFile(const char *filename, FileType type)
@@ -2419,7 +2515,7 @@ bool TestFile(const char *filename, FileType type)
2419
2515
  RG_ASSERT(type != FileType::Link);
2420
2516
 
2421
2517
  FileInfo file_info;
2422
- if (!StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info))
2518
+ if (StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info) != StatResult::Success)
2423
2519
  return false;
2424
2520
 
2425
2521
  // Don't follow, but don't warn if we just wanted a file
@@ -2966,47 +3062,49 @@ static bool CheckForDumbTerm()
2966
3062
 
2967
3063
  #ifdef _WIN32
2968
3064
 
2969
- int OpenDescriptor(const char *filename, unsigned int flags)
3065
+ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int silent, int *out_fd)
2970
3066
  {
3067
+ RG_ASSERT(!(silent & ((int)OpenResult::Success | (int)OpenResult::OtherError)));
3068
+
2971
3069
  DWORD access = 0;
2972
3070
  DWORD share = 0;
2973
3071
  DWORD creation = 0;
2974
3072
  int oflags = -1;
2975
- switch (flags & ((int)OpenFileFlag::Read |
2976
- (int)OpenFileFlag::Write |
2977
- (int)OpenFileFlag::Append)) {
2978
- case (int)OpenFileFlag::Read: {
3073
+ switch (flags & ((int)OpenFlag::Read |
3074
+ (int)OpenFlag::Write |
3075
+ (int)OpenFlag::Append)) {
3076
+ case (int)OpenFlag::Read: {
2979
3077
  access = GENERIC_READ;
2980
3078
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2981
3079
  creation = OPEN_EXISTING;
2982
3080
 
2983
3081
  oflags = _O_RDONLY | _O_BINARY | _O_NOINHERIT;
2984
3082
  } break;
2985
- case (int)OpenFileFlag::Write: {
3083
+ case (int)OpenFlag::Write: {
2986
3084
  access = GENERIC_WRITE;
2987
3085
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2988
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3086
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
2989
3087
 
2990
3088
  oflags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY | _O_NOINHERIT;
2991
3089
  } break;
2992
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: {
3090
+ case (int)OpenFlag::Read | (int)OpenFlag::Write: {
2993
3091
  access = GENERIC_READ | GENERIC_WRITE;
2994
3092
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2995
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3093
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
2996
3094
 
2997
3095
  oflags = _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY | _O_NOINHERIT;
2998
3096
  } break;
2999
- case (int)OpenFileFlag::Append: {
3097
+ case (int)OpenFlag::Append: {
3000
3098
  access = GENERIC_WRITE;
3001
3099
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
3002
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3100
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3003
3101
 
3004
3102
  oflags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY | _O_NOINHERIT;
3005
3103
  } break;
3006
3104
  }
3007
3105
  RG_ASSERT(oflags >= 0);
3008
3106
 
3009
- if (flags & (int)OpenFileFlag::Exclusive) {
3107
+ if (flags & (int)OpenFlag::Exclusive) {
3010
3108
  oflags |= (int)_O_EXCL;
3011
3109
  }
3012
3110
  share |= FILE_SHARE_DELETE;
@@ -3017,20 +3115,26 @@ int OpenDescriptor(const char *filename, unsigned int flags)
3017
3115
  } else {
3018
3116
  wchar_t filename_w[4096];
3019
3117
  if (ConvertUtf8ToWin32Wide(filename, filename_w) < 0)
3020
- return -1;
3118
+ return OpenResult::OtherError;
3021
3119
 
3022
3120
  h = CreateFileW(filename_w, access, share, nullptr, creation, FILE_ATTRIBUTE_NORMAL, nullptr);
3023
3121
  }
3024
3122
  if (h == INVALID_HANDLE_VALUE) {
3025
3123
  DWORD err = GetLastError();
3026
3124
 
3027
- if (err == ERROR_FILE_EXISTS) {
3028
- LogError("File '%1' already exists", filename);
3029
- } else {
3030
- LogError("Cannot open '%1': %2", filename, GetWin32ErrorString(err));
3125
+ OpenResult ret;
3126
+ switch (err) {
3127
+ case ERROR_FILE_NOT_FOUND:
3128
+ case ERROR_PATH_NOT_FOUND: { ret = OpenResult::MissingPath; } break;
3129
+ case ERROR_FILE_EXISTS: { ret = OpenResult::FileExists; } break;
3130
+ case ERROR_ACCESS_DENIED: { ret = OpenResult::AccessDenied; } break;
3131
+ default: { ret = OpenResult::OtherError; } break;
3031
3132
  }
3032
3133
 
3033
- return -1;
3134
+ if (!(silent & (int)ret)) {
3135
+ LogError("Cannot open '%1': %2", filename, GetWin32ErrorString(err));
3136
+ }
3137
+ return ret;
3034
3138
  }
3035
3139
 
3036
3140
  int fd = _open_osfhandle((intptr_t)h, oflags);
@@ -3038,22 +3142,23 @@ int OpenDescriptor(const char *filename, unsigned int flags)
3038
3142
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3039
3143
  CloseHandle(h);
3040
3144
 
3041
- return -1;
3145
+ return OpenResult::OtherError;
3042
3146
  }
3043
3147
 
3044
- return fd;
3148
+ *out_fd = fd;
3149
+ return OpenResult::Success;
3045
3150
  }
3046
3151
 
3047
- FILE *OpenFile(const char *filename, unsigned int flags)
3152
+ OpenResult OpenFile(const char *filename, unsigned int flags, unsigned int silent, FILE **out_fp)
3048
3153
  {
3049
3154
  char mode[16] = {};
3050
- switch (flags & ((int)OpenFileFlag::Read |
3051
- (int)OpenFileFlag::Write |
3052
- (int)OpenFileFlag::Append)) {
3053
- case (int)OpenFileFlag::Read: { CopyString("rbc", mode); } break;
3054
- case (int)OpenFileFlag::Write: { CopyString("wbc", mode); } break;
3055
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { CopyString("w+bc", mode); } break;
3056
- case (int)OpenFileFlag::Append: { CopyString("abc", mode); } break;
3155
+ switch (flags & ((int)OpenFlag::Read |
3156
+ (int)OpenFlag::Write |
3157
+ (int)OpenFlag::Append)) {
3158
+ case (int)OpenFlag::Read: { CopyString("rbc", mode); } break;
3159
+ case (int)OpenFlag::Write: { CopyString("wbc", mode); } break;
3160
+ case (int)OpenFlag::Read | (int)OpenFlag::Write: { CopyString("w+bc", mode); } break;
3161
+ case (int)OpenFlag::Append: { CopyString("abc", mode); } break;
3057
3162
  }
3058
3163
  RG_ASSERT(mode[0]);
3059
3164
 
@@ -3062,17 +3167,35 @@ FILE *OpenFile(const char *filename, unsigned int flags)
3062
3167
  strcat(mode, "N");
3063
3168
  #endif
3064
3169
 
3065
- int fd = OpenDescriptor(filename, flags);
3066
- if (fd < 0)
3067
- return nullptr;
3170
+ int fd = -1;
3171
+ OpenResult ret = OpenDescriptor(filename, flags, silent, &fd);
3172
+ if (ret != OpenResult::Success)
3173
+ return ret;
3068
3174
 
3069
3175
  FILE *fp = _fdopen(fd, mode);
3070
3176
  if (!fp) {
3071
3177
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3072
3178
  _close(fd);
3179
+
3180
+ return OpenResult::OtherError;
3181
+ }
3182
+
3183
+ *out_fp = fp;
3184
+ return OpenResult::Success;
3185
+ }
3186
+
3187
+ bool FlushFile(int fd, const char *filename)
3188
+ {
3189
+ RG_ASSERT(filename);
3190
+
3191
+ HANDLE h = (HANDLE)_get_osfhandle(fd);
3192
+
3193
+ if (!FlushFileBuffers(h)) {
3194
+ LogError("Failed to sync '%1': %2", filename, GetWin32ErrorString());
3195
+ return false;
3073
3196
  }
3074
3197
 
3075
- return fp;
3198
+ return true;
3076
3199
  }
3077
3200
 
3078
3201
  bool FlushFile(FILE *fp, const char *filename)
@@ -3272,60 +3395,89 @@ error:
3272
3395
 
3273
3396
  #else
3274
3397
 
3275
- int OpenDescriptor(const char *filename, unsigned int flags)
3398
+ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int silent, int *out_fd)
3276
3399
  {
3400
+ RG_ASSERT(!(silent & ((int)OpenResult::Success | (int)OpenResult::OtherError)));
3401
+
3277
3402
  int oflags = -1;
3278
- switch (flags & ((int)OpenFileFlag::Read |
3279
- (int)OpenFileFlag::Write |
3280
- (int)OpenFileFlag::Append)) {
3281
- case (int)OpenFileFlag::Read: { oflags = O_RDONLY | O_CLOEXEC; } break;
3282
- case (int)OpenFileFlag::Write: { oflags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3283
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { oflags = O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3284
- case (int)OpenFileFlag::Append: { oflags = O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC; } break;
3403
+ switch (flags & ((int)OpenFlag::Read |
3404
+ (int)OpenFlag::Write |
3405
+ (int)OpenFlag::Append)) {
3406
+ case (int)OpenFlag::Read: { oflags = O_RDONLY | O_CLOEXEC; } break;
3407
+ case (int)OpenFlag::Write: { oflags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3408
+ case (int)OpenFlag::Read | (int)OpenFlag::Write: { oflags = O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3409
+ case (int)OpenFlag::Append: { oflags = O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC; } break;
3285
3410
  }
3286
3411
  RG_ASSERT(oflags >= 0);
3287
3412
 
3288
- if (flags & (int)OpenFileFlag::Exclusive) {
3413
+ if (flags & (int)OpenFlag::Exclusive) {
3289
3414
  oflags |= O_EXCL;
3290
3415
  }
3291
3416
 
3292
3417
  int fd = RG_POSIX_RESTART_EINTR(open(filename, oflags, 0644), < 0);
3293
3418
  if (fd < 0) {
3294
- if (errno == EEXIST) {
3295
- LogError("File '%1' already exists", filename);
3296
- } else {
3419
+ OpenResult ret;
3420
+ switch (errno) {
3421
+ case ENOENT: { ret = OpenResult::MissingPath; } break;
3422
+ case EEXIST: { ret = OpenResult::FileExists; } break;
3423
+ case EACCES: { ret = OpenResult::AccessDenied; } break;
3424
+ default: { ret = OpenResult::OtherError; } break;
3425
+ }
3426
+
3427
+ if (!(silent & (int)ret)) {
3297
3428
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3298
3429
  }
3299
- return -1;
3430
+ return ret;
3300
3431
  }
3301
3432
 
3302
- return fd;
3433
+ *out_fd = fd;
3434
+ return OpenResult::Success;
3303
3435
  }
3304
3436
 
3305
- FILE *OpenFile(const char *filename, unsigned int flags)
3437
+ OpenResult OpenFile(const char *filename, unsigned int flags, unsigned int silent, FILE **out_fp)
3306
3438
  {
3307
3439
  const char *mode = nullptr;
3308
- switch (flags & ((int)OpenFileFlag::Read |
3309
- (int)OpenFileFlag::Write |
3310
- (int)OpenFileFlag::Append)) {
3311
- case (int)OpenFileFlag::Read: { mode = "rbe"; } break;
3312
- case (int)OpenFileFlag::Write: { mode = "wbe"; } break;
3313
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { mode = "w+be"; } break;
3314
- case (int)OpenFileFlag::Append: { mode = "abe"; } break;
3440
+ switch (flags & ((int)OpenFlag::Read |
3441
+ (int)OpenFlag::Write |
3442
+ (int)OpenFlag::Append)) {
3443
+ case (int)OpenFlag::Read: { mode = "rbe"; } break;
3444
+ case (int)OpenFlag::Write: { mode = "wbe"; } break;
3445
+ case (int)OpenFlag::Read | (int)OpenFlag::Write: { mode = "w+be"; } break;
3446
+ case (int)OpenFlag::Append: { mode = "abe"; } break;
3315
3447
  }
3316
3448
  RG_ASSERT(mode);
3317
3449
 
3318
- int fd = OpenDescriptor(filename, flags);
3319
- if (fd < 0)
3320
- return nullptr;
3450
+ int fd = -1;
3451
+ OpenResult ret = OpenDescriptor(filename, flags, silent, &fd);
3452
+ if (ret != OpenResult::Success)
3453
+ return ret;
3321
3454
 
3322
3455
  FILE *fp = fdopen(fd, mode);
3323
3456
  if (!fp) {
3324
3457
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3325
3458
  close(fd);
3459
+
3460
+ return OpenResult::OtherError;
3326
3461
  }
3327
3462
 
3328
- return fp;
3463
+ *out_fp = fp;
3464
+ return OpenResult::Success;
3465
+ }
3466
+
3467
+ bool FlushFile(int fd, const char *filename)
3468
+ {
3469
+ RG_ASSERT(filename);
3470
+
3471
+ #ifdef __APPLE__
3472
+ if (fsync(fd) < 0 && errno != EINVAL && errno != ENOTSUP) {
3473
+ #else
3474
+ if (fsync(fd) < 0 && errno != EINVAL) {
3475
+ #endif
3476
+ LogError("Failed to sync '%1': %2", filename, strerror(errno));
3477
+ return false;
3478
+ }
3479
+
3480
+ return true;
3329
3481
  }
3330
3482
 
3331
3483
  bool FlushFile(FILE *fp, const char *filename)
@@ -4011,7 +4163,7 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
4011
4163
  }
4012
4164
 
4013
4165
  // Try to read
4014
- if (out_revents & (POLLHUP | POLLERR)) {
4166
+ if (out_revents & POLLERR) {
4015
4167
  break;
4016
4168
  } else if (out_revents & POLLIN) {
4017
4169
  RG_ASSERT(out_func.IsValid());
@@ -4028,6 +4180,9 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
4028
4180
  LogError("Failed to read process output: %1", strerror(errno));
4029
4181
  break;
4030
4182
  }
4183
+ } else if (out_revents & POLLHUP) {
4184
+ // Only deal with this once POLLIN goes down to avoid truncated output
4185
+ break;
4031
4186
  }
4032
4187
 
4033
4188
  if (term_revents) {
@@ -4248,10 +4403,12 @@ int GetCoreCount()
4248
4403
  if (env) {
4249
4404
  char *end_ptr;
4250
4405
  long value = strtol(env, &end_ptr, 10);
4406
+
4251
4407
  if (end_ptr > env && !end_ptr[0] && value > 0) {
4252
4408
  cores = (int)value;
4253
4409
  } else {
4254
4410
  LogError("OVERRIDE_CORES must be positive number (ignored)");
4411
+ cores = (int)std::thread::hardware_concurrency();
4255
4412
  }
4256
4413
  } else {
4257
4414
  cores = (int)std::thread::hardware_concurrency();
@@ -4542,8 +4699,8 @@ const char *FindConfigFile(const char *name, Allocator *alloc, LocalArray<const
4542
4699
  return filename;
4543
4700
  }
4544
4701
 
4545
- static const char *CreateTemporaryPath(Span<const char> directory, const char *prefix, const char *extension,
4546
- Allocator *alloc, FunctionRef<bool(const char *path)> create)
4702
+ static const char *CreateUniquePath(Span<const char> directory, const char *prefix, const char *extension,
4703
+ Allocator *alloc, FunctionRef<bool(const char *path)> create)
4547
4704
  {
4548
4705
  RG_ASSERT(alloc);
4549
4706
 
@@ -4576,12 +4733,12 @@ static const char *CreateTemporaryPath(Span<const char> directory, const char *p
4576
4733
  return nullptr;
4577
4734
  }
4578
4735
 
4579
- const char *CreateTemporaryFile(Span<const char> directory, const char *prefix, const char *extension,
4580
- Allocator *alloc, FILE **out_fp)
4736
+ const char *CreateUniqueFile(Span<const char> directory, const char *prefix, const char *extension,
4737
+ Allocator *alloc, FILE **out_fp)
4581
4738
  {
4582
- return CreateTemporaryPath(directory, prefix, extension, alloc, [&](const char *path) {
4583
- int flags = (int)OpenFileFlag::Read | (int)OpenFileFlag::Write |
4584
- (int)OpenFileFlag::Exclusive;
4739
+ return CreateUniquePath(directory, prefix, extension, alloc, [&](const char *path) {
4740
+ int flags = (int)OpenFlag::Read | (int)OpenFlag::Write |
4741
+ (int)OpenFlag::Exclusive;
4585
4742
 
4586
4743
  FILE *fp = OpenFile(path, flags);
4587
4744
 
@@ -4599,9 +4756,9 @@ const char *CreateTemporaryFile(Span<const char> directory, const char *prefix,
4599
4756
  });
4600
4757
  }
4601
4758
 
4602
- const char *CreateTemporaryDirectory(Span<const char> directory, const char *prefix, Allocator *alloc)
4759
+ const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix, Allocator *alloc)
4603
4760
  {
4604
- return CreateTemporaryPath(directory, prefix, "", alloc, [&](const char *path) {
4761
+ return CreateUniquePath(directory, prefix, "", alloc, [&](const char *path) {
4605
4762
  return MakeDirectory(path);
4606
4763
  });
4607
4764
  }
@@ -5083,6 +5240,9 @@ class AsyncPool {
5083
5240
  public:
5084
5241
  AsyncPool(int threads, bool leak);
5085
5242
 
5243
+ int GetWorkerCount() const { return (int)queues.len; }
5244
+ int CountPendingTasks() const { return pending_tasks; }
5245
+
5086
5246
  void RegisterAsync();
5087
5247
  void UnregisterAsync();
5088
5248
 
@@ -5127,9 +5287,18 @@ Async::Async(int threads, bool stop_after_error)
5127
5287
  pool->RegisterAsync();
5128
5288
  }
5129
5289
 
5290
+ Async::Async(Async *parent, bool stop_after_error)
5291
+ : stop_after_error(stop_after_error)
5292
+ {
5293
+ RG_ASSERT(parent);
5294
+
5295
+ pool = parent->pool;
5296
+ pool->RegisterAsync();
5297
+ }
5298
+
5130
5299
  Async::~Async()
5131
5300
  {
5132
- RG_ASSERT(!remaining_tasks);
5301
+ Sync();
5133
5302
  pool->UnregisterAsync();
5134
5303
  }
5135
5304
 
@@ -5144,6 +5313,11 @@ bool Async::Sync()
5144
5313
  return success;
5145
5314
  }
5146
5315
 
5316
+ int Async::CountPendingTasks()
5317
+ {
5318
+ return pool->CountPendingTasks();
5319
+ }
5320
+
5147
5321
  bool Async::IsTaskRunning()
5148
5322
  {
5149
5323
  return async_running_task;
@@ -5154,6 +5328,11 @@ int Async::GetWorkerIdx()
5154
5328
  return async_running_worker_idx;
5155
5329
  }
5156
5330
 
5331
+ int Async::GetWorkerCount()
5332
+ {
5333
+ return async_running_pool->GetWorkerCount();
5334
+ }
5335
+
5157
5336
  AsyncPool::AsyncPool(int threads, bool leak)
5158
5337
  {
5159
5338
  if (threads > RG_ASYNC_MAX_THREADS) {
@@ -5640,6 +5819,7 @@ bool StreamReader::Open(Span<const uint8_t> buf, const char *filename,
5640
5819
 
5641
5820
  RG_DEFER_N(err_guard) { error = true; };
5642
5821
  error = false;
5822
+ raw_read = 0;
5643
5823
 
5644
5824
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<memory>";
5645
5825
 
@@ -5660,6 +5840,7 @@ bool StreamReader::Open(FILE *fp, const char *filename, CompressionType compress
5660
5840
 
5661
5841
  RG_DEFER_N(err_guard) { error = true; };
5662
5842
  error = false;
5843
+ raw_read = 0;
5663
5844
 
5664
5845
  RG_ASSERT(fp);
5665
5846
  RG_ASSERT(filename);
@@ -5676,27 +5857,30 @@ bool StreamReader::Open(FILE *fp, const char *filename, CompressionType compress
5676
5857
  return true;
5677
5858
  }
5678
5859
 
5679
- bool StreamReader::Open(const char *filename, CompressionType compression_type)
5860
+ OpenResult StreamReader::Open(const char *filename, CompressionType compression_type)
5680
5861
  {
5681
5862
  Close(true);
5682
5863
 
5683
5864
  RG_DEFER_N(err_guard) { error = true; };
5684
5865
  error = false;
5866
+ raw_read = 0;
5685
5867
 
5686
5868
  RG_ASSERT(filename);
5687
5869
  this->filename = DuplicateString(filename, &str_alloc).ptr;
5688
5870
 
5689
5871
  source.type = SourceType::File;
5690
- source.u.file.fp = OpenFile(filename, (int)OpenFileFlag::Read);
5691
- if (!source.u.file.fp)
5692
- return false;
5872
+ {
5873
+ OpenResult ret = OpenFile(filename, (int)OpenFlag::Read, &source.u.file.fp);
5874
+ if (ret != OpenResult::Success)
5875
+ return ret;
5876
+ }
5693
5877
  source.u.file.owned = true;
5694
5878
 
5695
5879
  if (!InitDecompressor(compression_type))
5696
- return false;
5880
+ return OpenResult::OtherError;
5697
5881
 
5698
5882
  err_guard.Disable();
5699
- return true;
5883
+ return OpenResult::Success;
5700
5884
  }
5701
5885
 
5702
5886
  bool StreamReader::Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
@@ -5706,6 +5890,7 @@ bool StreamReader::Open(const std::function<Size(Span<uint8_t>)> &func, const ch
5706
5890
 
5707
5891
  RG_DEFER_N(err_guard) { error = true; };
5708
5892
  error = false;
5893
+ raw_read = 0;
5709
5894
 
5710
5895
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<closure>";
5711
5896
 
@@ -5776,7 +5961,6 @@ bool StreamReader::Close(bool implicit)
5776
5961
  source.eof = false;
5777
5962
  eof = false;
5778
5963
  raw_len = -1;
5779
- raw_read = 0;
5780
5964
  str_alloc.ReleaseAll();
5781
5965
 
5782
5966
  return ret;
@@ -5836,6 +6020,23 @@ bool StreamReader::Rewind()
5836
6020
  return true;
5837
6021
  }
5838
6022
 
6023
+ FILE *StreamReader::GetFile() const
6024
+ {
6025
+ RG_ASSERT(source.type == SourceType::File);
6026
+ return source.u.file.fp;
6027
+ }
6028
+
6029
+ int StreamReader::GetDescriptor() const
6030
+ {
6031
+ RG_ASSERT(source.type == SourceType::File);
6032
+
6033
+ #ifdef _WIN32
6034
+ return _fileno(source.u.file.fp);
6035
+ #else
6036
+ return fileno(source.u.file.fp);
6037
+ #endif
6038
+ }
6039
+
5839
6040
  Size StreamReader::Read(Span<uint8_t> out_buf)
5840
6041
  {
5841
6042
  if (RG_UNLIKELY(error))
@@ -5978,7 +6179,7 @@ bool StreamReader::InitDecompressor(CompressionType type)
5978
6179
  case CompressionType::Gzip:
5979
6180
  case CompressionType::Zlib: {
5980
6181
  #ifdef MZ_VERSION
5981
- compression.u.miniz = AllocateOne<MinizInflateContext>(nullptr, (int)Allocator::Flag::Zero);
6182
+ compression.u.miniz = AllocateOne<MinizInflateContext>(nullptr, (int)AllocFlag::Zero);
5982
6183
  tinfl_init(&compression.u.miniz->inflator);
5983
6184
  compression.u.miniz->crc32 = MZ_CRC32_INIT;
5984
6185
  #else
@@ -5990,7 +6191,7 @@ bool StreamReader::InitDecompressor(CompressionType type)
5990
6191
 
5991
6192
  case CompressionType::Brotli: {
5992
6193
  #ifdef BROTLI_DEFAULT_MODE
5993
- compression.u.brotli = AllocateOne<BrotliDecompressContext>(nullptr, (int)Allocator::Flag::Zero);
6194
+ compression.u.brotli = AllocateOne<BrotliDecompressContext>(nullptr, (int)AllocFlag::Zero);
5994
6195
  compression.u.brotli->state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
5995
6196
  #else
5996
6197
  LogError("Brotli decompression not available for '%1'", filename);
@@ -6339,6 +6540,7 @@ bool StreamWriter::Open(HeapArray<uint8_t> *mem, const char *filename,
6339
6540
 
6340
6541
  RG_DEFER_N(err_guard) { error = true; };
6341
6542
  error = false;
6543
+ raw_written = 0;
6342
6544
 
6343
6545
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<memory>";
6344
6546
 
@@ -6361,6 +6563,7 @@ bool StreamWriter::Open(FILE *fp, const char *filename,
6361
6563
 
6362
6564
  RG_DEFER_N(err_guard) { error = true; };
6363
6565
  error = false;
6566
+ raw_written = 0;
6364
6567
 
6365
6568
  RG_ASSERT(fp);
6366
6569
  RG_ASSERT(filename);
@@ -6385,6 +6588,7 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6385
6588
 
6386
6589
  RG_DEFER_N(err_guard) { error = true; };
6387
6590
  error = false;
6591
+ raw_written = 0;
6388
6592
 
6389
6593
  RG_ASSERT(filename);
6390
6594
  this->filename = DuplicateString(filename, &str_alloc).ptr;
@@ -6396,8 +6600,8 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6396
6600
  Span<const char> directory = GetPathDirectory(filename);
6397
6601
 
6398
6602
  if (flags & (int)StreamWriterFlag::Exclusive) {
6399
- FILE *fp = OpenFile(filename, (int)OpenFileFlag::Write |
6400
- (int)OpenFileFlag::Exclusive);
6603
+ FILE *fp = OpenFile(filename, (int)OpenFlag::Write |
6604
+ (int)OpenFlag::Exclusive);
6401
6605
  if (!fp)
6402
6606
  return false;
6403
6607
  fclose(fp);
@@ -6405,13 +6609,13 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6405
6609
  dest.u.file.tmp_exclusive = true;
6406
6610
  }
6407
6611
 
6408
- dest.u.file.tmp_filename = CreateTemporaryFile(directory, "", ".tmp", &str_alloc, &dest.u.file.fp);
6612
+ dest.u.file.tmp_filename = CreateUniqueFile(directory, "", ".tmp", &str_alloc, &dest.u.file.fp);
6409
6613
  if (!dest.u.file.tmp_filename)
6410
6614
  return false;
6411
6615
  dest.u.file.owned = true;
6412
6616
  } else {
6413
- unsigned int open_flags = (int)OpenFileFlag::Write;
6414
- open_flags |= (flags & (int)StreamWriterFlag::Exclusive) ? (int)OpenFileFlag::Exclusive : 0;
6617
+ unsigned int open_flags = (int)OpenFlag::Write;
6618
+ open_flags |= (flags & (int)StreamWriterFlag::Exclusive) ? (int)OpenFlag::Exclusive : 0;
6415
6619
 
6416
6620
  dest.u.file.fp = OpenFile(filename, open_flags);
6417
6621
  if (!dest.u.file.fp)
@@ -6434,6 +6638,7 @@ bool StreamWriter::Open(const std::function<bool(Span<const uint8_t>)> &func, co
6434
6638
 
6435
6639
  RG_DEFER_N(err_guard) { error = true; };
6436
6640
  error = false;
6641
+ raw_written = 0;
6437
6642
 
6438
6643
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<closure>";
6439
6644
 
@@ -6455,13 +6660,37 @@ bool StreamWriter::Flush()
6455
6660
 
6456
6661
  switch (dest.type) {
6457
6662
  case DestinationType::Memory: return true;
6458
- case DestinationType::File: return FlushFile(dest.u.file.fp, filename);
6663
+ case DestinationType::File: {
6664
+ if (!FlushFile(dest.u.file.fp, filename)) {
6665
+ error = true;
6666
+ return false;
6667
+ }
6668
+
6669
+ return true;
6670
+ } break;
6459
6671
  case DestinationType::Function: return true;
6460
6672
  }
6461
6673
 
6462
6674
  RG_UNREACHABLE();
6463
6675
  }
6464
6676
 
6677
+ FILE *StreamWriter::GetFile() const
6678
+ {
6679
+ RG_ASSERT(dest.type == DestinationType::File);
6680
+ return dest.u.file.fp;
6681
+ }
6682
+
6683
+ int StreamWriter::GetDescriptor() const
6684
+ {
6685
+ RG_ASSERT(dest.type == DestinationType::File);
6686
+
6687
+ #ifdef _WIN32
6688
+ return _fileno(dest.u.file.fp);
6689
+ #else
6690
+ return fileno(dest.u.file.fp);
6691
+ #endif
6692
+ }
6693
+
6465
6694
  bool StreamWriter::Write(Span<const uint8_t> buf)
6466
6695
  {
6467
6696
  if (RG_UNLIKELY(error))
@@ -6601,21 +6830,23 @@ bool StreamWriter::Close(bool implicit)
6601
6830
  case DestinationType::Memory: { dest.u.mem = {}; } break;
6602
6831
 
6603
6832
  case DestinationType::File: {
6604
- if (IsValid() && !FlushFile(dest.u.file.fp, filename)) {
6605
- error = true;
6606
- }
6607
-
6608
6833
  if (dest.u.file.tmp_filename) {
6609
- if (IsValid() && implicit) {
6610
- LogDebug("Deleting implicitly closed file '%1'", filename);
6611
- error = true;
6834
+ if (IsValid()) {
6835
+ if (implicit) {
6836
+ LogDebug("Deleting implicitly closed file '%1'", filename);
6837
+ error = true;
6838
+ } else if (!FlushFile(dest.u.file.fp, filename)) {
6839
+ error = true;
6840
+ }
6612
6841
  }
6613
6842
 
6614
6843
  if (IsValid()) {
6615
6844
  fclose(dest.u.file.fp);
6616
6845
  dest.u.file.owned = false;
6617
6846
 
6618
- if (RenameFile(dest.u.file.tmp_filename, filename, true)) {
6847
+ unsigned int flags = (int)RenameFlag::Overwrite | (int)RenameFlag::Sync;
6848
+
6849
+ if (RenameFile(dest.u.file.tmp_filename, filename, flags)) {
6619
6850
  dest.u.file.tmp_filename = nullptr;
6620
6851
  dest.u.file.tmp_exclusive = false;
6621
6852
  } else {
@@ -6666,7 +6897,7 @@ bool StreamWriter::InitCompressor(CompressionType type, CompressionSpeed speed)
6666
6897
  case CompressionType::Gzip:
6667
6898
  case CompressionType::Zlib: {
6668
6899
  #ifdef MZ_VERSION
6669
- compression.u.miniz = AllocateOne<MinizDeflateContext>(nullptr, (int)Allocator::Flag::Zero);
6900
+ compression.u.miniz = AllocateOne<MinizDeflateContext>(nullptr, (int)AllocFlag::Zero);
6670
6901
  compression.u.miniz->crc32 = MZ_CRC32_INIT;
6671
6902
 
6672
6903
  int flags = 0;
@@ -6797,7 +7028,7 @@ bool StreamWriter::WriteRaw(Span<const uint8_t> buf)
6797
7028
  memcpy_safe(dest.u.mem.memory->ptr + dest.u.mem.memory->len, buf.ptr, (size_t)buf.len);
6798
7029
  dest.u.mem.memory->len += buf.len;
6799
7030
 
6800
- return true;
7031
+ raw_written += buf.len;
6801
7032
  } break;
6802
7033
 
6803
7034
  case DestinationType::File: {
@@ -6816,9 +7047,9 @@ bool StreamWriter::WriteRaw(Span<const uint8_t> buf)
6816
7047
 
6817
7048
  buf.ptr += write_len;
6818
7049
  buf.len -= write_len;
6819
- }
6820
7050
 
6821
- return true;
7051
+ raw_written += write_len;
7052
+ }
6822
7053
  } break;
6823
7054
 
6824
7055
  case DestinationType::Function: {
@@ -6826,13 +7057,16 @@ bool StreamWriter::WriteRaw(Span<const uint8_t> buf)
6826
7057
  if (!buf.len)
6827
7058
  return true;
6828
7059
 
6829
- bool ret = dest.u.func(buf);
6830
- error |= !ret;
6831
- return ret;
7060
+ if (!dest.u.func(buf)) {
7061
+ error = true;
7062
+ return false;
7063
+ }
7064
+
7065
+ raw_written += buf.len;
6832
7066
  } break;
6833
7067
  }
6834
7068
 
6835
- RG_UNREACHABLE();
7069
+ return true;
6836
7070
  }
6837
7071
 
6838
7072
  bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer)
@@ -6983,7 +7217,7 @@ bool ReloadAssets()
6983
7217
  // Check library time
6984
7218
  {
6985
7219
  FileInfo file_info;
6986
- if (!StatFile(assets_filename, &file_info))
7220
+ if (StatFile(assets_filename, &file_info) != StatResult::Success)
6987
7221
  return false;
6988
7222
 
6989
7223
  if (assets_last_check == file_info.mtime)