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.
- package/ChangeLog.md +13 -1
- 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/call.cc +2 -2
- package/src/call.hh +1 -1
- package/src/ffi.hh +1 -1
- package/src/util.hh +6 -0
- package/test/raylib.js +37 -5
- package/vendor/libcc/libcc.cc +488 -254
- package/vendor/libcc/libcc.hh +1463 -1277
- 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.0/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/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,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)
|
|
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
|
|
143
|
+
void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags) override
|
|
152
144
|
{
|
|
153
145
|
if (!new_size) {
|
|
154
|
-
Release(
|
|
155
|
-
|
|
146
|
+
Release(ptr, old_size);
|
|
147
|
+
ptr = nullptr;
|
|
156
148
|
} else {
|
|
157
|
-
void *new_ptr = realloc(
|
|
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)
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
227
|
+
void *LinkedAllocator::Resize(void *ptr, Size old_size, Size new_size, unsigned int flags)
|
|
239
228
|
{
|
|
240
|
-
if (
|
|
241
|
-
|
|
229
|
+
if (!ptr) {
|
|
230
|
+
ptr = Allocate(new_size, flags);
|
|
242
231
|
} else if (!new_size) {
|
|
243
|
-
Release(
|
|
244
|
-
|
|
232
|
+
Release(ptr, old_size);
|
|
233
|
+
ptr = nullptr;
|
|
245
234
|
} else {
|
|
246
|
-
Bucket *bucket = PointerToBucket(
|
|
235
|
+
Bucket *bucket = PointerToBucket(ptr);
|
|
247
236
|
|
|
248
|
-
bucket =
|
|
249
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
306
|
-
|
|
307
|
-
current_bucket->used =
|
|
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)
|
|
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
|
|
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(
|
|
320
|
+
Release(ptr, old_size);
|
|
321
|
+
ptr = nullptr;
|
|
331
322
|
} else {
|
|
332
|
-
if (
|
|
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 (
|
|
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)
|
|
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 =
|
|
342
|
+
ptr = ResizeRaw(alloc, ptr, old_size, new_size, flags);
|
|
352
343
|
} else {
|
|
353
|
-
void *new_ptr = Allocate(new_size, flags & ~(int)
|
|
344
|
+
void *new_ptr = Allocate(new_size, flags & ~(int)AllocFlag::Zero);
|
|
354
345
|
if (new_size > old_size) {
|
|
355
|
-
memcpy_safe(new_ptr,
|
|
346
|
+
memcpy_safe(new_ptr, ptr, old_size);
|
|
356
347
|
|
|
357
|
-
if (flags & (int)
|
|
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,
|
|
352
|
+
memcpy_safe(new_ptr, ptr, new_size);
|
|
362
353
|
}
|
|
363
354
|
|
|
364
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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>
|
|
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::
|
|
1139
|
-
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);
|
|
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
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
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(
|
|
1255
|
-
FmtArg(
|
|
1256
|
-
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),
|
|
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(
|
|
1261
|
-
FmtArg(
|
|
1262
|
-
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;
|
|
1263
1292
|
}
|
|
1264
1293
|
out = out_buf;
|
|
1265
1294
|
} break;
|
|
1266
1295
|
case FmtType::TimeNice: {
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
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
|
-
|
|
1318
|
+
static const char *const DefaultChars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1319
|
+
Span<const char> chars = arg.u.random.chars ? arg.u.random.chars : DefaultChars;
|
|
1280
1320
|
|
|
1281
|
-
|
|
1282
|
-
static const char *chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1321
|
+
RG_ASSERT(arg.u.random.len <= RG_SIZE(out_buf.data));
|
|
1283
1322
|
|
|
1284
|
-
|
|
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::
|
|
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 = *(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
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
|
|
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
|
|
2136
|
+
return StatResult::Success;
|
|
2068
2137
|
}
|
|
2069
2138
|
|
|
2070
|
-
bool RenameFile(const char *src_filename, const char *dest_filename,
|
|
2139
|
+
bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
|
|
2071
2140
|
{
|
|
2072
|
-
DWORD
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
2179
|
+
return EnumResult::OtherError;
|
|
2111
2180
|
}
|
|
2112
2181
|
|
|
2113
2182
|
if (ConvertUtf8ToWin32Wide(find_filter, find_filter_w) < 0)
|
|
2114
|
-
return
|
|
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
|
-
|
|
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
|
|
2202
|
+
return EnumResult::Success;
|
|
2132
2203
|
}
|
|
2133
2204
|
|
|
2134
|
-
LogError("Cannot enumerate directory '%1': %2", dirname,
|
|
2135
|
-
|
|
2136
|
-
|
|
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
|
|
2224
|
+
return EnumResult::PartialEnum;
|
|
2149
2225
|
}
|
|
2150
2226
|
|
|
2151
2227
|
char filename[512];
|
|
2152
2228
|
if (ConvertWin32WideToUtf8(find_data.cFileName, filename) < 0)
|
|
2153
|
-
return
|
|
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
|
|
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
|
|
2240
|
+
return EnumResult::OtherError;
|
|
2165
2241
|
}
|
|
2166
2242
|
|
|
2167
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
2213
|
-
|
|
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
|
|
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,
|
|
2349
|
+
bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags)
|
|
2261
2350
|
{
|
|
2262
2351
|
int fd = -1;
|
|
2263
|
-
if (!
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
2450
|
+
return EnumResult::OtherError;
|
|
2357
2451
|
}
|
|
2358
2452
|
|
|
2359
|
-
return
|
|
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
|
-
|
|
2370
|
-
|
|
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 (
|
|
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
|
-
|
|
2405
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
2973
|
-
(int)
|
|
2974
|
-
(int)
|
|
2975
|
-
case (int)
|
|
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)
|
|
3083
|
+
case (int)OpenFlag::Write: {
|
|
2983
3084
|
access = GENERIC_WRITE;
|
|
2984
3085
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
2985
|
-
creation = (flags & (int)
|
|
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)
|
|
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)
|
|
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)
|
|
3097
|
+
case (int)OpenFlag::Append: {
|
|
2997
3098
|
access = GENERIC_WRITE;
|
|
2998
3099
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
2999
|
-
creation = (flags & (int)
|
|
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)
|
|
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
|
|
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
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
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
|
-
|
|
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
|
|
3145
|
+
return OpenResult::OtherError;
|
|
3039
3146
|
}
|
|
3040
3147
|
|
|
3041
|
-
|
|
3148
|
+
*out_fd = fd;
|
|
3149
|
+
return OpenResult::Success;
|
|
3042
3150
|
}
|
|
3043
3151
|
|
|
3044
|
-
|
|
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)
|
|
3048
|
-
(int)
|
|
3049
|
-
(int)
|
|
3050
|
-
case (int)
|
|
3051
|
-
case (int)
|
|
3052
|
-
case (int)
|
|
3053
|
-
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;
|
|
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 =
|
|
3063
|
-
|
|
3064
|
-
|
|
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
|
|
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
|
-
|
|
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)
|
|
3276
|
-
(int)
|
|
3277
|
-
(int)
|
|
3278
|
-
case (int)
|
|
3279
|
-
case (int)
|
|
3280
|
-
case (int)
|
|
3281
|
-
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;
|
|
3282
3410
|
}
|
|
3283
3411
|
RG_ASSERT(oflags >= 0);
|
|
3284
3412
|
|
|
3285
|
-
if (flags & (int)
|
|
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
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
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
|
|
3430
|
+
return ret;
|
|
3297
3431
|
}
|
|
3298
3432
|
|
|
3299
|
-
|
|
3433
|
+
*out_fd = fd;
|
|
3434
|
+
return OpenResult::Success;
|
|
3300
3435
|
}
|
|
3301
3436
|
|
|
3302
|
-
|
|
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)
|
|
3306
|
-
(int)
|
|
3307
|
-
(int)
|
|
3308
|
-
case (int)
|
|
3309
|
-
case (int)
|
|
3310
|
-
case (int)
|
|
3311
|
-
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;
|
|
3312
3447
|
}
|
|
3313
3448
|
RG_ASSERT(mode);
|
|
3314
3449
|
|
|
3315
|
-
int fd =
|
|
3316
|
-
|
|
3317
|
-
|
|
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
|
-
|
|
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 =
|
|
3564
|
-
RG_DEFER {
|
|
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 &
|
|
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 *
|
|
4543
|
-
|
|
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 *
|
|
4577
|
-
|
|
4736
|
+
const char *CreateUniqueFile(Span<const char> directory, const char *prefix, const char *extension,
|
|
4737
|
+
Allocator *alloc, FILE **out_fp)
|
|
4578
4738
|
{
|
|
4579
|
-
return
|
|
4580
|
-
int flags = (int)
|
|
4581
|
-
(int)
|
|
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 *
|
|
4759
|
+
const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix, Allocator *alloc)
|
|
4600
4760
|
{
|
|
4601
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
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
|
|
5880
|
+
return OpenResult::OtherError;
|
|
5694
5881
|
|
|
5695
5882
|
err_guard.Disable();
|
|
5696
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
6399
|
-
(int)
|
|
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 =
|
|
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)
|
|
6413
|
-
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;
|
|
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:
|
|
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
|
-
|
|
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()
|
|
6609
|
-
|
|
6610
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
@@ -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 =
|
|
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;
|