koffi 2.1.0 → 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 (313) hide show
  1. package/ChangeLog.md +13 -1
  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/call.cc +2 -2
  23. package/src/call.hh +1 -1
  24. package/src/ffi.hh +1 -1
  25. package/src/util.hh +6 -0
  26. package/test/raylib.js +37 -5
  27. package/vendor/libcc/libcc.cc +488 -254
  28. package/vendor/libcc/libcc.hh +1463 -1277
  29. package/vendor/raylib/BINDINGS.md +87 -70
  30. package/vendor/raylib/CHANGELOG +263 -50
  31. package/vendor/raylib/CMakeLists.txt +12 -0
  32. package/vendor/raylib/CMakeOptions.txt +8 -1
  33. package/vendor/raylib/CONVENTIONS.md +2 -3
  34. package/vendor/raylib/FAQ.md +137 -0
  35. package/vendor/raylib/HISTORY.md +62 -29
  36. package/vendor/raylib/LICENSE +1 -1
  37. package/vendor/raylib/README.md +22 -17
  38. package/vendor/raylib/ROADMAP.md +8 -7
  39. package/vendor/raylib/cmake/CompileDefinitions.cmake +19 -15
  40. package/vendor/raylib/cmake/GlfwImport.cmake +2 -0
  41. package/vendor/raylib/cmake/LibraryConfigurations.cmake +22 -16
  42. package/vendor/raylib/cmake/raylib-config.cmake +52 -49
  43. package/vendor/raylib/examples/CMakeLists.txt +14 -9
  44. package/vendor/raylib/examples/Makefile +112 -125
  45. package/vendor/raylib/examples/Makefile.Android +1 -1
  46. package/vendor/raylib/examples/Makefile.Web +145 -158
  47. package/vendor/raylib/examples/README.md +141 -141
  48. package/vendor/raylib/examples/audio/audio_module_playing.c +9 -4
  49. package/vendor/raylib/examples/audio/audio_multichannel_sound.c +8 -3
  50. package/vendor/raylib/examples/audio/audio_music_stream.c +16 -11
  51. package/vendor/raylib/examples/audio/audio_raw_stream.c +57 -9
  52. package/vendor/raylib/examples/audio/audio_sound_loading.c +8 -3
  53. package/vendor/raylib/examples/audio/audio_stream_effects.c +179 -0
  54. package/vendor/raylib/examples/audio/audio_stream_effects.png +0 -0
  55. package/vendor/raylib/examples/build.zig +17 -6
  56. package/vendor/raylib/examples/core/core_2d_camera.c +8 -4
  57. package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.c +105 -0
  58. package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.png +0 -0
  59. package/vendor/raylib/examples/core/core_2d_camera_platformer.c +11 -6
  60. package/vendor/raylib/examples/core/core_3d_camera_first_person.c +9 -4
  61. package/vendor/raylib/examples/core/core_3d_camera_free.c +9 -4
  62. package/vendor/raylib/examples/core/core_3d_camera_mode.c +8 -3
  63. package/vendor/raylib/examples/core/core_3d_picking.c +9 -4
  64. package/vendor/raylib/examples/core/core_basic_screen_manager.c +9 -7
  65. package/vendor/raylib/examples/core/core_basic_window.c +8 -3
  66. package/vendor/raylib/examples/core/core_basic_window_web.c +13 -11
  67. package/vendor/raylib/examples/core/core_custom_frame_control.c +9 -4
  68. package/vendor/raylib/examples/core/core_custom_logging.c +12 -8
  69. package/vendor/raylib/examples/core/core_drop_files.c +20 -12
  70. package/vendor/raylib/examples/core/core_input_gamepad.c +20 -15
  71. package/vendor/raylib/examples/core/core_input_gestures.c +19 -15
  72. package/vendor/raylib/examples/core/core_input_keys.c +8 -3
  73. package/vendor/raylib/examples/core/core_input_mouse.c +8 -3
  74. package/vendor/raylib/examples/core/core_input_mouse_wheel.c +8 -3
  75. package/vendor/raylib/examples/core/core_input_multitouch.c +8 -3
  76. package/vendor/raylib/examples/core/core_loading_thread.c +10 -6
  77. package/vendor/raylib/examples/core/core_random_values.c +8 -3
  78. package/vendor/raylib/examples/core/core_scissor_test.c +8 -3
  79. package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +9 -4
  80. package/vendor/raylib/examples/core/core_split_screen.c +8 -3
  81. package/vendor/raylib/examples/core/core_storage_values.c +109 -3
  82. package/vendor/raylib/examples/core/core_vr_simulator.c +15 -7
  83. package/vendor/raylib/examples/core/core_window_flags.c +8 -3
  84. package/vendor/raylib/examples/core/core_window_letterbox.c +13 -18
  85. package/vendor/raylib/examples/core/core_window_should_close.c +77 -0
  86. package/vendor/raylib/examples/core/core_window_should_close.png +0 -0
  87. package/vendor/raylib/examples/core/core_world_screen.c +9 -4
  88. package/vendor/raylib/examples/examples_template.c +8 -3
  89. package/vendor/raylib/examples/models/models_animation.c +11 -7
  90. package/vendor/raylib/examples/models/models_billboard.c +9 -4
  91. package/vendor/raylib/examples/models/models_box_collisions.c +8 -3
  92. package/vendor/raylib/examples/models/models_cubicmap.c +9 -4
  93. package/vendor/raylib/examples/models/models_first_person_maze.c +9 -4
  94. package/vendor/raylib/examples/models/models_geometric_shapes.c +8 -3
  95. package/vendor/raylib/examples/models/models_heightmap.c +9 -4
  96. package/vendor/raylib/examples/models/models_loading.c +21 -17
  97. package/vendor/raylib/examples/models/models_loading_gltf.c +15 -41
  98. package/vendor/raylib/examples/models/models_loading_vox.c +9 -4
  99. package/vendor/raylib/examples/models/models_mesh_generation.c +71 -58
  100. package/vendor/raylib/examples/models/models_mesh_picking.c +25 -7
  101. package/vendor/raylib/examples/models/models_orthographic_projection.c +8 -5
  102. package/vendor/raylib/examples/models/models_rlgl_solar_system.c +6 -4
  103. package/vendor/raylib/examples/models/models_skybox.c +16 -12
  104. package/vendor/raylib/examples/models/models_waving_cubes.c +9 -4
  105. package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +12 -7
  106. package/vendor/raylib/examples/models/resources/LICENSE.md +9 -10
  107. package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +2 -23
  108. package/vendor/raylib/examples/models/resources/models/gltf/{raylib_32x32.glb → raylib_logo_3d.glb} +0 -0
  109. package/vendor/raylib/examples/models/resources/models/gltf/robot.blend +0 -0
  110. package/vendor/raylib/examples/models/resources/models/gltf/robot.glb +0 -0
  111. package/vendor/raylib/examples/others/easings_testbed.c +10 -8
  112. package/vendor/raylib/examples/others/easings_testbed.png +0 -0
  113. package/vendor/raylib/examples/others/embedded_files_loading.c +10 -5
  114. package/vendor/raylib/examples/others/embedded_files_loading.png +0 -0
  115. package/vendor/raylib/examples/others/raylib_opengl_interop.c +10 -6
  116. package/vendor/raylib/{src/extras/easings.h → examples/others/reasings.h} +38 -38
  117. package/vendor/raylib/examples/others/rlgl_compute_shader.c +21 -20
  118. package/vendor/raylib/examples/others/rlgl_compute_shader.png +0 -0
  119. package/vendor/raylib/examples/others/rlgl_standalone.c +4 -4
  120. package/vendor/raylib/examples/others/rlgl_standalone.png +0 -0
  121. package/vendor/raylib/examples/raylib_compile_execute.bat +2 -2
  122. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +1 -1
  123. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/{base_lighting_instanced.vs → lighting_instancing.vs} +2 -2
  124. package/vendor/raylib/examples/shaders/rlights.h +14 -27
  125. package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +24 -26
  126. package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +10 -5
  127. package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +13 -8
  128. package/vendor/raylib/examples/shaders/shaders_fog.c +8 -12
  129. package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +10 -5
  130. package/vendor/raylib/examples/shaders/shaders_julia_set.c +9 -4
  131. package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +45 -119
  132. package/vendor/raylib/examples/shaders/shaders_model_shader.c +10 -5
  133. package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +8 -3
  134. package/vendor/raylib/examples/shaders/shaders_palette_switch.c +8 -3
  135. package/vendor/raylib/examples/shaders/shaders_postprocessing.c +9 -4
  136. package/vendor/raylib/examples/shaders/shaders_raymarching.c +14 -11
  137. package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +8 -3
  138. package/vendor/raylib/examples/shaders/shaders_simple_mask.c +10 -5
  139. package/vendor/raylib/examples/shaders/shaders_spotlight.c +10 -6
  140. package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +9 -4
  141. package/vendor/raylib/examples/shaders/shaders_texture_outline.c +8 -3
  142. package/vendor/raylib/examples/shaders/shaders_texture_waves.c +8 -3
  143. package/vendor/raylib/{src/extras → examples/shapes}/raygui.h +1290 -1141
  144. package/vendor/raylib/examples/{others/easings.h → shapes/reasings.h} +40 -40
  145. package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +8 -3
  146. package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +8 -3
  147. package/vendor/raylib/examples/shapes/shapes_collision_area.c +10 -4
  148. package/vendor/raylib/examples/shapes/shapes_colors_palette.c +8 -3
  149. package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +9 -4
  150. package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +9 -4
  151. package/vendor/raylib/examples/shapes/shapes_draw_ring.c +10 -6
  152. package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +9 -4
  153. package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +9 -4
  154. package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +9 -4
  155. package/vendor/raylib/examples/shapes/shapes_following_eyes.c +8 -3
  156. package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +8 -3
  157. package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +8 -3
  158. package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +8 -3
  159. package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +14 -5
  160. package/vendor/raylib/examples/shapes/shapes_top_down_lights.c +355 -0
  161. package/vendor/raylib/examples/shapes/shapes_top_down_lights.png +0 -0
  162. package/vendor/raylib/examples/text/resources/DotGothic16-Regular.ttf +0 -0
  163. package/vendor/raylib/examples/text/resources/DotGothic16-Regular_OFL.txt +93 -0
  164. package/vendor/raylib/examples/text/resources/LICENSE.md +1 -1
  165. package/vendor/raylib/examples/text/text_codepoints_loading.c +138 -0
  166. package/vendor/raylib/examples/text/text_codepoints_loading.png +0 -0
  167. package/vendor/raylib/examples/text/text_draw_3d.c +42 -33
  168. package/vendor/raylib/examples/text/text_font_filters.c +14 -11
  169. package/vendor/raylib/examples/text/text_font_loading.c +9 -4
  170. package/vendor/raylib/examples/text/text_font_sdf.c +9 -4
  171. package/vendor/raylib/examples/text/text_font_spritefont.c +12 -6
  172. package/vendor/raylib/examples/text/text_format_text.c +8 -3
  173. package/vendor/raylib/examples/text/text_input_box.c +8 -3
  174. package/vendor/raylib/examples/text/text_raylib_fonts.c +9 -4
  175. package/vendor/raylib/examples/text/text_rectangle_bounds.c +9 -5
  176. package/vendor/raylib/examples/text/text_unicode.c +9 -7
  177. package/vendor/raylib/examples/text/text_writing_anim.c +8 -3
  178. package/vendor/raylib/examples/textures/resources/scarfy_run.gif +0 -0
  179. package/vendor/raylib/examples/textures/textures_background_scrolling.c +8 -3
  180. package/vendor/raylib/examples/textures/textures_blend_modes.c +8 -3
  181. package/vendor/raylib/examples/textures/textures_bunnymark.c +8 -3
  182. package/vendor/raylib/examples/textures/textures_draw_tiled.c +14 -10
  183. package/vendor/raylib/examples/textures/textures_fog_of_war.c +154 -0
  184. package/vendor/raylib/examples/textures/textures_fog_of_war.png +0 -0
  185. package/vendor/raylib/examples/textures/textures_gif_player.c +121 -0
  186. package/vendor/raylib/examples/textures/textures_gif_player.png +0 -0
  187. package/vendor/raylib/examples/textures/textures_image_drawing.c +8 -3
  188. package/vendor/raylib/examples/textures/textures_image_generation.c +8 -3
  189. package/vendor/raylib/examples/textures/textures_image_loading.c +8 -3
  190. package/vendor/raylib/examples/textures/textures_image_processing.c +8 -3
  191. package/vendor/raylib/examples/textures/textures_image_text.c +8 -3
  192. package/vendor/raylib/examples/textures/textures_logo_raylib.c +8 -3
  193. package/vendor/raylib/examples/textures/textures_mouse_painting.c +9 -4
  194. package/vendor/raylib/examples/textures/textures_npatch_drawing.c +8 -3
  195. package/vendor/raylib/examples/textures/textures_particles_blending.c +8 -3
  196. package/vendor/raylib/examples/textures/textures_polygon.c +9 -5
  197. package/vendor/raylib/examples/textures/textures_raw_data.c +8 -3
  198. package/vendor/raylib/examples/textures/{textures_rectangle.c → textures_sprite_anim.c} +11 -5
  199. package/vendor/raylib/examples/textures/{textures_rectangle.png → textures_sprite_anim.png} +0 -0
  200. package/vendor/raylib/examples/textures/textures_sprite_button.c +8 -3
  201. package/vendor/raylib/examples/textures/textures_sprite_explosion.c +8 -3
  202. package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +8 -3
  203. package/vendor/raylib/examples/textures/textures_to_image.c +8 -3
  204. package/vendor/raylib/parser/LICENSE +1 -1
  205. package/vendor/raylib/parser/Makefile +28 -0
  206. package/vendor/raylib/parser/README.md +49 -5
  207. package/vendor/raylib/parser/output/raylib_api.json +10717 -0
  208. package/vendor/raylib/parser/output/raylib_api.lua +7435 -0
  209. package/vendor/raylib/parser/{raylib_api.txt → output/raylib_api.txt} +1371 -824
  210. package/vendor/raylib/parser/{raylib_api.xml → output/raylib_api.xml} +827 -595
  211. package/vendor/raylib/parser/raylib_parser.c +1174 -196
  212. package/vendor/raylib/projects/4coder/Makefile +2 -4
  213. package/vendor/raylib/projects/4coder/main.c +0 -1
  214. package/vendor/raylib/projects/CMake/CMakeLists.txt +13 -16
  215. package/vendor/raylib/projects/CMake/README.md +27 -0
  216. package/vendor/raylib/projects/CMake/core_basic_window.c +52 -31
  217. package/vendor/raylib/projects/CodeBlocks/README.md +4 -4
  218. package/vendor/raylib/projects/Geany/core_basic_window.c +1 -1
  219. package/vendor/raylib/projects/Notepad++/c_raylib.xml +168 -128
  220. package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
  221. package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
  222. package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
  223. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +168 -84
  224. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +67 -51
  225. package/vendor/raylib/projects/README.md +1 -1
  226. package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +1 -1
  227. package/vendor/raylib/projects/VSCode/Makefile +8 -11
  228. package/vendor/raylib/projects/VSCode/main.c +53 -26
  229. package/vendor/raylib/projects/VSCode/resources/LICENSE +1 -0
  230. package/vendor/raylib/projects/scripts/build-linux.sh +6 -6
  231. package/vendor/raylib/projects/scripts/build-osx.sh +6 -6
  232. package/vendor/raylib/projects/scripts/build-rpi.sh +6 -6
  233. package/vendor/raylib/projects/scripts/build-windows.bat +2 -2
  234. package/vendor/raylib/src/CMakeLists.txt +6 -7
  235. package/vendor/raylib/src/Makefile +209 -103
  236. package/vendor/raylib/src/build.zig +56 -20
  237. package/vendor/raylib/src/config.h +32 -27
  238. package/vendor/raylib/src/external/cgltf.h +342 -104
  239. package/vendor/raylib/src/external/dr_wav.h +487 -225
  240. package/vendor/raylib/src/external/glfw/src/posix_time.c +1 -3
  241. package/vendor/raylib/src/external/glfw/src/wl_init.c +1 -3
  242. package/vendor/raylib/src/external/jar_xm.h +2 -1
  243. package/vendor/raylib/src/external/miniaudio.h +62251 -42061
  244. package/vendor/raylib/src/external/qoi.h +671 -0
  245. package/vendor/raylib/src/external/stb_vorbis.h +1 -1
  246. package/vendor/raylib/src/external/vox_loader.h +30 -25
  247. package/vendor/raylib/src/minshell.html +82 -0
  248. package/vendor/raylib/src/raudio.c +359 -201
  249. package/vendor/raylib/src/raylib.dll.rc +5 -5
  250. package/vendor/raylib/src/raylib.dll.rc.data +0 -0
  251. package/vendor/raylib/src/raylib.h +95 -63
  252. package/vendor/raylib/src/raylib.rc +5 -5
  253. package/vendor/raylib/src/raylib.rc.data +0 -0
  254. package/vendor/raylib/src/raymath.h +391 -133
  255. package/vendor/raylib/src/rcamera.h +32 -41
  256. package/vendor/raylib/src/rcore.c +775 -471
  257. package/vendor/raylib/src/rgestures.h +5 -5
  258. package/vendor/raylib/src/rglfw.c +3 -3
  259. package/vendor/raylib/src/rlgl.h +184 -144
  260. package/vendor/raylib/src/rmodels.c +207 -144
  261. package/vendor/raylib/src/rshapes.c +105 -47
  262. package/vendor/raylib/src/rtext.c +255 -38
  263. package/vendor/raylib/src/rtextures.c +167 -71
  264. package/vendor/raylib/src/shell.html +63 -63
  265. package/vendor/raylib/src/utils.c +49 -3
  266. package/vendor/raylib/src/utils.h +3 -3
  267. package/build/qemu/2.1.0/koffi_darwin_arm64.tar.gz +0 -0
  268. package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
  269. package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
  270. package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
  271. package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
  272. package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
  273. package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
  274. package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
  275. package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  276. package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
  277. package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
  278. package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
  279. package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
  280. package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
  281. package/build/qemu/2.1.0/koffi_win32_x64.tar.gz +0 -0
  282. package/vendor/raylib/CONTRIBUTORS.md +0 -63
  283. package/vendor/raylib/SPONSORS.md +0 -68
  284. package/vendor/raylib/examples/core/core_quat_conversion.c +0 -132
  285. package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
  286. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
  287. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +0 -118
  288. package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
  289. package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
  290. package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
  291. package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
  292. package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
  293. package/vendor/raylib/examples/models/rlights.h +0 -183
  294. package/vendor/raylib/examples/others/raudio_standalone.c +0 -152
  295. package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
  296. package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
  297. package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
  298. package/vendor/raylib/examples/physics/physics_demo.c +0 -128
  299. package/vendor/raylib/examples/physics/physics_demo.png +0 -0
  300. package/vendor/raylib/examples/physics/physics_friction.c +0 -142
  301. package/vendor/raylib/examples/physics/physics_friction.png +0 -0
  302. package/vendor/raylib/examples/physics/physics_movement.c +0 -128
  303. package/vendor/raylib/examples/physics/physics_movement.png +0 -0
  304. package/vendor/raylib/examples/physics/physics_restitution.c +0 -129
  305. package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
  306. package/vendor/raylib/examples/physics/physics_shatter.c +0 -111
  307. package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
  308. package/vendor/raylib/parser/raylib_api.json +0 -6668
  309. package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
  310. package/vendor/raylib/projects/VS2019/raylib/resource.h +0 -14
  311. package/vendor/raylib/src/extras/physac.h +0 -1977
  312. package/vendor/raylib/src/extras/rmem.h +0 -751
  313. 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,42 +133,44 @@ 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
 
148
140
  return ptr;
149
141
  }
150
142
 
151
- void Resize(void **ptr, Size old_size, Size new_size, unsigned int flags) override
143
+ void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags) override
152
144
  {
153
145
  if (!new_size) {
154
- Release(*ptr, old_size);
155
- *ptr = nullptr;
146
+ Release(ptr, old_size);
147
+ ptr = nullptr;
156
148
  } else {
157
- void *new_ptr = realloc(*ptr, (size_t)new_size);
149
+ void *new_ptr = realloc(ptr, (size_t)new_size);
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
 
165
- *ptr = new_ptr;
157
+ ptr = new_ptr;
166
158
  }
159
+
160
+ return ptr;
167
161
  }
168
162
 
169
- void Release(void *ptr, Size) override
163
+ void Release(const void *ptr, Size) override
170
164
  {
171
- free(ptr);
165
+ free((void *)ptr);
172
166
  }
173
167
  };
174
168
 
175
169
  class NullAllocator: public Allocator {
176
170
  protected:
177
171
  void *Allocate(Size, unsigned int) override { RG_UNREACHABLE(); }
178
- void Resize(void **, Size, Size, unsigned int) override { RG_UNREACHABLE(); }
179
- void Release(void *, Size) override {}
172
+ void *Resize(void *, Size, Size, unsigned int) override { RG_UNREACHABLE(); }
173
+ void Release(const void *, Size) override {}
180
174
  };
181
175
 
182
176
  Allocator *GetDefaultAllocator()
@@ -205,7 +199,7 @@ void LinkedAllocator::ReleaseAll()
205
199
  Node *head = list.next;
206
200
  while (head) {
207
201
  Node *next = head->next;
208
- ReleaseMemory(allocator, head, -1);
202
+ ReleaseRaw(allocator, head, -1);
209
203
  head = next;
210
204
  }
211
205
  list = {};
@@ -213,7 +207,7 @@ void LinkedAllocator::ReleaseAll()
213
207
 
214
208
  void *LinkedAllocator::Allocate(Size size, unsigned int flags)
215
209
  {
216
- Bucket *bucket = AllocateMemory<Bucket>(allocator, RG_SIZE(*bucket) + size, flags).ptr;
210
+ Bucket *bucket = (Bucket *)AllocateRaw(allocator, RG_SIZE(Node) + size, flags);
217
211
 
218
212
  if (list.prev) {
219
213
  list.prev->next = &bucket->head;
@@ -227,26 +221,21 @@ void *LinkedAllocator::Allocate(Size size, unsigned int flags)
227
221
  bucket->head.next = nullptr;
228
222
  }
229
223
 
230
- uint8_t *data = bucket->data;
231
- uint8_t *aligned = AlignUp(data, 16);
232
-
233
- RG_ASSERT(aligned - data <= 8);
234
-
235
- return (void *)aligned;
224
+ return (void *)bucket->data;
236
225
  }
237
226
 
238
- void LinkedAllocator::Resize(void **ptr, Size old_size, Size new_size, unsigned int flags)
227
+ void *LinkedAllocator::Resize(void *ptr, Size old_size, Size new_size, unsigned int flags)
239
228
  {
240
- if (!*ptr) {
241
- *ptr = Allocate(new_size, flags);
229
+ if (!ptr) {
230
+ ptr = Allocate(new_size, flags);
242
231
  } else if (!new_size) {
243
- Release(*ptr, old_size);
244
- *ptr = nullptr;
232
+ Release(ptr, old_size);
233
+ ptr = nullptr;
245
234
  } else {
246
- Bucket *bucket = PointerToBucket(*ptr);
235
+ Bucket *bucket = PointerToBucket(ptr);
247
236
 
248
- bucket = ResizeMemory(allocator, bucket, RG_SIZE(*bucket) + old_size,
249
- RG_SIZE(*bucket) + new_size, flags).ptr;
237
+ bucket = (Bucket *)ResizeRaw(allocator, bucket, RG_SIZE(Node) + old_size,
238
+ RG_SIZE(Node) + new_size, flags);
250
239
 
251
240
  if (bucket->head.next) {
252
241
  bucket->head.next->prev = &bucket->head;
@@ -259,19 +248,16 @@ void LinkedAllocator::Resize(void **ptr, Size old_size, Size new_size, unsigned
259
248
  list.next = &bucket->head;
260
249
  }
261
250
 
262
- uint8_t *data = bucket->data;
263
- uint8_t *aligned = AlignUp(data, 16);
264
-
265
- RG_ASSERT(aligned - data <= 8);
266
-
267
- *ptr = (void *)aligned;
251
+ ptr = (void *)bucket->data;
268
252
  }
253
+
254
+ return ptr;
269
255
  }
270
256
 
271
- void LinkedAllocator::Release(void *ptr, Size size)
257
+ void LinkedAllocator::Release(const void *ptr, Size size)
272
258
  {
273
259
  if (ptr) {
274
- Bucket *bucket = PointerToBucket(ptr);
260
+ Bucket *bucket = PointerToBucket((void *)ptr);
275
261
 
276
262
  if (bucket->head.next) {
277
263
  bucket->head.next->prev = bucket->head.prev;
@@ -284,10 +270,16 @@ void LinkedAllocator::Release(void *ptr, Size size)
284
270
  list.next = bucket->head.next;
285
271
  }
286
272
 
287
- ReleaseMemory(allocator, bucket, size);
273
+ ReleaseRaw(allocator, bucket, RG_SIZE(Bucket) + size);
288
274
  }
289
275
  }
290
276
 
277
+ LinkedAllocator::Bucket *LinkedAllocator::PointerToBucket(void *ptr)
278
+ {
279
+ uint8_t *data = (uint8_t *)ptr;
280
+ return (Bucket *)(data - RG_OFFSET_OF(Bucket, data));
281
+ }
282
+
291
283
  void *BlockAllocatorBase::Allocate(Size size, unsigned int flags)
292
284
  {
293
285
  RG_ASSERT(size >= 0);
@@ -298,21 +290,19 @@ void *BlockAllocatorBase::Allocate(Size size, unsigned int flags)
298
290
  Size aligned_size = AlignLen(size, 8);
299
291
 
300
292
  if (AllocateSeparately(aligned_size)) {
301
- uint8_t *ptr = AllocateMemory<uint8_t>(alloc, size, flags).ptr;
293
+ uint8_t *ptr = (uint8_t *)AllocateRaw(alloc, size, flags);
302
294
  return ptr;
303
295
  } else {
304
296
  if (!current_bucket || (current_bucket->used + aligned_size) > block_size) {
305
- current_bucket = AllocateMemory<Bucket>(alloc, RG_SIZE(Bucket) + block_size,
306
- flags & ~(int)Allocator::Flag::Zero).ptr;
307
- current_bucket->used = AlignUp(current_bucket->data, 16) - current_bucket->data;
308
-
309
- RG_ASSERT(current_bucket->used <= 8);
297
+ current_bucket = (Bucket *)AllocateRaw(alloc, RG_SIZE(Bucket) + block_size,
298
+ flags & ~(int)AllocFlag::Zero);
299
+ current_bucket->used = 0;
310
300
  }
311
301
 
312
302
  uint8_t *ptr = current_bucket->data + current_bucket->used;
313
303
  current_bucket->used += aligned_size;
314
304
 
315
- if (flags & (int)Allocator::Flag::Zero) {
305
+ if (flags & (int)AllocFlag::Zero) {
316
306
  memset_safe(ptr, 0, size);
317
307
  }
318
308
 
@@ -321,15 +311,16 @@ void *BlockAllocatorBase::Allocate(Size size, unsigned int flags)
321
311
  }
322
312
  }
323
313
 
324
- void BlockAllocatorBase::Resize(void **ptr, Size old_size, Size new_size, unsigned int flags)
314
+ void *BlockAllocatorBase::Resize(void *ptr, Size old_size, Size new_size, unsigned int flags)
325
315
  {
326
316
  RG_ASSERT(old_size >= 0);
327
317
  RG_ASSERT(new_size >= 0);
328
318
 
329
319
  if (!new_size) {
330
- Release(*ptr, old_size);
320
+ Release(ptr, old_size);
321
+ ptr = nullptr;
331
322
  } else {
332
- if (!*ptr) {
323
+ if (!ptr) {
333
324
  old_size = 0;
334
325
  }
335
326
 
@@ -338,35 +329,37 @@ void BlockAllocatorBase::Resize(void **ptr, Size old_size, Size new_size, unsign
338
329
  Size aligned_delta = aligned_new_size - aligned_old_size;
339
330
 
340
331
  // Try fast path
341
- if (*ptr && *ptr == last_alloc &&
332
+ if (ptr && ptr == last_alloc &&
342
333
  (current_bucket->used + aligned_delta) <= block_size &&
343
334
  !AllocateSeparately(aligned_new_size)) {
344
335
  current_bucket->used += aligned_delta;
345
336
 
346
- if ((flags & (int)Allocator::Flag::Zero) && new_size > old_size) {
347
- memset_safe(ptr + old_size, 0, new_size - old_size);
337
+ if ((flags & (int)AllocFlag::Zero) && new_size > old_size) {
338
+ memset_safe((uint8_t *)ptr + old_size, 0, new_size - old_size);
348
339
  }
349
340
  } else if (AllocateSeparately(aligned_old_size)) {
350
341
  LinkedAllocator *alloc = GetAllocator();
351
- ptr = ResizeMemory(alloc, ptr, old_size, new_size, flags).ptr;
342
+ ptr = ResizeRaw(alloc, ptr, old_size, new_size, flags);
352
343
  } else {
353
- void *new_ptr = Allocate(new_size, flags & ~(int)Allocator::Flag::Zero);
344
+ void *new_ptr = Allocate(new_size, flags & ~(int)AllocFlag::Zero);
354
345
  if (new_size > old_size) {
355
- memcpy_safe(new_ptr, *ptr, old_size);
346
+ memcpy_safe(new_ptr, ptr, old_size);
356
347
 
357
- if (flags & (int)Allocator::Flag::Zero) {
358
- memset_safe(ptr + old_size, 0, new_size - old_size);
348
+ if (flags & (int)AllocFlag::Zero) {
349
+ memset_safe((uint8_t *)ptr + old_size, 0, new_size - old_size);
359
350
  }
360
351
  } else {
361
- memcpy_safe(new_ptr, *ptr, new_size);
352
+ memcpy_safe(new_ptr, ptr, new_size);
362
353
  }
363
354
 
364
- *ptr = new_ptr;
355
+ ptr = new_ptr;
365
356
  }
366
357
  }
358
+
359
+ return ptr;
367
360
  }
368
361
 
369
- void BlockAllocatorBase::Release(void *ptr, Size size)
362
+ void BlockAllocatorBase::Release(const void *ptr, Size size)
370
363
  {
371
364
  RG_ASSERT(size >= 0);
372
365
 
@@ -377,13 +370,15 @@ void BlockAllocatorBase::Release(void *ptr, Size size)
377
370
 
378
371
  if (ptr == last_alloc) {
379
372
  current_bucket->used -= aligned_size;
373
+
380
374
  if (!current_bucket->used) {
381
- ReleaseMemory(alloc, current_bucket, RG_SIZE(Bucket) + block_size);
375
+ ReleaseRaw(alloc, current_bucket, RG_SIZE(Bucket) + block_size);
382
376
  current_bucket = nullptr;
383
377
  }
378
+
384
379
  last_alloc = nullptr;
385
380
  } else if (AllocateSeparately(aligned_size)) {
386
- ReleaseMemory(alloc, ptr, size);
381
+ ReleaseRaw(alloc, ptr, size);
387
382
  }
388
383
  }
389
384
  }
@@ -425,6 +420,7 @@ IndirectBlockAllocator& IndirectBlockAllocator::operator=(IndirectBlockAllocator
425
420
 
426
421
  void IndirectBlockAllocator::ReleaseAll()
427
422
  {
423
+ ForgetCurrentBlock();
428
424
  allocator->ReleaseAll();
429
425
  }
430
426
 
@@ -692,7 +688,7 @@ TimeSpec DecomposeTime(int64_t time, TimeMode mode)
692
688
  switch (mode) {
693
689
  case TimeMode::Local: {
694
690
  localtime_r(&time64, &ti);
695
- offset = ti.tm_gmtoff + ti.tm_isdst * 3600;
691
+ offset = ti.tm_gmtoff;
696
692
  } break;
697
693
 
698
694
  case TimeMode::UTC: {
@@ -762,7 +758,7 @@ bool CopyString(Span<const char> str, Span<char> buf)
762
758
 
763
759
  Span<char> DuplicateString(Span<const char> str, Allocator *alloc)
764
760
  {
765
- char *new_str = AllocateMemory<char>(alloc, str.len + 1).ptr;
761
+ char *new_str = (char *)AllocateRaw(alloc, str.len + 1);
766
762
  memcpy_safe(new_str, str.ptr, (size_t)str.len);
767
763
  new_str[str.len] = 0;
768
764
  return MakeSpan(new_str, str.len);
@@ -830,7 +826,7 @@ static Span<char> FormatUnsignedToDecimal(uint64_t value, char out_buf[32])
830
826
  return MakeSpan(out_buf + offset, 32 - offset);
831
827
  }
832
828
 
833
- static Span<char> FormatUnsignedToHex(uint64_t value, char out_buf[32])
829
+ static Span<char> FormatUnsignedToBigHex(uint64_t value, char out_buf[32])
834
830
  {
835
831
  static const char literals[] = "0123456789ABCDEF";
836
832
 
@@ -844,6 +840,20 @@ static Span<char> FormatUnsignedToHex(uint64_t value, char out_buf[32])
844
840
  return MakeSpan(out_buf + offset, 32 - offset);
845
841
  }
846
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
+
847
857
  static Span<char> FormatUnsignedToBinary(uint64_t value, char out_buf[64])
848
858
  {
849
859
  Size msb = 64 - (Size)CountLeadingZeros(value);
@@ -1135,8 +1145,11 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1135
1145
  case FmtType::Binary: {
1136
1146
  out = FormatUnsignedToBinary(arg.u.u, num_buf);
1137
1147
  } break;
1138
- case FmtType::Hexadecimal: {
1139
- 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);
1140
1153
  } break;
1141
1154
 
1142
1155
  case FmtType::MemorySize: {
@@ -1246,42 +1259,69 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1246
1259
  } break;
1247
1260
 
1248
1261
  case FmtType::TimeISO: {
1249
- if (arg.u.time.offset) {
1250
- int offset_h = arg.u.time.offset / 60;
1251
- 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;
1252
1267
 
1253
1268
  out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6.%7%8%9%10",
1254
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1255
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1256
- 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),
1257
1272
  offset_h >= 0 ? "+" : "", FmtArg(offset_h).Pad0(-2), FmtArg(offset_m).Pad0(-2)).len;
1258
- } 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) {
1259
1283
  out_buf.len = Fmt(out_buf.data, "%1%2%3T%4%5%6.%7Z",
1260
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1261
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1262
- 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;
1263
1292
  }
1264
1293
  out = out_buf;
1265
1294
  } break;
1266
1295
  case FmtType::TimeNice: {
1267
- int offset_h = arg.u.time.offset / 60;
1268
- int offset_m = arg.u.time.offset % 60;
1269
-
1270
- out_buf.len = Fmt(out_buf.data, "%1-%2-%3 %4:%5:%6.%7 %8%9%10",
1271
- FmtArg(arg.u.time.year).Pad0(-2), FmtArg(arg.u.time.month).Pad0(-2),
1272
- FmtArg(arg.u.time.day).Pad0(-2), FmtArg(arg.u.time.hour).Pad0(-2),
1273
- FmtArg(arg.u.time.min).Pad0(-2), FmtArg(arg.u.time.sec).Pad0(-2), FmtArg(arg.u.time.msec).Pad0(-3),
1274
- 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
+ }
1275
1314
  out = out_buf;
1276
1315
  } break;
1277
1316
 
1278
1317
  case FmtType::Random: {
1279
- 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;
1280
1320
 
1281
- for (Size j = 0; j < arg.u.random_len; j++) {
1282
- static const char *chars = "abcdefghijklmnopqrstuvwxyz0123456789";
1321
+ RG_ASSERT(arg.u.random.len <= RG_SIZE(out_buf.data));
1283
1322
 
1284
- 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);
1285
1325
  out_buf.Append(chars[rnd]);
1286
1326
  }
1287
1327
 
@@ -1335,7 +1375,8 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1335
1375
  case FmtType::Integer:
1336
1376
  case FmtType::Unsigned:
1337
1377
  case FmtType::Binary:
1338
- case FmtType::Hexadecimal: {
1378
+ case FmtType::BigHex:
1379
+ case FmtType::SmallHex: {
1339
1380
  switch (arg.u.span.type_len) {
1340
1381
  case 8: { arg2.u.u = *(const uint64_t *)ptr; } break;
1341
1382
  case 4: { arg2.u.u = *(const uint32_t *)ptr; } break;
@@ -1358,7 +1399,7 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
1358
1399
  case FmtType::DiskSize: { arg2.u.i = *(const int64_t *)ptr; } break;
1359
1400
  case FmtType::Date: { arg2.u.date = *(const LocalDate *)ptr; } break;
1360
1401
  case FmtType::TimeISO:
1361
- case FmtType::TimeNice: { arg2.u.time = *(const TimeSpec *)ptr; } break;
1402
+ case FmtType::TimeNice: { arg2.u.time = *(decltype(FmtArg::u.time) *)ptr; } break;
1362
1403
  case FmtType::Random: { RG_UNREACHABLE(); } break;
1363
1404
  case FmtType::FlagNames: { RG_UNREACHABLE(); } break;
1364
1405
  case FmtType::FlagOptions: { RG_UNREACHABLE(); } break;
@@ -1677,6 +1718,20 @@ void PrintLnFmt(const char *fmt, Span<const FmtArg> args, FILE *fp)
1677
1718
  fputc('\n', fp);
1678
1719
  }
1679
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
+
1680
1735
  // ------------------------------------------------------------------------
1681
1736
  // Debug and errors
1682
1737
  // ------------------------------------------------------------------------
@@ -2027,7 +2082,7 @@ static FileType FileAttributesToType(uint32_t attr)
2027
2082
  }
2028
2083
  }
2029
2084
 
2030
- bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2085
+ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2031
2086
  {
2032
2087
  // We don't detect symbolic links, but since they are much less of a hazard
2033
2088
  // than on POSIX systems we care a lot less about them.
@@ -2039,40 +2094,54 @@ bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2039
2094
  } else {
2040
2095
  wchar_t filename_w[4096];
2041
2096
  if (ConvertUtf8ToWin32Wide(filename, filename_w) < 0)
2042
- return false;
2097
+ return StatResult::OtherError;
2043
2098
 
2044
2099
  h = CreateFileW(filename_w, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2045
2100
  nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
2046
2101
  }
2047
2102
  if (h == INVALID_HANDLE_VALUE) {
2048
2103
  DWORD err = GetLastError();
2049
- if (!(flags & (int)StatFlag::IgnoreMissing) ||
2050
- (err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND)) {
2051
- 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;
2052
2121
  }
2053
- return false;
2054
2122
  }
2055
2123
  RG_DEFER { CloseHandle(h); };
2056
2124
 
2057
2125
  BY_HANDLE_FILE_INFORMATION attr;
2058
2126
  if (!GetFileInformationByHandle(h, &attr)) {
2059
2127
  LogError("Cannot stat file '%1': %2", filename, GetWin32ErrorString());
2060
- return false;
2128
+ return StatResult::OtherError;
2061
2129
  }
2062
2130
 
2063
2131
  out_info->type = FileAttributesToType(attr.dwFileAttributes);
2064
2132
  out_info->size = ((uint64_t)attr.nFileSizeHigh << 32) | attr.nFileSizeLow;
2065
2133
  out_info->mtime = FileTimeToUnixTime(attr.ftLastWriteTime);
2134
+ out_info->mode = (out_info->type == FileType::Directory) ? 0755 : 0644;
2066
2135
 
2067
- return true;
2136
+ return StatResult::Success;
2068
2137
  }
2069
2138
 
2070
- 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)
2071
2140
  {
2072
- DWORD flags = overwrite ? MOVEFILE_REPLACE_EXISTING : 0;
2141
+ DWORD move_flags = (flags & (int)RenameFlag::Overwrite) ? MOVEFILE_REPLACE_EXISTING : 0;
2073
2142
 
2074
2143
  if (win32_utf8) {
2075
- if (!MoveFileExA(src_filename, dest_filename, flags))
2144
+ if (!MoveFileExA(src_filename, dest_filename, move_flags))
2076
2145
  goto error;
2077
2146
  } else {
2078
2147
  wchar_t src_filename_w[4096];
@@ -2082,7 +2151,7 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2082
2151
  if (ConvertUtf8ToWin32Wide(dest_filename, dest_filename_w) < 0)
2083
2152
  return false;
2084
2153
 
2085
- if (!MoveFileExW(src_filename_w, dest_filename_w, flags))
2154
+ if (!MoveFileExW(src_filename_w, dest_filename_w, move_flags))
2086
2155
  goto error;
2087
2156
  }
2088
2157
 
@@ -2093,7 +2162,7 @@ error:
2093
2162
  return false;
2094
2163
  }
2095
2164
 
2096
- EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2165
+ EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2097
2166
  FunctionRef<bool(const char *, FileType)> func)
2098
2167
  {
2099
2168
  if (filter) {
@@ -2107,18 +2176,20 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2107
2176
  char find_filter[4096];
2108
2177
  if (snprintf(find_filter, RG_SIZE(find_filter), "%s\\%s", dirname, filter) >= RG_SIZE(find_filter)) {
2109
2178
  LogError("Cannot enumerate directory '%1': Path too long", dirname);
2110
- return EnumStatus::Error;
2179
+ return EnumResult::OtherError;
2111
2180
  }
2112
2181
 
2113
2182
  if (ConvertUtf8ToWin32Wide(find_filter, find_filter_w) < 0)
2114
- return EnumStatus::Error;
2183
+ return EnumResult::OtherError;
2115
2184
  }
2116
2185
 
2117
2186
  WIN32_FIND_DATAW find_data;
2118
2187
  HANDLE handle = FindFirstFileExW(find_filter_w, FindExInfoBasic, &find_data,
2119
2188
  FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
2120
2189
  if (handle == INVALID_HANDLE_VALUE) {
2121
- if (GetLastError() == ERROR_FILE_NOT_FOUND) {
2190
+ DWORD err = GetLastError();
2191
+
2192
+ if (err == ERROR_FILE_NOT_FOUND) {
2122
2193
  // Erase the filter part from the buffer, we are about to exit anyway.
2123
2194
  // And no, I don't want to include wchar.h
2124
2195
  Size len = 0;
@@ -2128,12 +2199,17 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2128
2199
 
2129
2200
  DWORD attrib = GetFileAttributesW(find_filter_w);
2130
2201
  if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY))
2131
- return EnumStatus::Complete;
2202
+ return EnumResult::Success;
2132
2203
  }
2133
2204
 
2134
- LogError("Cannot enumerate directory '%1': %2", dirname,
2135
- GetWin32ErrorString());
2136
- 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
+ }
2137
2213
  }
2138
2214
  RG_DEFER { FindClose(handle); };
2139
2215
 
@@ -2145,26 +2221,26 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2145
2221
 
2146
2222
  if (RG_UNLIKELY(count++ >= max_files && max_files >= 0)) {
2147
2223
  LogError("Partial enumation of directory '%1'", dirname);
2148
- return EnumStatus::Partial;
2224
+ return EnumResult::PartialEnum;
2149
2225
  }
2150
2226
 
2151
2227
  char filename[512];
2152
2228
  if (ConvertWin32WideToUtf8(find_data.cFileName, filename) < 0)
2153
- return EnumStatus::Error;
2229
+ return EnumResult::OtherError;
2154
2230
 
2155
2231
  FileType file_type = FileAttributesToType(find_data.dwFileAttributes);
2156
2232
 
2157
2233
  if (!func(filename, file_type))
2158
- return EnumStatus::Stopped;
2234
+ return EnumResult::CallbackFail;
2159
2235
  } while (FindNextFileW(handle, &find_data));
2160
2236
 
2161
2237
  if (GetLastError() != ERROR_NO_MORE_FILES) {
2162
2238
  LogError("Error while enumerating directory '%1': %2", dirname,
2163
2239
  GetWin32ErrorString());
2164
- return EnumStatus::Error;
2240
+ return EnumResult::OtherError;
2165
2241
  }
2166
2242
 
2167
- return EnumStatus::Complete;
2243
+ return EnumResult::Success;
2168
2244
  }
2169
2245
 
2170
2246
  #else
@@ -2203,16 +2279,28 @@ static FileType FileModeToType(mode_t mode)
2203
2279
  }
2204
2280
  }
2205
2281
 
2206
- bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2282
+ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2207
2283
  {
2208
2284
  int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
2209
2285
 
2210
2286
  struct stat sb;
2211
2287
  if (fstatat(AT_FDCWD, filename, &sb, stat_flags) < 0) {
2212
- if (!(flags & (int)StatFlag::IgnoreMissing) || errno != ENOENT) {
2213
- 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;
2214
2303
  }
2215
- return false;
2216
2304
  }
2217
2305
 
2218
2306
  out_info->type = FileModeToType(sb.st_mode);
@@ -2226,8 +2314,9 @@ bool StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2226
2314
  #else
2227
2315
  out_info->mtime = (int64_t)sb.st_mtime * 1000;
2228
2316
  #endif
2317
+ out_info->mode = (unsigned int)sb.st_mode;
2229
2318
 
2230
- return true;
2319
+ return StatResult::Success;
2231
2320
  }
2232
2321
 
2233
2322
  static bool SyncFileDirectory(const char *filename)
@@ -2257,10 +2346,10 @@ static bool SyncFileDirectory(const char *filename)
2257
2346
  return true;
2258
2347
  }
2259
2348
 
2260
- 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)
2261
2350
  {
2262
2351
  int fd = -1;
2263
- if (!overwrite) {
2352
+ if (!(flags & (int)RenameFlag::Overwrite)) {
2264
2353
  fd = open(dest_filename, O_CREAT | O_EXCL, 0644);
2265
2354
  if (fd < 0) {
2266
2355
  if (errno == EEXIST) {
@@ -2281,7 +2370,7 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2281
2370
 
2282
2371
  // Not much we can do if fsync fails (I think), so ignore errors.
2283
2372
  // Hope for the best: that's the spirit behind the POSIX filesystem API (...).
2284
- if (sync) {
2373
+ if (flags & (int)RenameFlag::Sync) {
2285
2374
  SyncFileDirectory(src_filename);
2286
2375
  SyncFileDirectory(dest_filename);
2287
2376
  }
@@ -2289,13 +2378,18 @@ bool RenameFile(const char *src_filename, const char *dest_filename, bool overwr
2289
2378
  return true;
2290
2379
  }
2291
2380
 
2292
- EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2381
+ EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
2293
2382
  FunctionRef<bool(const char *, FileType)> func)
2294
2383
  {
2295
2384
  DIR *dirp = RG_POSIX_RESTART_EINTR(opendir(dirname), == nullptr);
2296
2385
  if (!dirp) {
2297
2386
  LogError("Cannot enumerate directory '%1': %2", dirname, strerror(errno));
2298
- 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
+ }
2299
2393
  }
2300
2394
  RG_DEFER { closedir(dirp); };
2301
2395
 
@@ -2312,7 +2406,7 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2312
2406
  if (!filter || !fnmatch(filter, dent->d_name, FNM_PERIOD)) {
2313
2407
  if (RG_UNLIKELY(count++ >= max_files && max_files >= 0)) {
2314
2408
  LogError("Partial enumation of directory '%1'", dirname);
2315
- return EnumStatus::Partial;
2409
+ return EnumResult::PartialEnum;
2316
2410
  }
2317
2411
 
2318
2412
  FileType file_type;
@@ -2345,7 +2439,7 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2345
2439
  }
2346
2440
 
2347
2441
  if (!func(dent->d_name, file_type))
2348
- return EnumStatus::Stopped;
2442
+ return EnumResult::CallbackFail;
2349
2443
  }
2350
2444
 
2351
2445
  errno = 0;
@@ -2353,10 +2447,10 @@ EnumStatus EnumerateDirectory(const char *dirname, const char *filter, Size max_
2353
2447
 
2354
2448
  if (errno) {
2355
2449
  LogError("Error while enumerating directory '%1': %2", dirname, strerror(errno));
2356
- return EnumStatus::Error;
2450
+ return EnumResult::OtherError;
2357
2451
  }
2358
2452
 
2359
- return EnumStatus::Complete;
2453
+ return EnumResult::Success;
2360
2454
  }
2361
2455
 
2362
2456
  #endif
@@ -2366,8 +2460,8 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2366
2460
  {
2367
2461
  RG_DEFER_NC(out_guard, len = out_files->len) { out_files->RemoveFrom(len); };
2368
2462
 
2369
- EnumStatus status = EnumerateDirectory(dirname, nullptr, max_files,
2370
- [&](const char *basename, FileType file_type) {
2463
+ EnumResult ret = EnumerateDirectory(dirname, nullptr, max_files,
2464
+ [&](const char *basename, FileType file_type) {
2371
2465
  switch (file_type) {
2372
2466
  case FileType::Directory: {
2373
2467
  if (max_depth) {
@@ -2392,7 +2486,7 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2392
2486
 
2393
2487
  return true;
2394
2488
  });
2395
- if (status == EnumStatus::Error)
2489
+ if (ret != EnumResult::Success && ret != EnumResult::PartialEnum)
2396
2490
  return false;
2397
2491
 
2398
2492
  out_guard.Disable();
@@ -2401,14 +2495,19 @@ bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Siz
2401
2495
 
2402
2496
  bool IsDirectoryEmpty(const char *dirname)
2403
2497
  {
2404
- EnumStatus status = EnumerateDirectory(dirname, nullptr, -1, [](const char *, FileType) { return false; });
2405
- 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;
2406
2502
  }
2407
2503
 
2408
2504
  bool TestFile(const char *filename)
2409
2505
  {
2410
2506
  FileInfo file_info;
2411
- 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;
2412
2511
  }
2413
2512
 
2414
2513
  bool TestFile(const char *filename, FileType type)
@@ -2416,7 +2515,7 @@ bool TestFile(const char *filename, FileType type)
2416
2515
  RG_ASSERT(type != FileType::Link);
2417
2516
 
2418
2517
  FileInfo file_info;
2419
- if (!StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info))
2518
+ if (StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info) != StatResult::Success)
2420
2519
  return false;
2421
2520
 
2422
2521
  // Don't follow, but don't warn if we just wanted a file
@@ -2771,7 +2870,7 @@ const char *GetApplicationExecutable()
2771
2870
  RG_ASSERT(strlen(path) < RG_SIZE(executable_path));
2772
2871
 
2773
2872
  CopyString(path, executable_path);
2774
- ReleaseMemory(nullptr, (void *)path, -1);
2873
+ ReleaseRaw(nullptr, (void *)path, -1);
2775
2874
  }
2776
2875
  }
2777
2876
 
@@ -2963,47 +3062,49 @@ static bool CheckForDumbTerm()
2963
3062
 
2964
3063
  #ifdef _WIN32
2965
3064
 
2966
- int OpenDescriptor(const char *filename, unsigned int flags)
3065
+ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int silent, int *out_fd)
2967
3066
  {
3067
+ RG_ASSERT(!(silent & ((int)OpenResult::Success | (int)OpenResult::OtherError)));
3068
+
2968
3069
  DWORD access = 0;
2969
3070
  DWORD share = 0;
2970
3071
  DWORD creation = 0;
2971
3072
  int oflags = -1;
2972
- switch (flags & ((int)OpenFileFlag::Read |
2973
- (int)OpenFileFlag::Write |
2974
- (int)OpenFileFlag::Append)) {
2975
- case (int)OpenFileFlag::Read: {
3073
+ switch (flags & ((int)OpenFlag::Read |
3074
+ (int)OpenFlag::Write |
3075
+ (int)OpenFlag::Append)) {
3076
+ case (int)OpenFlag::Read: {
2976
3077
  access = GENERIC_READ;
2977
3078
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2978
3079
  creation = OPEN_EXISTING;
2979
3080
 
2980
3081
  oflags = _O_RDONLY | _O_BINARY | _O_NOINHERIT;
2981
3082
  } break;
2982
- case (int)OpenFileFlag::Write: {
3083
+ case (int)OpenFlag::Write: {
2983
3084
  access = GENERIC_WRITE;
2984
3085
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2985
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3086
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
2986
3087
 
2987
3088
  oflags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY | _O_NOINHERIT;
2988
3089
  } break;
2989
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: {
3090
+ case (int)OpenFlag::Read | (int)OpenFlag::Write: {
2990
3091
  access = GENERIC_READ | GENERIC_WRITE;
2991
3092
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2992
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3093
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
2993
3094
 
2994
3095
  oflags = _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY | _O_NOINHERIT;
2995
3096
  } break;
2996
- case (int)OpenFileFlag::Append: {
3097
+ case (int)OpenFlag::Append: {
2997
3098
  access = GENERIC_WRITE;
2998
3099
  share = FILE_SHARE_READ | FILE_SHARE_WRITE;
2999
- creation = (flags & (int)OpenFileFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3100
+ creation = (flags & (int)OpenFlag::Exclusive) ? CREATE_NEW : CREATE_ALWAYS;
3000
3101
 
3001
3102
  oflags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY | _O_NOINHERIT;
3002
3103
  } break;
3003
3104
  }
3004
3105
  RG_ASSERT(oflags >= 0);
3005
3106
 
3006
- if (flags & (int)OpenFileFlag::Exclusive) {
3107
+ if (flags & (int)OpenFlag::Exclusive) {
3007
3108
  oflags |= (int)_O_EXCL;
3008
3109
  }
3009
3110
  share |= FILE_SHARE_DELETE;
@@ -3014,20 +3115,26 @@ int OpenDescriptor(const char *filename, unsigned int flags)
3014
3115
  } else {
3015
3116
  wchar_t filename_w[4096];
3016
3117
  if (ConvertUtf8ToWin32Wide(filename, filename_w) < 0)
3017
- return -1;
3118
+ return OpenResult::OtherError;
3018
3119
 
3019
3120
  h = CreateFileW(filename_w, access, share, nullptr, creation, FILE_ATTRIBUTE_NORMAL, nullptr);
3020
3121
  }
3021
3122
  if (h == INVALID_HANDLE_VALUE) {
3022
3123
  DWORD err = GetLastError();
3023
3124
 
3024
- if (err == ERROR_FILE_EXISTS) {
3025
- LogError("File '%1' already exists", filename);
3026
- } else {
3027
- 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;
3028
3132
  }
3029
3133
 
3030
- return -1;
3134
+ if (!(silent & (int)ret)) {
3135
+ LogError("Cannot open '%1': %2", filename, GetWin32ErrorString(err));
3136
+ }
3137
+ return ret;
3031
3138
  }
3032
3139
 
3033
3140
  int fd = _open_osfhandle((intptr_t)h, oflags);
@@ -3035,22 +3142,23 @@ int OpenDescriptor(const char *filename, unsigned int flags)
3035
3142
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3036
3143
  CloseHandle(h);
3037
3144
 
3038
- return -1;
3145
+ return OpenResult::OtherError;
3039
3146
  }
3040
3147
 
3041
- return fd;
3148
+ *out_fd = fd;
3149
+ return OpenResult::Success;
3042
3150
  }
3043
3151
 
3044
- FILE *OpenFile(const char *filename, unsigned int flags)
3152
+ OpenResult OpenFile(const char *filename, unsigned int flags, unsigned int silent, FILE **out_fp)
3045
3153
  {
3046
3154
  char mode[16] = {};
3047
- switch (flags & ((int)OpenFileFlag::Read |
3048
- (int)OpenFileFlag::Write |
3049
- (int)OpenFileFlag::Append)) {
3050
- case (int)OpenFileFlag::Read: { CopyString("rbc", mode); } break;
3051
- case (int)OpenFileFlag::Write: { CopyString("wbc", mode); } break;
3052
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { CopyString("w+bc", mode); } break;
3053
- 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;
3054
3162
  }
3055
3163
  RG_ASSERT(mode[0]);
3056
3164
 
@@ -3059,17 +3167,35 @@ FILE *OpenFile(const char *filename, unsigned int flags)
3059
3167
  strcat(mode, "N");
3060
3168
  #endif
3061
3169
 
3062
- int fd = OpenDescriptor(filename, flags);
3063
- if (fd < 0)
3064
- return nullptr;
3170
+ int fd = -1;
3171
+ OpenResult ret = OpenDescriptor(filename, flags, silent, &fd);
3172
+ if (ret != OpenResult::Success)
3173
+ return ret;
3065
3174
 
3066
3175
  FILE *fp = _fdopen(fd, mode);
3067
3176
  if (!fp) {
3068
3177
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3069
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;
3070
3196
  }
3071
3197
 
3072
- return fp;
3198
+ return true;
3073
3199
  }
3074
3200
 
3075
3201
  bool FlushFile(FILE *fp, const char *filename)
@@ -3269,60 +3395,89 @@ error:
3269
3395
 
3270
3396
  #else
3271
3397
 
3272
- int OpenDescriptor(const char *filename, unsigned int flags)
3398
+ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int silent, int *out_fd)
3273
3399
  {
3400
+ RG_ASSERT(!(silent & ((int)OpenResult::Success | (int)OpenResult::OtherError)));
3401
+
3274
3402
  int oflags = -1;
3275
- switch (flags & ((int)OpenFileFlag::Read |
3276
- (int)OpenFileFlag::Write |
3277
- (int)OpenFileFlag::Append)) {
3278
- case (int)OpenFileFlag::Read: { oflags = O_RDONLY | O_CLOEXEC; } break;
3279
- case (int)OpenFileFlag::Write: { oflags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3280
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { oflags = O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC; } break;
3281
- 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;
3282
3410
  }
3283
3411
  RG_ASSERT(oflags >= 0);
3284
3412
 
3285
- if (flags & (int)OpenFileFlag::Exclusive) {
3413
+ if (flags & (int)OpenFlag::Exclusive) {
3286
3414
  oflags |= O_EXCL;
3287
3415
  }
3288
3416
 
3289
3417
  int fd = RG_POSIX_RESTART_EINTR(open(filename, oflags, 0644), < 0);
3290
3418
  if (fd < 0) {
3291
- if (errno == EEXIST) {
3292
- LogError("File '%1' already exists", filename);
3293
- } 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)) {
3294
3428
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3295
3429
  }
3296
- return -1;
3430
+ return ret;
3297
3431
  }
3298
3432
 
3299
- return fd;
3433
+ *out_fd = fd;
3434
+ return OpenResult::Success;
3300
3435
  }
3301
3436
 
3302
- FILE *OpenFile(const char *filename, unsigned int flags)
3437
+ OpenResult OpenFile(const char *filename, unsigned int flags, unsigned int silent, FILE **out_fp)
3303
3438
  {
3304
3439
  const char *mode = nullptr;
3305
- switch (flags & ((int)OpenFileFlag::Read |
3306
- (int)OpenFileFlag::Write |
3307
- (int)OpenFileFlag::Append)) {
3308
- case (int)OpenFileFlag::Read: { mode = "rbe"; } break;
3309
- case (int)OpenFileFlag::Write: { mode = "wbe"; } break;
3310
- case (int)OpenFileFlag::Read | (int)OpenFileFlag::Write: { mode = "w+be"; } break;
3311
- 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;
3312
3447
  }
3313
3448
  RG_ASSERT(mode);
3314
3449
 
3315
- int fd = OpenDescriptor(filename, flags);
3316
- if (fd < 0)
3317
- return nullptr;
3450
+ int fd = -1;
3451
+ OpenResult ret = OpenDescriptor(filename, flags, silent, &fd);
3452
+ if (ret != OpenResult::Success)
3453
+ return ret;
3318
3454
 
3319
3455
  FILE *fp = fdopen(fd, mode);
3320
3456
  if (!fp) {
3321
3457
  LogError("Cannot open '%1': %2", filename, strerror(errno));
3322
3458
  close(fd);
3459
+
3460
+ return OpenResult::OtherError;
3323
3461
  }
3324
3462
 
3325
- 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;
3326
3481
  }
3327
3482
 
3328
3483
  bool FlushFile(FILE *fp, const char *filename)
@@ -3560,8 +3715,8 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
3560
3715
  STARTUPINFOW si = {};
3561
3716
 
3562
3717
  // Convert command line
3563
- Span<wchar_t> cmd_line_w = AllocateMemory<wchar_t>(nullptr, 4 * strlen(cmd_line) + 2);
3564
- RG_DEFER { ReleaseMemory(nullptr, cmd_line_w.ptr, cmd_line_w.len); };
3718
+ Span<wchar_t> cmd_line_w = AllocateSpan<wchar_t>(nullptr, 2 * strlen(cmd_line) + 1);
3719
+ RG_DEFER { ReleaseSpan(nullptr, cmd_line_w); };
3565
3720
  if (ConvertUtf8ToWin32Wide(cmd_line, cmd_line_w) < 0)
3566
3721
  return false;
3567
3722
 
@@ -4008,7 +4163,7 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
4008
4163
  }
4009
4164
 
4010
4165
  // Try to read
4011
- if (out_revents & (POLLHUP | POLLERR)) {
4166
+ if (out_revents & POLLERR) {
4012
4167
  break;
4013
4168
  } else if (out_revents & POLLIN) {
4014
4169
  RG_ASSERT(out_func.IsValid());
@@ -4025,6 +4180,9 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
4025
4180
  LogError("Failed to read process output: %1", strerror(errno));
4026
4181
  break;
4027
4182
  }
4183
+ } else if (out_revents & POLLHUP) {
4184
+ // Only deal with this once POLLIN goes down to avoid truncated output
4185
+ break;
4028
4186
  }
4029
4187
 
4030
4188
  if (term_revents) {
@@ -4245,10 +4403,12 @@ int GetCoreCount()
4245
4403
  if (env) {
4246
4404
  char *end_ptr;
4247
4405
  long value = strtol(env, &end_ptr, 10);
4406
+
4248
4407
  if (end_ptr > env && !end_ptr[0] && value > 0) {
4249
4408
  cores = (int)value;
4250
4409
  } else {
4251
4410
  LogError("OVERRIDE_CORES must be positive number (ignored)");
4411
+ cores = (int)std::thread::hardware_concurrency();
4252
4412
  }
4253
4413
  } else {
4254
4414
  cores = (int)std::thread::hardware_concurrency();
@@ -4539,8 +4699,8 @@ const char *FindConfigFile(const char *name, Allocator *alloc, LocalArray<const
4539
4699
  return filename;
4540
4700
  }
4541
4701
 
4542
- static const char *CreateTemporaryPath(Span<const char> directory, const char *prefix, const char *extension,
4543
- 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)
4544
4704
  {
4545
4705
  RG_ASSERT(alloc);
4546
4706
 
@@ -4573,12 +4733,12 @@ static const char *CreateTemporaryPath(Span<const char> directory, const char *p
4573
4733
  return nullptr;
4574
4734
  }
4575
4735
 
4576
- const char *CreateTemporaryFile(Span<const char> directory, const char *prefix, const char *extension,
4577
- 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)
4578
4738
  {
4579
- return CreateTemporaryPath(directory, prefix, extension, alloc, [&](const char *path) {
4580
- int flags = (int)OpenFileFlag::Read | (int)OpenFileFlag::Write |
4581
- (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;
4582
4742
 
4583
4743
  FILE *fp = OpenFile(path, flags);
4584
4744
 
@@ -4596,9 +4756,9 @@ const char *CreateTemporaryFile(Span<const char> directory, const char *prefix,
4596
4756
  });
4597
4757
  }
4598
4758
 
4599
- 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)
4600
4760
  {
4601
- return CreateTemporaryPath(directory, prefix, "", alloc, [&](const char *path) {
4761
+ return CreateUniquePath(directory, prefix, "", alloc, [&](const char *path) {
4602
4762
  return MakeDirectory(path);
4603
4763
  });
4604
4764
  }
@@ -5080,6 +5240,9 @@ class AsyncPool {
5080
5240
  public:
5081
5241
  AsyncPool(int threads, bool leak);
5082
5242
 
5243
+ int GetWorkerCount() const { return (int)queues.len; }
5244
+ int CountPendingTasks() const { return pending_tasks; }
5245
+
5083
5246
  void RegisterAsync();
5084
5247
  void UnregisterAsync();
5085
5248
 
@@ -5124,9 +5287,18 @@ Async::Async(int threads, bool stop_after_error)
5124
5287
  pool->RegisterAsync();
5125
5288
  }
5126
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
+
5127
5299
  Async::~Async()
5128
5300
  {
5129
- RG_ASSERT(!remaining_tasks);
5301
+ Sync();
5130
5302
  pool->UnregisterAsync();
5131
5303
  }
5132
5304
 
@@ -5141,6 +5313,11 @@ bool Async::Sync()
5141
5313
  return success;
5142
5314
  }
5143
5315
 
5316
+ int Async::CountPendingTasks()
5317
+ {
5318
+ return pool->CountPendingTasks();
5319
+ }
5320
+
5144
5321
  bool Async::IsTaskRunning()
5145
5322
  {
5146
5323
  return async_running_task;
@@ -5151,6 +5328,11 @@ int Async::GetWorkerIdx()
5151
5328
  return async_running_worker_idx;
5152
5329
  }
5153
5330
 
5331
+ int Async::GetWorkerCount()
5332
+ {
5333
+ return async_running_pool->GetWorkerCount();
5334
+ }
5335
+
5154
5336
  AsyncPool::AsyncPool(int threads, bool leak)
5155
5337
  {
5156
5338
  if (threads > RG_ASYNC_MAX_THREADS) {
@@ -5444,7 +5626,7 @@ Fiber::~Fiber()
5444
5626
  fib_run = nullptr;
5445
5627
  }
5446
5628
 
5447
- ReleaseMemory(nullptr, ucp.uc_stack.ss_sp, (Size)ucp.uc_stack.ss_size);
5629
+ ReleaseRaw(nullptr, ucp.uc_stack.ss_sp, (Size)ucp.uc_stack.ss_size);
5448
5630
  }
5449
5631
 
5450
5632
  void Fiber::SwitchTo()
@@ -5637,6 +5819,7 @@ bool StreamReader::Open(Span<const uint8_t> buf, const char *filename,
5637
5819
 
5638
5820
  RG_DEFER_N(err_guard) { error = true; };
5639
5821
  error = false;
5822
+ raw_read = 0;
5640
5823
 
5641
5824
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<memory>";
5642
5825
 
@@ -5657,6 +5840,7 @@ bool StreamReader::Open(FILE *fp, const char *filename, CompressionType compress
5657
5840
 
5658
5841
  RG_DEFER_N(err_guard) { error = true; };
5659
5842
  error = false;
5843
+ raw_read = 0;
5660
5844
 
5661
5845
  RG_ASSERT(fp);
5662
5846
  RG_ASSERT(filename);
@@ -5673,27 +5857,30 @@ bool StreamReader::Open(FILE *fp, const char *filename, CompressionType compress
5673
5857
  return true;
5674
5858
  }
5675
5859
 
5676
- bool StreamReader::Open(const char *filename, CompressionType compression_type)
5860
+ OpenResult StreamReader::Open(const char *filename, CompressionType compression_type)
5677
5861
  {
5678
5862
  Close(true);
5679
5863
 
5680
5864
  RG_DEFER_N(err_guard) { error = true; };
5681
5865
  error = false;
5866
+ raw_read = 0;
5682
5867
 
5683
5868
  RG_ASSERT(filename);
5684
5869
  this->filename = DuplicateString(filename, &str_alloc).ptr;
5685
5870
 
5686
5871
  source.type = SourceType::File;
5687
- source.u.file.fp = OpenFile(filename, (int)OpenFileFlag::Read);
5688
- if (!source.u.file.fp)
5689
- return false;
5872
+ {
5873
+ OpenResult ret = OpenFile(filename, (int)OpenFlag::Read, &source.u.file.fp);
5874
+ if (ret != OpenResult::Success)
5875
+ return ret;
5876
+ }
5690
5877
  source.u.file.owned = true;
5691
5878
 
5692
5879
  if (!InitDecompressor(compression_type))
5693
- return false;
5880
+ return OpenResult::OtherError;
5694
5881
 
5695
5882
  err_guard.Disable();
5696
- return true;
5883
+ return OpenResult::Success;
5697
5884
  }
5698
5885
 
5699
5886
  bool StreamReader::Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
@@ -5703,6 +5890,7 @@ bool StreamReader::Open(const std::function<Size(Span<uint8_t>)> &func, const ch
5703
5890
 
5704
5891
  RG_DEFER_N(err_guard) { error = true; };
5705
5892
  error = false;
5893
+ raw_read = 0;
5706
5894
 
5707
5895
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<closure>";
5708
5896
 
@@ -5726,7 +5914,7 @@ bool StreamReader::Close(bool implicit)
5726
5914
  case CompressionType::Gzip:
5727
5915
  case CompressionType::Zlib: {
5728
5916
  #ifdef MZ_VERSION
5729
- ReleaseMemory(nullptr, compression.u.miniz, RG_SIZE(*compression.u.miniz));
5917
+ ReleaseOne(nullptr, compression.u.miniz);
5730
5918
  compression.u.miniz = nullptr;
5731
5919
  #else
5732
5920
  RG_UNREACHABLE();
@@ -5742,7 +5930,7 @@ bool StreamReader::Close(bool implicit)
5742
5930
  BrotliDecoderDestroyInstance(ctx->state);
5743
5931
  }
5744
5932
 
5745
- ReleaseMemory(nullptr, ctx, RG_SIZE(*ctx));
5933
+ ReleaseOne(nullptr, ctx);
5746
5934
  compression.u.brotli = nullptr;
5747
5935
  }
5748
5936
  #else
@@ -5773,7 +5961,6 @@ bool StreamReader::Close(bool implicit)
5773
5961
  source.eof = false;
5774
5962
  eof = false;
5775
5963
  raw_len = -1;
5776
- raw_read = 0;
5777
5964
  str_alloc.ReleaseAll();
5778
5965
 
5779
5966
  return ret;
@@ -5833,6 +6020,23 @@ bool StreamReader::Rewind()
5833
6020
  return true;
5834
6021
  }
5835
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
+
5836
6040
  Size StreamReader::Read(Span<uint8_t> out_buf)
5837
6041
  {
5838
6042
  if (RG_UNLIKELY(error))
@@ -5975,8 +6179,7 @@ bool StreamReader::InitDecompressor(CompressionType type)
5975
6179
  case CompressionType::Gzip:
5976
6180
  case CompressionType::Zlib: {
5977
6181
  #ifdef MZ_VERSION
5978
- compression.u.miniz =
5979
- AllocateMemory<MinizInflateContext>(nullptr, RG_SIZE(MinizInflateContext), (int)Allocator::Flag::Zero).ptr;
6182
+ compression.u.miniz = AllocateOne<MinizInflateContext>(nullptr, (int)AllocFlag::Zero);
5980
6183
  tinfl_init(&compression.u.miniz->inflator);
5981
6184
  compression.u.miniz->crc32 = MZ_CRC32_INIT;
5982
6185
  #else
@@ -5988,8 +6191,7 @@ bool StreamReader::InitDecompressor(CompressionType type)
5988
6191
 
5989
6192
  case CompressionType::Brotli: {
5990
6193
  #ifdef BROTLI_DEFAULT_MODE
5991
- compression.u.brotli =
5992
- AllocateMemory<BrotliDecompressContext>(nullptr, RG_SIZE(BrotliDecompressContext), (int)Allocator::Flag::Zero).ptr;
6194
+ compression.u.brotli = AllocateOne<BrotliDecompressContext>(nullptr, (int)AllocFlag::Zero);
5993
6195
  compression.u.brotli->state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
5994
6196
  #else
5995
6197
  LogError("Brotli decompression not available for '%1'", filename);
@@ -6338,6 +6540,7 @@ bool StreamWriter::Open(HeapArray<uint8_t> *mem, const char *filename,
6338
6540
 
6339
6541
  RG_DEFER_N(err_guard) { error = true; };
6340
6542
  error = false;
6543
+ raw_written = 0;
6341
6544
 
6342
6545
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<memory>";
6343
6546
 
@@ -6360,6 +6563,7 @@ bool StreamWriter::Open(FILE *fp, const char *filename,
6360
6563
 
6361
6564
  RG_DEFER_N(err_guard) { error = true; };
6362
6565
  error = false;
6566
+ raw_written = 0;
6363
6567
 
6364
6568
  RG_ASSERT(fp);
6365
6569
  RG_ASSERT(filename);
@@ -6384,6 +6588,7 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6384
6588
 
6385
6589
  RG_DEFER_N(err_guard) { error = true; };
6386
6590
  error = false;
6591
+ raw_written = 0;
6387
6592
 
6388
6593
  RG_ASSERT(filename);
6389
6594
  this->filename = DuplicateString(filename, &str_alloc).ptr;
@@ -6395,8 +6600,8 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6395
6600
  Span<const char> directory = GetPathDirectory(filename);
6396
6601
 
6397
6602
  if (flags & (int)StreamWriterFlag::Exclusive) {
6398
- FILE *fp = OpenFile(filename, (int)OpenFileFlag::Write |
6399
- (int)OpenFileFlag::Exclusive);
6603
+ FILE *fp = OpenFile(filename, (int)OpenFlag::Write |
6604
+ (int)OpenFlag::Exclusive);
6400
6605
  if (!fp)
6401
6606
  return false;
6402
6607
  fclose(fp);
@@ -6404,13 +6609,13 @@ bool StreamWriter::Open(const char *filename, unsigned int flags,
6404
6609
  dest.u.file.tmp_exclusive = true;
6405
6610
  }
6406
6611
 
6407
- 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);
6408
6613
  if (!dest.u.file.tmp_filename)
6409
6614
  return false;
6410
6615
  dest.u.file.owned = true;
6411
6616
  } else {
6412
- unsigned int open_flags = (int)OpenFileFlag::Write;
6413
- 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;
6414
6619
 
6415
6620
  dest.u.file.fp = OpenFile(filename, open_flags);
6416
6621
  if (!dest.u.file.fp)
@@ -6433,6 +6638,7 @@ bool StreamWriter::Open(const std::function<bool(Span<const uint8_t>)> &func, co
6433
6638
 
6434
6639
  RG_DEFER_N(err_guard) { error = true; };
6435
6640
  error = false;
6641
+ raw_written = 0;
6436
6642
 
6437
6643
  this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<closure>";
6438
6644
 
@@ -6454,13 +6660,37 @@ bool StreamWriter::Flush()
6454
6660
 
6455
6661
  switch (dest.type) {
6456
6662
  case DestinationType::Memory: return true;
6457
- 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;
6458
6671
  case DestinationType::Function: return true;
6459
6672
  }
6460
6673
 
6461
6674
  RG_UNREACHABLE();
6462
6675
  }
6463
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
+
6464
6694
  bool StreamWriter::Write(Span<const uint8_t> buf)
6465
6695
  {
6466
6696
  if (RG_UNLIKELY(error))
@@ -6527,7 +6757,7 @@ bool StreamWriter::Close(bool implicit)
6527
6757
  MinizDeflateContext *ctx = compression.u.miniz;
6528
6758
 
6529
6759
  RG_DEFER {
6530
- ReleaseMemory(nullptr, ctx, RG_SIZE(*ctx));
6760
+ ReleaseOne(nullptr, ctx);
6531
6761
  compression.u.miniz = nullptr;
6532
6762
  };
6533
6763
 
@@ -6600,21 +6830,23 @@ bool StreamWriter::Close(bool implicit)
6600
6830
  case DestinationType::Memory: { dest.u.mem = {}; } break;
6601
6831
 
6602
6832
  case DestinationType::File: {
6603
- if (IsValid() && !FlushFile(dest.u.file.fp, filename)) {
6604
- error = true;
6605
- }
6606
-
6607
6833
  if (dest.u.file.tmp_filename) {
6608
- if (IsValid() && implicit) {
6609
- LogDebug("Deleting implicitly closed file '%1'", filename);
6610
- 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
+ }
6611
6841
  }
6612
6842
 
6613
6843
  if (IsValid()) {
6614
6844
  fclose(dest.u.file.fp);
6615
6845
  dest.u.file.owned = false;
6616
6846
 
6617
- 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)) {
6618
6850
  dest.u.file.tmp_filename = nullptr;
6619
6851
  dest.u.file.tmp_exclusive = false;
6620
6852
  } else {
@@ -6665,8 +6897,7 @@ bool StreamWriter::InitCompressor(CompressionType type, CompressionSpeed speed)
6665
6897
  case CompressionType::Gzip:
6666
6898
  case CompressionType::Zlib: {
6667
6899
  #ifdef MZ_VERSION
6668
- compression.u.miniz =
6669
- AllocateMemory<MinizDeflateContext>(nullptr, RG_SIZE(MinizDeflateContext), (int)Allocator::Flag::Zero).ptr;
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)
@@ -7033,7 +7267,7 @@ bool ReloadAssets()
7033
7267
  AssetInfo asset_copy;
7034
7268
 
7035
7269
  asset_copy.name = DuplicateString(asset.name, &assets_alloc).ptr;
7036
- asset_copy.data = AllocateMemory<uint8_t>(&assets_alloc, asset.data.len);
7270
+ asset_copy.data = AllocateSpan<uint8_t>(&assets_alloc, asset.data.len);
7037
7271
  memcpy_safe((void *)asset_copy.data.ptr, asset.data.ptr, (size_t)asset.data.len);
7038
7272
  asset_copy.compression_type = asset.compression_type;
7039
7273
  asset_copy.source_map = DuplicateString(asset.source_map, &assets_alloc).ptr;