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.
- package/ChangeLog.md +6 -0
- package/build/qemu/2.1.2/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_x64.tar.gz +0 -0
- package/doc/templates/badges.html +3 -0
- package/package.json +2 -2
- package/src/abi_arm64.cc +35 -1
- package/src/abi_x64_win.cc +2 -8
- package/src/abi_x86.cc +1 -7
- package/src/ffi.hh +1 -1
- package/src/util.hh +6 -0
- package/test/raylib.js +37 -5
- package/vendor/libcc/libcc.cc +430 -196
- package/vendor/libcc/libcc.hh +1417 -1283
- package/vendor/raylib/BINDINGS.md +87 -70
- package/vendor/raylib/CHANGELOG +263 -50
- package/vendor/raylib/CMakeLists.txt +12 -0
- package/vendor/raylib/CMakeOptions.txt +8 -1
- package/vendor/raylib/CONVENTIONS.md +2 -3
- package/vendor/raylib/FAQ.md +137 -0
- package/vendor/raylib/HISTORY.md +62 -29
- package/vendor/raylib/LICENSE +1 -1
- package/vendor/raylib/README.md +22 -17
- package/vendor/raylib/ROADMAP.md +8 -7
- package/vendor/raylib/cmake/CompileDefinitions.cmake +19 -15
- package/vendor/raylib/cmake/GlfwImport.cmake +2 -0
- package/vendor/raylib/cmake/LibraryConfigurations.cmake +22 -16
- package/vendor/raylib/cmake/raylib-config.cmake +52 -49
- package/vendor/raylib/examples/CMakeLists.txt +14 -9
- package/vendor/raylib/examples/Makefile +112 -125
- package/vendor/raylib/examples/Makefile.Android +1 -1
- package/vendor/raylib/examples/Makefile.Web +145 -158
- package/vendor/raylib/examples/README.md +141 -141
- package/vendor/raylib/examples/audio/audio_module_playing.c +9 -4
- package/vendor/raylib/examples/audio/audio_multichannel_sound.c +8 -3
- package/vendor/raylib/examples/audio/audio_music_stream.c +16 -11
- package/vendor/raylib/examples/audio/audio_raw_stream.c +57 -9
- package/vendor/raylib/examples/audio/audio_sound_loading.c +8 -3
- package/vendor/raylib/examples/audio/audio_stream_effects.c +179 -0
- package/vendor/raylib/examples/audio/audio_stream_effects.png +0 -0
- package/vendor/raylib/examples/build.zig +17 -6
- package/vendor/raylib/examples/core/core_2d_camera.c +8 -4
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.c +105 -0
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.png +0 -0
- package/vendor/raylib/examples/core/core_2d_camera_platformer.c +11 -6
- package/vendor/raylib/examples/core/core_3d_camera_first_person.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_free.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_mode.c +8 -3
- package/vendor/raylib/examples/core/core_3d_picking.c +9 -4
- package/vendor/raylib/examples/core/core_basic_screen_manager.c +9 -7
- package/vendor/raylib/examples/core/core_basic_window.c +8 -3
- package/vendor/raylib/examples/core/core_basic_window_web.c +13 -11
- package/vendor/raylib/examples/core/core_custom_frame_control.c +9 -4
- package/vendor/raylib/examples/core/core_custom_logging.c +12 -8
- package/vendor/raylib/examples/core/core_drop_files.c +20 -12
- package/vendor/raylib/examples/core/core_input_gamepad.c +20 -15
- package/vendor/raylib/examples/core/core_input_gestures.c +19 -15
- package/vendor/raylib/examples/core/core_input_keys.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse_wheel.c +8 -3
- package/vendor/raylib/examples/core/core_input_multitouch.c +8 -3
- package/vendor/raylib/examples/core/core_loading_thread.c +10 -6
- package/vendor/raylib/examples/core/core_random_values.c +8 -3
- package/vendor/raylib/examples/core/core_scissor_test.c +8 -3
- package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +9 -4
- package/vendor/raylib/examples/core/core_split_screen.c +8 -3
- package/vendor/raylib/examples/core/core_storage_values.c +109 -3
- package/vendor/raylib/examples/core/core_vr_simulator.c +15 -7
- package/vendor/raylib/examples/core/core_window_flags.c +8 -3
- package/vendor/raylib/examples/core/core_window_letterbox.c +13 -18
- package/vendor/raylib/examples/core/core_window_should_close.c +77 -0
- package/vendor/raylib/examples/core/core_window_should_close.png +0 -0
- package/vendor/raylib/examples/core/core_world_screen.c +9 -4
- package/vendor/raylib/examples/examples_template.c +8 -3
- package/vendor/raylib/examples/models/models_animation.c +11 -7
- package/vendor/raylib/examples/models/models_billboard.c +9 -4
- package/vendor/raylib/examples/models/models_box_collisions.c +8 -3
- package/vendor/raylib/examples/models/models_cubicmap.c +9 -4
- package/vendor/raylib/examples/models/models_first_person_maze.c +9 -4
- package/vendor/raylib/examples/models/models_geometric_shapes.c +8 -3
- package/vendor/raylib/examples/models/models_heightmap.c +9 -4
- package/vendor/raylib/examples/models/models_loading.c +21 -17
- package/vendor/raylib/examples/models/models_loading_gltf.c +15 -41
- package/vendor/raylib/examples/models/models_loading_vox.c +9 -4
- package/vendor/raylib/examples/models/models_mesh_generation.c +71 -58
- package/vendor/raylib/examples/models/models_mesh_picking.c +25 -7
- package/vendor/raylib/examples/models/models_orthographic_projection.c +8 -5
- package/vendor/raylib/examples/models/models_rlgl_solar_system.c +6 -4
- package/vendor/raylib/examples/models/models_skybox.c +16 -12
- package/vendor/raylib/examples/models/models_waving_cubes.c +9 -4
- package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +12 -7
- package/vendor/raylib/examples/models/resources/LICENSE.md +9 -10
- package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +2 -23
- package/vendor/raylib/examples/models/resources/models/gltf/{raylib_32x32.glb → raylib_logo_3d.glb} +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.blend +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.glb +0 -0
- package/vendor/raylib/examples/others/easings_testbed.c +10 -8
- package/vendor/raylib/examples/others/easings_testbed.png +0 -0
- package/vendor/raylib/examples/others/embedded_files_loading.c +10 -5
- package/vendor/raylib/examples/others/embedded_files_loading.png +0 -0
- package/vendor/raylib/examples/others/raylib_opengl_interop.c +10 -6
- package/vendor/raylib/{src/extras/easings.h → examples/others/reasings.h} +38 -38
- package/vendor/raylib/examples/others/rlgl_compute_shader.c +21 -20
- package/vendor/raylib/examples/others/rlgl_compute_shader.png +0 -0
- package/vendor/raylib/examples/others/rlgl_standalone.c +4 -4
- package/vendor/raylib/examples/others/rlgl_standalone.png +0 -0
- package/vendor/raylib/examples/raylib_compile_execute.bat +2 -2
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +1 -1
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/{base_lighting_instanced.vs → lighting_instancing.vs} +2 -2
- package/vendor/raylib/examples/shaders/rlights.h +14 -27
- package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +24 -26
- package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +13 -8
- package/vendor/raylib/examples/shaders/shaders_fog.c +8 -12
- package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_julia_set.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +45 -119
- package/vendor/raylib/examples/shaders/shaders_model_shader.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_palette_switch.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_postprocessing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_raymarching.c +14 -11
- package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_simple_mask.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_spotlight.c +10 -6
- package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_texture_outline.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_texture_waves.c +8 -3
- package/vendor/raylib/{src/extras → examples/shapes}/raygui.h +1290 -1141
- package/vendor/raylib/examples/{others/easings.h → shapes/reasings.h} +40 -40
- package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_collision_area.c +10 -4
- package/vendor/raylib/examples/shapes/shapes_colors_palette.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_ring.c +10 -6
- package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_following_eyes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +14 -5
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.c +355 -0
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.png +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular.ttf +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular_OFL.txt +93 -0
- package/vendor/raylib/examples/text/resources/LICENSE.md +1 -1
- package/vendor/raylib/examples/text/text_codepoints_loading.c +138 -0
- package/vendor/raylib/examples/text/text_codepoints_loading.png +0 -0
- package/vendor/raylib/examples/text/text_draw_3d.c +42 -33
- package/vendor/raylib/examples/text/text_font_filters.c +14 -11
- package/vendor/raylib/examples/text/text_font_loading.c +9 -4
- package/vendor/raylib/examples/text/text_font_sdf.c +9 -4
- package/vendor/raylib/examples/text/text_font_spritefont.c +12 -6
- package/vendor/raylib/examples/text/text_format_text.c +8 -3
- package/vendor/raylib/examples/text/text_input_box.c +8 -3
- package/vendor/raylib/examples/text/text_raylib_fonts.c +9 -4
- package/vendor/raylib/examples/text/text_rectangle_bounds.c +9 -5
- package/vendor/raylib/examples/text/text_unicode.c +9 -7
- package/vendor/raylib/examples/text/text_writing_anim.c +8 -3
- package/vendor/raylib/examples/textures/resources/scarfy_run.gif +0 -0
- package/vendor/raylib/examples/textures/textures_background_scrolling.c +8 -3
- package/vendor/raylib/examples/textures/textures_blend_modes.c +8 -3
- package/vendor/raylib/examples/textures/textures_bunnymark.c +8 -3
- package/vendor/raylib/examples/textures/textures_draw_tiled.c +14 -10
- package/vendor/raylib/examples/textures/textures_fog_of_war.c +154 -0
- package/vendor/raylib/examples/textures/textures_fog_of_war.png +0 -0
- package/vendor/raylib/examples/textures/textures_gif_player.c +121 -0
- package/vendor/raylib/examples/textures/textures_gif_player.png +0 -0
- package/vendor/raylib/examples/textures/textures_image_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_generation.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_loading.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_processing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_text.c +8 -3
- package/vendor/raylib/examples/textures/textures_logo_raylib.c +8 -3
- package/vendor/raylib/examples/textures/textures_mouse_painting.c +9 -4
- package/vendor/raylib/examples/textures/textures_npatch_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_particles_blending.c +8 -3
- package/vendor/raylib/examples/textures/textures_polygon.c +9 -5
- package/vendor/raylib/examples/textures/textures_raw_data.c +8 -3
- package/vendor/raylib/examples/textures/{textures_rectangle.c → textures_sprite_anim.c} +11 -5
- package/vendor/raylib/examples/textures/{textures_rectangle.png → textures_sprite_anim.png} +0 -0
- package/vendor/raylib/examples/textures/textures_sprite_button.c +8 -3
- package/vendor/raylib/examples/textures/textures_sprite_explosion.c +8 -3
- package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +8 -3
- package/vendor/raylib/examples/textures/textures_to_image.c +8 -3
- package/vendor/raylib/parser/LICENSE +1 -1
- package/vendor/raylib/parser/Makefile +28 -0
- package/vendor/raylib/parser/README.md +49 -5
- package/vendor/raylib/parser/output/raylib_api.json +10717 -0
- package/vendor/raylib/parser/output/raylib_api.lua +7435 -0
- package/vendor/raylib/parser/{raylib_api.txt → output/raylib_api.txt} +1371 -824
- package/vendor/raylib/parser/{raylib_api.xml → output/raylib_api.xml} +827 -595
- package/vendor/raylib/parser/raylib_parser.c +1174 -196
- package/vendor/raylib/projects/4coder/Makefile +2 -4
- package/vendor/raylib/projects/4coder/main.c +0 -1
- package/vendor/raylib/projects/CMake/CMakeLists.txt +13 -16
- package/vendor/raylib/projects/CMake/README.md +27 -0
- package/vendor/raylib/projects/CMake/core_basic_window.c +52 -31
- package/vendor/raylib/projects/CodeBlocks/README.md +4 -4
- package/vendor/raylib/projects/Geany/core_basic_window.c +1 -1
- package/vendor/raylib/projects/Notepad++/c_raylib.xml +168 -128
- package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +168 -84
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +67 -51
- package/vendor/raylib/projects/README.md +1 -1
- package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +1 -1
- package/vendor/raylib/projects/VSCode/Makefile +8 -11
- package/vendor/raylib/projects/VSCode/main.c +53 -26
- package/vendor/raylib/projects/VSCode/resources/LICENSE +1 -0
- package/vendor/raylib/projects/scripts/build-linux.sh +6 -6
- package/vendor/raylib/projects/scripts/build-osx.sh +6 -6
- package/vendor/raylib/projects/scripts/build-rpi.sh +6 -6
- package/vendor/raylib/projects/scripts/build-windows.bat +2 -2
- package/vendor/raylib/src/CMakeLists.txt +6 -7
- package/vendor/raylib/src/Makefile +209 -103
- package/vendor/raylib/src/build.zig +56 -20
- package/vendor/raylib/src/config.h +32 -27
- package/vendor/raylib/src/external/cgltf.h +342 -104
- package/vendor/raylib/src/external/dr_wav.h +487 -225
- package/vendor/raylib/src/external/glfw/src/posix_time.c +1 -3
- package/vendor/raylib/src/external/glfw/src/wl_init.c +1 -3
- package/vendor/raylib/src/external/jar_xm.h +2 -1
- package/vendor/raylib/src/external/miniaudio.h +62251 -42061
- package/vendor/raylib/src/external/qoi.h +671 -0
- package/vendor/raylib/src/external/stb_vorbis.h +1 -1
- package/vendor/raylib/src/external/vox_loader.h +30 -25
- package/vendor/raylib/src/minshell.html +82 -0
- package/vendor/raylib/src/raudio.c +359 -201
- package/vendor/raylib/src/raylib.dll.rc +5 -5
- package/vendor/raylib/src/raylib.dll.rc.data +0 -0
- package/vendor/raylib/src/raylib.h +95 -63
- package/vendor/raylib/src/raylib.rc +5 -5
- package/vendor/raylib/src/raylib.rc.data +0 -0
- package/vendor/raylib/src/raymath.h +391 -133
- package/vendor/raylib/src/rcamera.h +32 -41
- package/vendor/raylib/src/rcore.c +775 -471
- package/vendor/raylib/src/rgestures.h +5 -5
- package/vendor/raylib/src/rglfw.c +3 -3
- package/vendor/raylib/src/rlgl.h +184 -144
- package/vendor/raylib/src/rmodels.c +207 -144
- package/vendor/raylib/src/rshapes.c +105 -47
- package/vendor/raylib/src/rtext.c +255 -38
- package/vendor/raylib/src/rtextures.c +167 -71
- package/vendor/raylib/src/shell.html +63 -63
- package/vendor/raylib/src/utils.c +49 -3
- package/vendor/raylib/src/utils.h +3 -3
- package/build/qemu/2.1.1/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_x64.tar.gz +0 -0
- package/vendor/raylib/CONTRIBUTORS.md +0 -63
- package/vendor/raylib/SPONSORS.md +0 -68
- package/vendor/raylib/examples/core/core_quat_conversion.c +0 -132
- package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +0 -118
- package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
- package/vendor/raylib/examples/models/rlights.h +0 -183
- package/vendor/raylib/examples/others/raudio_standalone.c +0 -152
- package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
- package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
- package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
- package/vendor/raylib/examples/physics/physics_demo.c +0 -128
- package/vendor/raylib/examples/physics/physics_demo.png +0 -0
- package/vendor/raylib/examples/physics/physics_friction.c +0 -142
- package/vendor/raylib/examples/physics/physics_friction.png +0 -0
- package/vendor/raylib/examples/physics/physics_movement.c +0 -128
- package/vendor/raylib/examples/physics/physics_movement.png +0 -0
- package/vendor/raylib/examples/physics/physics_restitution.c +0 -129
- package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
- package/vendor/raylib/examples/physics/physics_shatter.c +0 -111
- package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
- package/vendor/raylib/parser/raylib_api.json +0 -6668
- package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
- package/vendor/raylib/projects/VS2019/raylib/resource.h +0 -14
- package/vendor/raylib/src/extras/physac.h +0 -1977
- package/vendor/raylib/src/extras/rmem.h +0 -751
- package/vendor/raylib/src/raudio.h +0 -198
package/vendor/libcc/libcc.cc
CHANGED
|
@@ -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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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
|
|
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>
|
|
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::
|
|
1142
|
-
out =
|
|
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
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
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(
|
|
1258
|
-
FmtArg(
|
|
1259
|
-
FmtArg(
|
|
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(
|
|
1264
|
-
FmtArg(
|
|
1265
|
-
FmtArg(
|
|
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
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
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
|
-
|
|
1318
|
+
static const char *const DefaultChars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1319
|
+
Span<const char> chars = arg.u.random.chars ? arg.u.random.chars : DefaultChars;
|
|
1283
1320
|
|
|
1284
|
-
|
|
1285
|
-
static const char *chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1321
|
+
RG_ASSERT(arg.u.random.len <= RG_SIZE(out_buf.data));
|
|
1286
1322
|
|
|
1287
|
-
|
|
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::
|
|
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 = *(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
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
|
|
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
|
|
2136
|
+
return StatResult::Success;
|
|
2071
2137
|
}
|
|
2072
2138
|
|
|
2073
|
-
bool RenameFile(const char *src_filename, const char *dest_filename,
|
|
2139
|
+
bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
|
|
2074
2140
|
{
|
|
2075
|
-
DWORD
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
2179
|
+
return EnumResult::OtherError;
|
|
2114
2180
|
}
|
|
2115
2181
|
|
|
2116
2182
|
if (ConvertUtf8ToWin32Wide(find_filter, find_filter_w) < 0)
|
|
2117
|
-
return
|
|
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
|
-
|
|
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
|
|
2202
|
+
return EnumResult::Success;
|
|
2135
2203
|
}
|
|
2136
2204
|
|
|
2137
|
-
LogError("Cannot enumerate directory '%1': %2", dirname,
|
|
2138
|
-
|
|
2139
|
-
|
|
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
|
|
2224
|
+
return EnumResult::PartialEnum;
|
|
2152
2225
|
}
|
|
2153
2226
|
|
|
2154
2227
|
char filename[512];
|
|
2155
2228
|
if (ConvertWin32WideToUtf8(find_data.cFileName, filename) < 0)
|
|
2156
|
-
return
|
|
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
|
|
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
|
|
2240
|
+
return EnumResult::OtherError;
|
|
2168
2241
|
}
|
|
2169
2242
|
|
|
2170
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
2216
|
-
|
|
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
|
|
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,
|
|
2349
|
+
bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
|
|
2264
2350
|
{
|
|
2265
2351
|
int fd = -1;
|
|
2266
|
-
if (!
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
2450
|
+
return EnumResult::OtherError;
|
|
2360
2451
|
}
|
|
2361
2452
|
|
|
2362
|
-
return
|
|
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
|
-
|
|
2373
|
-
|
|
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 (
|
|
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
|
-
|
|
2408
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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)
|
|
2976
|
-
(int)
|
|
2977
|
-
(int)
|
|
2978
|
-
case (int)
|
|
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)
|
|
3083
|
+
case (int)OpenFlag::Write: {
|
|
2986
3084
|
access = GENERIC_WRITE;
|
|
2987
3085
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
2988
|
-
creation = (flags & (int)
|
|
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)
|
|
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)
|
|
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)
|
|
3097
|
+
case (int)OpenFlag::Append: {
|
|
3000
3098
|
access = GENERIC_WRITE;
|
|
3001
3099
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
3002
|
-
creation = (flags & (int)
|
|
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)
|
|
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
|
|
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
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
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
|
-
|
|
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
|
|
3145
|
+
return OpenResult::OtherError;
|
|
3042
3146
|
}
|
|
3043
3147
|
|
|
3044
|
-
|
|
3148
|
+
*out_fd = fd;
|
|
3149
|
+
return OpenResult::Success;
|
|
3045
3150
|
}
|
|
3046
3151
|
|
|
3047
|
-
|
|
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)
|
|
3051
|
-
(int)
|
|
3052
|
-
(int)
|
|
3053
|
-
case (int)
|
|
3054
|
-
case (int)
|
|
3055
|
-
case (int)
|
|
3056
|
-
case (int)
|
|
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 =
|
|
3066
|
-
|
|
3067
|
-
|
|
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
|
|
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
|
-
|
|
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)
|
|
3279
|
-
(int)
|
|
3280
|
-
(int)
|
|
3281
|
-
case (int)
|
|
3282
|
-
case (int)
|
|
3283
|
-
case (int)
|
|
3284
|
-
case (int)
|
|
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)
|
|
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
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
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
|
|
3430
|
+
return ret;
|
|
3300
3431
|
}
|
|
3301
3432
|
|
|
3302
|
-
|
|
3433
|
+
*out_fd = fd;
|
|
3434
|
+
return OpenResult::Success;
|
|
3303
3435
|
}
|
|
3304
3436
|
|
|
3305
|
-
|
|
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)
|
|
3309
|
-
(int)
|
|
3310
|
-
(int)
|
|
3311
|
-
case (int)
|
|
3312
|
-
case (int)
|
|
3313
|
-
case (int)
|
|
3314
|
-
case (int)
|
|
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 =
|
|
3319
|
-
|
|
3320
|
-
|
|
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
|
-
|
|
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 &
|
|
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 *
|
|
4546
|
-
|
|
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 *
|
|
4580
|
-
|
|
4736
|
+
const char *CreateUniqueFile(Span<const char> directory, const char *prefix, const char *extension,
|
|
4737
|
+
Allocator *alloc, FILE **out_fp)
|
|
4581
4738
|
{
|
|
4582
|
-
return
|
|
4583
|
-
int flags = (int)
|
|
4584
|
-
(int)
|
|
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 *
|
|
4759
|
+
const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix, Allocator *alloc)
|
|
4603
4760
|
{
|
|
4604
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
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
|
|
5880
|
+
return OpenResult::OtherError;
|
|
5697
5881
|
|
|
5698
5882
|
err_guard.Disable();
|
|
5699
|
-
return
|
|
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)
|
|
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)
|
|
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)
|
|
6400
|
-
(int)
|
|
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 =
|
|
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)
|
|
6414
|
-
open_flags |= (flags & (int)StreamWriterFlag::Exclusive) ? (int)
|
|
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:
|
|
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()
|
|
6610
|
-
|
|
6611
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
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
|
-
|
|
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 (
|
|
7220
|
+
if (StatFile(assets_filename, &file_info) != StatResult::Success)
|
|
6987
7221
|
return false;
|
|
6988
7222
|
|
|
6989
7223
|
if (assets_last_check == file_info.mtime)
|