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.hh
CHANGED
|
@@ -84,7 +84,7 @@ namespace RG {
|
|
|
84
84
|
|
|
85
85
|
#define RG_LINE_READER_STEP_SIZE 65536
|
|
86
86
|
|
|
87
|
-
#define RG_ASYNC_MAX_THREADS
|
|
87
|
+
#define RG_ASYNC_MAX_THREADS 2048
|
|
88
88
|
#define RG_ASYNC_MAX_IDLE_TIME 10000
|
|
89
89
|
#define RG_FIBER_DEFAULT_STACK_SIZE Kibibytes(128)
|
|
90
90
|
|
|
@@ -622,7 +622,7 @@ T ApplyMask(T value, U mask, bool enable)
|
|
|
622
622
|
if (enable) {
|
|
623
623
|
return value | (T)mask;
|
|
624
624
|
} else {
|
|
625
|
-
return value & (T)
|
|
625
|
+
return value & ~(T)mask;
|
|
626
626
|
}
|
|
627
627
|
}
|
|
628
628
|
|
|
@@ -824,21 +824,21 @@ static inline constexpr Strider<T> MakeStrider(T (&arr)[N])
|
|
|
824
824
|
return Strider<T>(arr, RG_SIZE(T));
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
+
enum class AllocFlag {
|
|
828
|
+
Zero = 1,
|
|
829
|
+
Resizable = 2
|
|
830
|
+
};
|
|
831
|
+
|
|
827
832
|
class Allocator {
|
|
828
833
|
RG_DELETE_COPY(Allocator)
|
|
829
834
|
|
|
830
835
|
public:
|
|
831
|
-
enum class Flag {
|
|
832
|
-
Zero = 1,
|
|
833
|
-
Resizable = 2
|
|
834
|
-
};
|
|
835
|
-
|
|
836
836
|
Allocator() = default;
|
|
837
837
|
virtual ~Allocator() = default;
|
|
838
838
|
|
|
839
839
|
virtual void *Allocate(Size size, unsigned int flags = 0) = 0;
|
|
840
840
|
virtual void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) = 0;
|
|
841
|
-
virtual void Release(void *ptr, Size size) = 0;
|
|
841
|
+
virtual void Release(const void *ptr, Size size) = 0;
|
|
842
842
|
};
|
|
843
843
|
|
|
844
844
|
Allocator *GetDefaultAllocator();
|
|
@@ -899,7 +899,7 @@ static inline void *ResizeRaw(Allocator *alloc, void *ptr, Size old_size, Size n
|
|
|
899
899
|
|
|
900
900
|
template <typename T>
|
|
901
901
|
Span<T> ResizeSpan(Allocator *alloc, Span<T> mem, Size new_len,
|
|
902
|
-
|
|
902
|
+
unsigned int flags = 0)
|
|
903
903
|
{
|
|
904
904
|
RG_ASSERT(new_len >= 0);
|
|
905
905
|
|
|
@@ -914,7 +914,7 @@ Span<T> ResizeSpan(Allocator *alloc, Span<T> mem, Size new_len,
|
|
|
914
914
|
return MakeSpan(mem.ptr, new_len);
|
|
915
915
|
}
|
|
916
916
|
|
|
917
|
-
static inline void ReleaseRaw(Allocator *alloc, void *ptr, Size size)
|
|
917
|
+
static inline void ReleaseRaw(Allocator *alloc, const void *ptr, Size size)
|
|
918
918
|
{
|
|
919
919
|
if (!alloc) {
|
|
920
920
|
alloc = GetDefaultAllocator();
|
|
@@ -972,7 +972,7 @@ public:
|
|
|
972
972
|
|
|
973
973
|
void *Allocate(Size size, unsigned int flags = 0) override;
|
|
974
974
|
void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) override;
|
|
975
|
-
void Release(void *ptr, Size size) override;
|
|
975
|
+
void Release(const void *ptr, Size size) override;
|
|
976
976
|
|
|
977
977
|
private:
|
|
978
978
|
static Bucket *PointerToBucket(void *ptr);
|
|
@@ -998,7 +998,7 @@ public:
|
|
|
998
998
|
|
|
999
999
|
void *Allocate(Size size, unsigned int flags = 0) override;
|
|
1000
1000
|
void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) override;
|
|
1001
|
-
void Release(void *ptr, Size size) override;
|
|
1001
|
+
void Release(const void *ptr, Size size) override;
|
|
1002
1002
|
|
|
1003
1003
|
protected:
|
|
1004
1004
|
void CopyFrom(BlockAllocatorBase *other);
|
|
@@ -1380,7 +1380,7 @@ public:
|
|
|
1380
1380
|
}
|
|
1381
1381
|
}
|
|
1382
1382
|
|
|
1383
|
-
|
|
1383
|
+
T *Grow(Size reserve_capacity = 1)
|
|
1384
1384
|
{
|
|
1385
1385
|
RG_ASSERT(capacity >= 0);
|
|
1386
1386
|
RG_ASSERT(reserve_capacity >= 0);
|
|
@@ -1398,6 +1398,8 @@ public:
|
|
|
1398
1398
|
|
|
1399
1399
|
SetCapacity(new_capacity);
|
|
1400
1400
|
}
|
|
1401
|
+
|
|
1402
|
+
return ptr + len;
|
|
1401
1403
|
}
|
|
1402
1404
|
|
|
1403
1405
|
void Trim(Size extra_capacity = 0) { SetCapacity(len + extra_capacity); }
|
|
@@ -2299,7 +2301,7 @@ private:
|
|
|
2299
2301
|
if (new_capacity) {
|
|
2300
2302
|
used = (size_t *)AllocateRaw(allocator,
|
|
2301
2303
|
(new_capacity + (RG_SIZE(size_t) * 8) - 1) / RG_SIZE(size_t),
|
|
2302
|
-
(int)
|
|
2304
|
+
(int)AllocFlag::Zero);
|
|
2303
2305
|
data = (ValueType *)AllocateRaw(allocator, new_capacity * RG_SIZE(ValueType));
|
|
2304
2306
|
for (Size i = 0; i < new_capacity; i++) {
|
|
2305
2307
|
new (&data[i]) ValueType();
|
|
@@ -2794,763 +2796,451 @@ static const char *const TimeModeNames[] = {
|
|
|
2794
2796
|
TimeSpec DecomposeTime(int64_t time, TimeMode mode = TimeMode::Local);
|
|
2795
2797
|
|
|
2796
2798
|
// ------------------------------------------------------------------------
|
|
2797
|
-
//
|
|
2799
|
+
// Format
|
|
2798
2800
|
// ------------------------------------------------------------------------
|
|
2799
2801
|
|
|
2800
|
-
|
|
2801
|
-
None,
|
|
2802
|
-
Zlib,
|
|
2803
|
-
Gzip,
|
|
2804
|
-
Brotli
|
|
2805
|
-
};
|
|
2806
|
-
static const char *const CompressionTypeNames[] = {
|
|
2807
|
-
"None",
|
|
2808
|
-
"Zlib",
|
|
2809
|
-
"Gzip",
|
|
2810
|
-
"Brotli"
|
|
2811
|
-
};
|
|
2802
|
+
class StreamWriter;
|
|
2812
2803
|
|
|
2813
|
-
enum class
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2804
|
+
enum class FmtType {
|
|
2805
|
+
Str1,
|
|
2806
|
+
Str2,
|
|
2807
|
+
Buffer,
|
|
2808
|
+
Char,
|
|
2809
|
+
Bool,
|
|
2810
|
+
Integer,
|
|
2811
|
+
Unsigned,
|
|
2812
|
+
Float,
|
|
2813
|
+
Double,
|
|
2814
|
+
Binary,
|
|
2815
|
+
BigHex,
|
|
2816
|
+
SmallHex,
|
|
2817
|
+
MemorySize,
|
|
2818
|
+
DiskSize,
|
|
2819
|
+
Date,
|
|
2820
|
+
TimeISO,
|
|
2821
|
+
TimeNice,
|
|
2822
|
+
Random,
|
|
2823
|
+
FlagNames,
|
|
2824
|
+
FlagOptions,
|
|
2825
|
+
Span
|
|
2817
2826
|
};
|
|
2818
2827
|
|
|
2819
|
-
class
|
|
2820
|
-
RG_DELETE_COPY(StreamReader)
|
|
2821
|
-
|
|
2822
|
-
enum class SourceType {
|
|
2823
|
-
Memory,
|
|
2824
|
-
File,
|
|
2825
|
-
Function
|
|
2826
|
-
};
|
|
2827
|
-
|
|
2828
|
-
const char *filename = nullptr;
|
|
2829
|
-
bool error = true;
|
|
2830
|
-
|
|
2831
|
-
struct {
|
|
2832
|
-
SourceType type = SourceType::Memory;
|
|
2833
|
-
union U {
|
|
2834
|
-
struct {
|
|
2835
|
-
Span<const uint8_t> buf;
|
|
2836
|
-
Size pos;
|
|
2837
|
-
} memory;
|
|
2838
|
-
struct {
|
|
2839
|
-
FILE *fp;
|
|
2840
|
-
bool owned;
|
|
2841
|
-
} file;
|
|
2842
|
-
std::function<Size(Span<uint8_t> buf)> func;
|
|
2843
|
-
|
|
2844
|
-
// StreamReader deals with func destructor
|
|
2845
|
-
U() {}
|
|
2846
|
-
~U() {}
|
|
2847
|
-
} u;
|
|
2848
|
-
|
|
2849
|
-
bool eof = false;
|
|
2850
|
-
} source;
|
|
2851
|
-
|
|
2852
|
-
struct {
|
|
2853
|
-
CompressionType type = CompressionType::None;
|
|
2854
|
-
union {
|
|
2855
|
-
struct MinizInflateContext *miniz;
|
|
2856
|
-
struct BrotliDecompressContext *brotli;
|
|
2857
|
-
} u;
|
|
2858
|
-
} compression;
|
|
2859
|
-
|
|
2860
|
-
int64_t raw_len = -1;
|
|
2861
|
-
Size raw_read = 0;
|
|
2862
|
-
bool eof = false;
|
|
2863
|
-
|
|
2864
|
-
BlockAllocator str_alloc;
|
|
2865
|
-
|
|
2828
|
+
class FmtArg {
|
|
2866
2829
|
public:
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
Size ReadAll(Size max_len, HeapArray<char> *out_buf)
|
|
2905
|
-
{ return ReadAll(max_len, (HeapArray<uint8_t> *)out_buf); }
|
|
2906
|
-
|
|
2907
|
-
int64_t ComputeRawLen();
|
|
2830
|
+
FmtType type;
|
|
2831
|
+
union {
|
|
2832
|
+
const char *str1;
|
|
2833
|
+
Span<const char> str2;
|
|
2834
|
+
char buf[32];
|
|
2835
|
+
char ch;
|
|
2836
|
+
bool b;
|
|
2837
|
+
int64_t i;
|
|
2838
|
+
uint64_t u;
|
|
2839
|
+
struct {
|
|
2840
|
+
float value;
|
|
2841
|
+
int min_prec;
|
|
2842
|
+
int max_prec;
|
|
2843
|
+
} f;
|
|
2844
|
+
struct {
|
|
2845
|
+
double value;
|
|
2846
|
+
int min_prec;
|
|
2847
|
+
int max_prec;
|
|
2848
|
+
} d;
|
|
2849
|
+
const void *ptr;
|
|
2850
|
+
LocalDate date;
|
|
2851
|
+
struct {
|
|
2852
|
+
TimeSpec spec;
|
|
2853
|
+
bool ms;
|
|
2854
|
+
} time;
|
|
2855
|
+
struct {
|
|
2856
|
+
Size len;
|
|
2857
|
+
const char *chars;
|
|
2858
|
+
} random;
|
|
2859
|
+
struct {
|
|
2860
|
+
uint64_t flags;
|
|
2861
|
+
union {
|
|
2862
|
+
Span<const char *const> names;
|
|
2863
|
+
Span<const struct OptionDesc> options;
|
|
2864
|
+
} u;
|
|
2865
|
+
const char *separator;
|
|
2866
|
+
} flags;
|
|
2908
2867
|
|
|
2909
|
-
|
|
2910
|
-
|
|
2868
|
+
struct {
|
|
2869
|
+
FmtType type;
|
|
2870
|
+
int type_len;
|
|
2871
|
+
const void *ptr;
|
|
2872
|
+
Size len;
|
|
2873
|
+
const char *separator;
|
|
2874
|
+
} span;
|
|
2875
|
+
} u;
|
|
2911
2876
|
|
|
2912
|
-
|
|
2877
|
+
int repeat = 1;
|
|
2878
|
+
int pad_len = 0;
|
|
2879
|
+
char pad_char = 0;
|
|
2913
2880
|
|
|
2914
|
-
|
|
2915
|
-
|
|
2881
|
+
FmtArg() = default;
|
|
2882
|
+
FmtArg(std::nullptr_t) : type(FmtType::Str1) { u.str1 = "(null)"; }
|
|
2883
|
+
FmtArg(const char *str) : type(FmtType::Str1) { u.str1 = str ? str : "(null)"; }
|
|
2884
|
+
FmtArg(Span<const char> str) : type(FmtType::Str2) { u.str2 = str; }
|
|
2885
|
+
FmtArg(char c) : type(FmtType::Char) { u.ch = c; }
|
|
2886
|
+
FmtArg(bool b) : type(FmtType::Bool) { u.b = b; }
|
|
2887
|
+
FmtArg(unsigned char i) : type(FmtType::Unsigned) { u.u = i; }
|
|
2888
|
+
FmtArg(short i) : type(FmtType::Integer) { u.i = i; }
|
|
2889
|
+
FmtArg(unsigned short i) : type(FmtType::Unsigned) { u.u = i; }
|
|
2890
|
+
FmtArg(int i) : type(FmtType::Integer) { u.i = i; }
|
|
2891
|
+
FmtArg(unsigned int i) : type(FmtType::Unsigned) { u.u = i; }
|
|
2892
|
+
FmtArg(long i) : type(FmtType::Integer) { u.i = i; }
|
|
2893
|
+
FmtArg(unsigned long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
2894
|
+
FmtArg(long long i) : type(FmtType::Integer) { u.i = i; }
|
|
2895
|
+
FmtArg(unsigned long long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
2896
|
+
FmtArg(float f) : type(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
|
|
2897
|
+
FmtArg(double d) : type(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
|
|
2898
|
+
FmtArg(const void *ptr) : type(FmtType::BigHex) { u.u = (uint64_t)ptr; }
|
|
2899
|
+
FmtArg(const LocalDate &date) : type(FmtType::Date) { u.date = date; }
|
|
2916
2900
|
|
|
2917
|
-
|
|
2901
|
+
FmtArg &Repeat(int new_repeat) { repeat = new_repeat; return *this; }
|
|
2902
|
+
FmtArg &Pad(int len, char c = ' ') { pad_char = c; pad_len = len; return *this; }
|
|
2903
|
+
FmtArg &Pad0(int len) { return Pad(len, '0'); }
|
|
2918
2904
|
};
|
|
2919
2905
|
|
|
2920
|
-
static inline
|
|
2906
|
+
static inline FmtArg FmtBin(uint64_t u)
|
|
2921
2907
|
{
|
|
2922
|
-
|
|
2923
|
-
|
|
2908
|
+
FmtArg arg;
|
|
2909
|
+
arg.type = FmtType::Binary;
|
|
2910
|
+
arg.u.u = u;
|
|
2911
|
+
return arg;
|
|
2924
2912
|
}
|
|
2925
|
-
static inline
|
|
2913
|
+
static inline FmtArg FmtHex(uint64_t u, FmtType type = FmtType::BigHex)
|
|
2926
2914
|
{
|
|
2927
|
-
|
|
2928
|
-
|
|
2915
|
+
RG_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
|
|
2916
|
+
|
|
2917
|
+
FmtArg arg;
|
|
2918
|
+
arg.type = type;
|
|
2919
|
+
arg.u.u = u;
|
|
2920
|
+
return arg;
|
|
2929
2921
|
}
|
|
2930
|
-
|
|
2922
|
+
|
|
2923
|
+
static inline FmtArg FmtFloat(float f, int min_prec, int max_prec)
|
|
2931
2924
|
{
|
|
2932
|
-
|
|
2933
|
-
|
|
2925
|
+
FmtArg arg;
|
|
2926
|
+
arg.type = FmtType::Float;
|
|
2927
|
+
arg.u.f.value = f;
|
|
2928
|
+
arg.u.f.min_prec = min_prec;
|
|
2929
|
+
arg.u.f.max_prec = max_prec;
|
|
2930
|
+
return arg;
|
|
2934
2931
|
}
|
|
2935
|
-
static inline
|
|
2932
|
+
static inline FmtArg FmtFloat(float f, int prec) { return FmtFloat(f, prec, prec); }
|
|
2933
|
+
static inline FmtArg FmtFloat(float f) { return FmtFloat(f, 0, INT_MAX); }
|
|
2934
|
+
|
|
2935
|
+
static inline FmtArg FmtDouble(double d, int min_prec, int max_prec)
|
|
2936
2936
|
{
|
|
2937
|
-
|
|
2938
|
-
|
|
2937
|
+
FmtArg arg;
|
|
2938
|
+
arg.type = FmtType::Double;
|
|
2939
|
+
arg.u.d.value = d;
|
|
2940
|
+
arg.u.d.min_prec = min_prec;
|
|
2941
|
+
arg.u.d.max_prec = max_prec;
|
|
2942
|
+
return arg;
|
|
2939
2943
|
}
|
|
2944
|
+
static inline FmtArg FmtDouble(double d, int prec) { return FmtDouble(d, prec, prec); }
|
|
2945
|
+
static inline FmtArg FmtDouble(double d) { return FmtDouble(d, 0, INT_MAX); }
|
|
2940
2946
|
|
|
2941
|
-
static inline
|
|
2942
|
-
HeapArray<uint8_t> *out_buf)
|
|
2947
|
+
static inline FmtArg FmtMemSize(int64_t size)
|
|
2943
2948
|
{
|
|
2944
|
-
|
|
2945
|
-
|
|
2949
|
+
FmtArg arg;
|
|
2950
|
+
arg.type = FmtType::MemorySize;
|
|
2951
|
+
arg.u.i = size;
|
|
2952
|
+
return arg;
|
|
2946
2953
|
}
|
|
2947
|
-
static inline
|
|
2954
|
+
static inline FmtArg FmtDiskSize(int64_t size)
|
|
2948
2955
|
{
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
HeapArray<char> *out_buf)
|
|
2954
|
-
{
|
|
2955
|
-
StreamReader st(filename, compression_type);
|
|
2956
|
-
return st.ReadAll(max_len, out_buf);
|
|
2956
|
+
FmtArg arg;
|
|
2957
|
+
arg.type = FmtType::DiskSize;
|
|
2958
|
+
arg.u.i = size;
|
|
2959
|
+
return arg;
|
|
2957
2960
|
}
|
|
2958
|
-
|
|
2961
|
+
|
|
2962
|
+
static inline FmtArg FmtTimeISO(TimeSpec spec, bool ms = false)
|
|
2959
2963
|
{
|
|
2960
|
-
|
|
2961
|
-
|
|
2964
|
+
FmtArg arg;
|
|
2965
|
+
arg.type = FmtType::TimeISO;
|
|
2966
|
+
arg.u.time.spec = spec;
|
|
2967
|
+
arg.u.time.ms = ms;
|
|
2968
|
+
return arg;
|
|
2962
2969
|
}
|
|
2963
2970
|
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
bool eof = false;
|
|
2971
|
+
static inline FmtArg FmtTimeNice(TimeSpec spec, bool ms = false)
|
|
2972
|
+
{
|
|
2973
|
+
FmtArg arg;
|
|
2974
|
+
arg.type = FmtType::TimeNice;
|
|
2975
|
+
arg.u.time.spec = spec;
|
|
2976
|
+
arg.u.time.ms = ms;
|
|
2977
|
+
return arg;
|
|
2978
|
+
}
|
|
2973
2979
|
|
|
2974
|
-
|
|
2975
|
-
|
|
2980
|
+
static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
|
|
2981
|
+
{
|
|
2982
|
+
RG_ASSERT(len < 256);
|
|
2983
|
+
len = std::min(len, (Size)256);
|
|
2976
2984
|
|
|
2977
|
-
|
|
2978
|
-
|
|
2985
|
+
FmtArg arg;
|
|
2986
|
+
arg.type = FmtType::Random;
|
|
2987
|
+
arg.u.random.len = len;
|
|
2988
|
+
arg.u.random.chars = chars;
|
|
2989
|
+
return arg;
|
|
2990
|
+
}
|
|
2979
2991
|
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2992
|
+
static inline FmtArg FmtFlags(uint64_t flags, Span<const char *const> names, const char *sep = ", ")
|
|
2993
|
+
{
|
|
2994
|
+
FmtArg arg;
|
|
2995
|
+
arg.type = FmtType::FlagNames;
|
|
2996
|
+
arg.u.flags.flags = flags & ((1ull << names.len) - 1);
|
|
2997
|
+
arg.u.flags.u.names = names;
|
|
2998
|
+
arg.u.flags.separator = sep;
|
|
2999
|
+
return arg;
|
|
3000
|
+
}
|
|
2984
3001
|
|
|
2985
|
-
|
|
2986
|
-
|
|
3002
|
+
static inline FmtArg FmtFlags(uint64_t flags, Span<const struct OptionDesc> options, const char *sep = ", ")
|
|
3003
|
+
{
|
|
3004
|
+
FmtArg arg;
|
|
3005
|
+
arg.type = FmtType::FlagOptions;
|
|
3006
|
+
arg.u.flags.flags = flags & ((1ull << options.len) - 1);
|
|
3007
|
+
arg.u.flags.u.options = options;
|
|
3008
|
+
arg.u.flags.separator = sep;
|
|
3009
|
+
return arg;
|
|
3010
|
+
}
|
|
2987
3011
|
|
|
2988
|
-
|
|
2989
|
-
|
|
3012
|
+
template <typename T>
|
|
3013
|
+
FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
|
|
3014
|
+
{
|
|
3015
|
+
FmtArg arg;
|
|
3016
|
+
arg.type = FmtType::Span;
|
|
3017
|
+
arg.u.span.type = type;
|
|
3018
|
+
arg.u.span.type_len = RG_SIZE(T);
|
|
3019
|
+
arg.u.span.ptr = (const void *)arr.ptr;
|
|
3020
|
+
arg.u.span.len = arr.len;
|
|
3021
|
+
arg.u.span.separator = sep;
|
|
3022
|
+
return arg;
|
|
3023
|
+
}
|
|
3024
|
+
template <typename T>
|
|
3025
|
+
FmtArg FmtSpan(Span<T> arr, const char *sep = ", ") { return FmtSpan(arr, FmtArg(T()).type, sep); }
|
|
3026
|
+
template <typename T, Size N>
|
|
3027
|
+
FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSpan(MakeSpan(arr), type, sep); }
|
|
3028
|
+
template <typename T, Size N>
|
|
3029
|
+
FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
|
|
2990
3030
|
|
|
2991
|
-
enum class
|
|
2992
|
-
|
|
2993
|
-
|
|
3031
|
+
enum class LogLevel {
|
|
3032
|
+
Debug,
|
|
3033
|
+
Info,
|
|
3034
|
+
Warning,
|
|
3035
|
+
Error
|
|
2994
3036
|
};
|
|
2995
3037
|
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
};
|
|
3004
|
-
|
|
3005
|
-
const char *filename = nullptr;
|
|
3006
|
-
bool error = true;
|
|
3007
|
-
|
|
3008
|
-
struct {
|
|
3009
|
-
DestinationType type = DestinationType::Memory;
|
|
3010
|
-
union U {
|
|
3011
|
-
struct {
|
|
3012
|
-
HeapArray<uint8_t> *memory;
|
|
3013
|
-
Size start;
|
|
3014
|
-
} mem;
|
|
3015
|
-
struct {
|
|
3016
|
-
FILE *fp;
|
|
3017
|
-
bool owned;
|
|
3018
|
-
|
|
3019
|
-
// Atomic write mode
|
|
3020
|
-
const char *tmp_filename;
|
|
3021
|
-
bool tmp_exclusive;
|
|
3022
|
-
} file;
|
|
3023
|
-
std::function<bool(Span<const uint8_t>)> func;
|
|
3024
|
-
|
|
3025
|
-
// StreamWriter deals with func destructor
|
|
3026
|
-
U() {}
|
|
3027
|
-
~U() {}
|
|
3028
|
-
} u;
|
|
3029
|
-
|
|
3030
|
-
bool vt100;
|
|
3031
|
-
} dest;
|
|
3032
|
-
|
|
3033
|
-
struct {
|
|
3034
|
-
CompressionType type = CompressionType::None;
|
|
3035
|
-
CompressionSpeed speed = CompressionSpeed::Default;
|
|
3036
|
-
union {
|
|
3037
|
-
struct MinizDeflateContext *miniz;
|
|
3038
|
-
struct BrotliEncoderStateStruct *brotli;
|
|
3039
|
-
} u;
|
|
3040
|
-
} compression;
|
|
3041
|
-
|
|
3042
|
-
BlockAllocator str_alloc;
|
|
3038
|
+
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Span<char> out_buf);
|
|
3039
|
+
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, HeapArray<char> *out_buf);
|
|
3040
|
+
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Allocator *alloc);
|
|
3041
|
+
void PrintFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3042
|
+
void PrintFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3043
|
+
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3044
|
+
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3043
3045
|
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
CompressionType compression_type = CompressionType::None,
|
|
3056
|
-
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
3057
|
-
: StreamWriter() { Open(filename, flags, compression_type, compression_speed); }
|
|
3058
|
-
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename = nullptr,
|
|
3059
|
-
CompressionType compression_type = CompressionType::None,
|
|
3060
|
-
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
3061
|
-
: StreamWriter() { Open(func, filename, compression_type, compression_speed); }
|
|
3062
|
-
~StreamWriter() { Close(true); }
|
|
3046
|
+
#define DEFINE_FMT_VARIANT(Name, Ret, Type) \
|
|
3047
|
+
static inline Ret Name(Type out, const char *fmt) \
|
|
3048
|
+
{ \
|
|
3049
|
+
return Name##Fmt(fmt, {}, out); \
|
|
3050
|
+
} \
|
|
3051
|
+
template <typename... Args> \
|
|
3052
|
+
Ret Name(Type out, const char *fmt, Args... args) \
|
|
3053
|
+
{ \
|
|
3054
|
+
const FmtArg fmt_args[] = { FmtArg(args)... }; \
|
|
3055
|
+
return Name##Fmt(fmt, fmt_args, out); \
|
|
3056
|
+
}
|
|
3063
3057
|
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
CompressionType compression_type = CompressionType::None,
|
|
3072
|
-
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
3073
|
-
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename = nullptr,
|
|
3074
|
-
CompressionType compression_type = CompressionType::None,
|
|
3075
|
-
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
3076
|
-
bool Close() { return Close(false); }
|
|
3058
|
+
DEFINE_FMT_VARIANT(Fmt, Span<char>, Span<char>)
|
|
3059
|
+
DEFINE_FMT_VARIANT(Fmt, Span<char>, HeapArray<char> *)
|
|
3060
|
+
DEFINE_FMT_VARIANT(Fmt, Span<char>, Allocator *)
|
|
3061
|
+
DEFINE_FMT_VARIANT(Print, void, StreamWriter *)
|
|
3062
|
+
DEFINE_FMT_VARIANT(Print, void, FILE *)
|
|
3063
|
+
DEFINE_FMT_VARIANT(PrintLn, void, StreamWriter *)
|
|
3064
|
+
DEFINE_FMT_VARIANT(PrintLn, void, FILE *)
|
|
3077
3065
|
|
|
3078
|
-
|
|
3079
|
-
bool Flush();
|
|
3066
|
+
#undef DEFINE_FMT_VARIANT
|
|
3080
3067
|
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3068
|
+
// Print formatted strings to stdout
|
|
3069
|
+
template <typename... Args>
|
|
3070
|
+
void Print(const char *fmt, Args... args)
|
|
3071
|
+
{
|
|
3072
|
+
Print(stdout, fmt, args...);
|
|
3073
|
+
}
|
|
3074
|
+
template <typename... Args>
|
|
3075
|
+
void PrintLn(const char *fmt, Args... args)
|
|
3076
|
+
{
|
|
3077
|
+
PrintLn(stdout, fmt, args...);
|
|
3078
|
+
}
|
|
3085
3079
|
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3080
|
+
// PrintLn variants without format strings
|
|
3081
|
+
void PrintLn(StreamWriter *out_st);
|
|
3082
|
+
void PrintLn(FILE *out_fp);
|
|
3083
|
+
void PrintLn();
|
|
3090
3084
|
|
|
3091
|
-
|
|
3092
|
-
|
|
3085
|
+
// ------------------------------------------------------------------------
|
|
3086
|
+
// Debug and errors
|
|
3087
|
+
// ------------------------------------------------------------------------
|
|
3093
3088
|
|
|
3094
|
-
|
|
3089
|
+
typedef void LogFunc(LogLevel level, const char *ctx, const char *msg);
|
|
3090
|
+
typedef void LogFilterFunc(LogLevel level, const char *ctx, const char *msg,
|
|
3091
|
+
FunctionRef<LogFunc> func);
|
|
3095
3092
|
|
|
3096
|
-
|
|
3097
|
-
|
|
3093
|
+
const char *GetQualifiedEnv(const char *name);
|
|
3094
|
+
bool GetDebugFlag(const char *name);
|
|
3098
3095
|
|
|
3099
|
-
|
|
3100
|
-
};
|
|
3096
|
+
void LogFmt(LogLevel level, const char *ctx, const char *fmt, Span<const FmtArg> args);
|
|
3101
3097
|
|
|
3102
|
-
static inline
|
|
3103
|
-
CompressionType compression_type = CompressionType::None)
|
|
3098
|
+
static inline void Log(LogLevel level, const char *ctx)
|
|
3104
3099
|
{
|
|
3105
|
-
|
|
3106
|
-
st.Write(buf);
|
|
3107
|
-
return st.Close();
|
|
3100
|
+
LogFmt(level, ctx, "", {});
|
|
3108
3101
|
}
|
|
3109
|
-
static inline
|
|
3110
|
-
CompressionType compression_type = CompressionType::None)
|
|
3102
|
+
static inline void Log(LogLevel level, const char *ctx, const char *fmt)
|
|
3111
3103
|
{
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3104
|
+
LogFmt(level, ctx, fmt, {});
|
|
3105
|
+
}
|
|
3106
|
+
template <typename... Args>
|
|
3107
|
+
static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args... args)
|
|
3108
|
+
{
|
|
3109
|
+
const FmtArg fmt_args[] = { FmtArg(args)... };
|
|
3110
|
+
LogFmt(level, ctx, fmt, fmt_args);
|
|
3115
3111
|
}
|
|
3116
3112
|
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
Buffer,
|
|
3132
|
-
Char,
|
|
3133
|
-
Bool,
|
|
3134
|
-
Integer,
|
|
3135
|
-
Unsigned,
|
|
3136
|
-
Float,
|
|
3137
|
-
Double,
|
|
3138
|
-
Binary,
|
|
3139
|
-
Hexadecimal,
|
|
3140
|
-
MemorySize,
|
|
3141
|
-
DiskSize,
|
|
3142
|
-
Date,
|
|
3143
|
-
TimeISO,
|
|
3144
|
-
TimeNice,
|
|
3145
|
-
Random,
|
|
3146
|
-
FlagNames,
|
|
3147
|
-
FlagOptions,
|
|
3148
|
-
Span
|
|
3149
|
-
};
|
|
3113
|
+
// Shortcut log functions
|
|
3114
|
+
#ifdef RG_DEBUG
|
|
3115
|
+
template <typename... Args>
|
|
3116
|
+
static inline void LogDebug(Args... args) { Log(LogLevel::Debug, "Debug", args...); }
|
|
3117
|
+
#else
|
|
3118
|
+
template <typename... Args>
|
|
3119
|
+
static inline void LogDebug(Args...) {}
|
|
3120
|
+
#endif
|
|
3121
|
+
template <typename... Args>
|
|
3122
|
+
static inline void LogInfo(Args... args) { Log(LogLevel::Info, nullptr, args...); }
|
|
3123
|
+
template <typename... Args>
|
|
3124
|
+
static inline void LogWarning(Args... args) { Log(LogLevel::Warning, "Warning", args...); }
|
|
3125
|
+
template <typename... Args>
|
|
3126
|
+
static inline void LogError(Args... args) { Log(LogLevel::Error, "Error", args...); }
|
|
3150
3127
|
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
FmtType type;
|
|
3154
|
-
union {
|
|
3155
|
-
const char *str1;
|
|
3156
|
-
Span<const char> str2;
|
|
3157
|
-
char buf[32];
|
|
3158
|
-
char ch;
|
|
3159
|
-
bool b;
|
|
3160
|
-
int64_t i;
|
|
3161
|
-
uint64_t u;
|
|
3162
|
-
struct {
|
|
3163
|
-
float value;
|
|
3164
|
-
int min_prec;
|
|
3165
|
-
int max_prec;
|
|
3166
|
-
} f;
|
|
3167
|
-
struct {
|
|
3168
|
-
double value;
|
|
3169
|
-
int min_prec;
|
|
3170
|
-
int max_prec;
|
|
3171
|
-
} d;
|
|
3172
|
-
const void *ptr;
|
|
3173
|
-
LocalDate date;
|
|
3174
|
-
TimeSpec time;
|
|
3175
|
-
Size random_len;
|
|
3176
|
-
struct {
|
|
3177
|
-
uint64_t flags;
|
|
3178
|
-
union {
|
|
3179
|
-
Span<const char *const> names;
|
|
3180
|
-
Span<const struct OptionDesc> options;
|
|
3181
|
-
} u;
|
|
3182
|
-
const char *separator;
|
|
3183
|
-
} flags;
|
|
3128
|
+
void SetLogHandler(const std::function<LogFunc> &func);
|
|
3129
|
+
void DefaultLogHandler(LogLevel level, const char *ctx, const char *msg);
|
|
3184
3130
|
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
int type_len;
|
|
3188
|
-
const void *ptr;
|
|
3189
|
-
Size len;
|
|
3190
|
-
const char *separator;
|
|
3191
|
-
} span;
|
|
3192
|
-
} u;
|
|
3131
|
+
void PushLogFilter(const std::function<LogFilterFunc> &func);
|
|
3132
|
+
void PopLogFilter();
|
|
3193
3133
|
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3134
|
+
#ifdef _WIN32
|
|
3135
|
+
bool RedirectLogToWindowsEvents(const char *name);
|
|
3136
|
+
#endif
|
|
3197
3137
|
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
FmtArg(Span<const char> str) : type(FmtType::Str2) { u.str2 = str; }
|
|
3202
|
-
FmtArg(char c) : type(FmtType::Char) { u.ch = c; }
|
|
3203
|
-
FmtArg(bool b) : type(FmtType::Bool) { u.b = b; }
|
|
3204
|
-
FmtArg(unsigned char i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3205
|
-
FmtArg(short i) : type(FmtType::Integer) { u.i = i; }
|
|
3206
|
-
FmtArg(unsigned short i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3207
|
-
FmtArg(int i) : type(FmtType::Integer) { u.i = i; }
|
|
3208
|
-
FmtArg(unsigned int i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3209
|
-
FmtArg(long i) : type(FmtType::Integer) { u.i = i; }
|
|
3210
|
-
FmtArg(unsigned long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3211
|
-
FmtArg(long long i) : type(FmtType::Integer) { u.i = i; }
|
|
3212
|
-
FmtArg(unsigned long long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3213
|
-
FmtArg(float f) : type(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
|
|
3214
|
-
FmtArg(double d) : type(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
|
|
3215
|
-
FmtArg(const void *ptr) : type(FmtType::Hexadecimal) { u.u = (uint64_t)ptr; }
|
|
3216
|
-
FmtArg(const LocalDate &date) : type(FmtType::Date) { u.date = date; }
|
|
3138
|
+
// ------------------------------------------------------------------------
|
|
3139
|
+
// Strings
|
|
3140
|
+
// ------------------------------------------------------------------------
|
|
3217
3141
|
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
};
|
|
3142
|
+
bool CopyString(const char *str, Span<char> buf);
|
|
3143
|
+
bool CopyString(Span<const char> str, Span<char> buf);
|
|
3144
|
+
Span<char> DuplicateString(Span<const char> str, Allocator *alloc);
|
|
3222
3145
|
|
|
3223
|
-
static inline
|
|
3146
|
+
static inline bool IsAsciiAlpha(int c)
|
|
3224
3147
|
{
|
|
3225
|
-
|
|
3226
|
-
arg.type = FmtType::Binary;
|
|
3227
|
-
arg.u.u = u;
|
|
3228
|
-
return arg;
|
|
3148
|
+
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
3229
3149
|
}
|
|
3230
|
-
static inline
|
|
3150
|
+
static inline bool IsAsciiDigit(int c)
|
|
3231
3151
|
{
|
|
3232
|
-
|
|
3233
|
-
arg.type = FmtType::Hexadecimal;
|
|
3234
|
-
arg.u.u = u;
|
|
3235
|
-
return arg;
|
|
3152
|
+
return (c >= '0' && c <= '9');
|
|
3236
3153
|
}
|
|
3237
|
-
|
|
3238
|
-
static inline FmtArg FmtFloat(float f, int min_prec, int max_prec)
|
|
3154
|
+
static inline bool IsAsciiAlphaOrDigit(int c)
|
|
3239
3155
|
{
|
|
3240
|
-
|
|
3241
|
-
arg.type = FmtType::Float;
|
|
3242
|
-
arg.u.f.value = f;
|
|
3243
|
-
arg.u.f.min_prec = min_prec;
|
|
3244
|
-
arg.u.f.max_prec = max_prec;
|
|
3245
|
-
return arg;
|
|
3156
|
+
return IsAsciiAlpha(c) || IsAsciiDigit(c);
|
|
3246
3157
|
}
|
|
3247
|
-
static inline
|
|
3248
|
-
static inline FmtArg FmtFloat(float f) { return FmtFloat(f, 0, INT_MAX); }
|
|
3249
|
-
|
|
3250
|
-
static inline FmtArg FmtDouble(double d, int min_prec, int max_prec)
|
|
3158
|
+
static inline bool IsAsciiWhite(int c)
|
|
3251
3159
|
{
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
arg.u.d.value = d;
|
|
3255
|
-
arg.u.d.min_prec = min_prec;
|
|
3256
|
-
arg.u.d.max_prec = max_prec;
|
|
3257
|
-
return arg;
|
|
3160
|
+
return c == ' ' || c == '\t' || c == '\v' ||
|
|
3161
|
+
c == '\n' || c == '\r' || c == '\f';
|
|
3258
3162
|
}
|
|
3259
|
-
static inline FmtArg FmtDouble(double d, int prec) { return FmtDouble(d, prec, prec); }
|
|
3260
|
-
static inline FmtArg FmtDouble(double d) { return FmtDouble(d, 0, INT_MAX); }
|
|
3261
3163
|
|
|
3262
|
-
static inline
|
|
3164
|
+
static inline char UpperAscii(int c)
|
|
3263
3165
|
{
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3166
|
+
if (c >= 'a' && c <= 'z') {
|
|
3167
|
+
return (char)(c - 32);
|
|
3168
|
+
} else {
|
|
3169
|
+
return (char)c;
|
|
3170
|
+
}
|
|
3268
3171
|
}
|
|
3269
|
-
static inline
|
|
3172
|
+
static inline char LowerAscii(int c)
|
|
3270
3173
|
{
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3174
|
+
if (c >= 'A' && c <= 'Z') {
|
|
3175
|
+
return (char)(c + 32);
|
|
3176
|
+
} else {
|
|
3177
|
+
return (char)c;
|
|
3178
|
+
}
|
|
3275
3179
|
}
|
|
3276
3180
|
|
|
3277
|
-
static inline
|
|
3181
|
+
static inline bool TestStr(Span<const char> str1, Span<const char> str2)
|
|
3278
3182
|
{
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3183
|
+
if (str1.len != str2.len)
|
|
3184
|
+
return false;
|
|
3185
|
+
for (Size i = 0; i < str1.len; i++) {
|
|
3186
|
+
if (str1[i] != str2[i])
|
|
3187
|
+
return false;
|
|
3188
|
+
}
|
|
3189
|
+
return true;
|
|
3283
3190
|
}
|
|
3284
|
-
|
|
3285
|
-
static inline FmtArg FmtTimeNice(TimeSpec spec)
|
|
3191
|
+
static inline bool TestStr(Span<const char> str1, const char *str2)
|
|
3286
3192
|
{
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3193
|
+
Size i;
|
|
3194
|
+
for (i = 0; i < str1.len && str2[i]; i++) {
|
|
3195
|
+
if (str1[i] != str2[i])
|
|
3196
|
+
return false;
|
|
3197
|
+
}
|
|
3198
|
+
return (i == str1.len) && !str2[i];
|
|
3291
3199
|
}
|
|
3200
|
+
static inline bool TestStr(const char *str1, Span<const char> str2)
|
|
3201
|
+
{ return TestStr(str2, str1); }
|
|
3202
|
+
static inline bool TestStr(const char *str1, const char *str2)
|
|
3203
|
+
{ return !strcmp(str1, str2); }
|
|
3292
3204
|
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3205
|
+
// Allow direct Span<const char> equality comparison
|
|
3206
|
+
inline bool Span<const char>::operator==(Span<const char> other) const
|
|
3207
|
+
{ return TestStr(*this, other); }
|
|
3208
|
+
inline bool Span<const char>::operator==(const char *other) const
|
|
3209
|
+
{ return TestStr(*this, other); }
|
|
3297
3210
|
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3211
|
+
// Case insensitive (ASCII) versions
|
|
3212
|
+
static inline bool TestStrI(Span<const char> str1, Span<const char> str2)
|
|
3213
|
+
{
|
|
3214
|
+
if (str1.len != str2.len)
|
|
3215
|
+
return false;
|
|
3216
|
+
for (Size i = 0; i < str1.len; i++) {
|
|
3217
|
+
if (LowerAscii(str1[i]) != LowerAscii(str2[i]))
|
|
3218
|
+
return false;
|
|
3219
|
+
}
|
|
3220
|
+
return true;
|
|
3302
3221
|
}
|
|
3303
|
-
|
|
3304
|
-
static inline FmtArg FmtFlags(uint64_t flags, Span<const char *const> names, const char *sep = ", ")
|
|
3222
|
+
static inline bool TestStrI(Span<const char> str1, const char *str2)
|
|
3305
3223
|
{
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
return
|
|
3224
|
+
Size i;
|
|
3225
|
+
for (i = 0; i < str1.len && str2[i]; i++) {
|
|
3226
|
+
if (LowerAscii(str1[i]) != LowerAscii(str2[i]))
|
|
3227
|
+
return false;
|
|
3228
|
+
}
|
|
3229
|
+
return (i == str1.len) && !str2[i];
|
|
3230
|
+
}
|
|
3231
|
+
static inline bool TestStrI(const char *str1, Span<const char> str2)
|
|
3232
|
+
{ return TestStr(str2, str1); }
|
|
3233
|
+
static inline bool TestStrI(const char *str1, const char *str2)
|
|
3234
|
+
{
|
|
3235
|
+
Size i = 0;
|
|
3236
|
+
int delta;
|
|
3237
|
+
do {
|
|
3238
|
+
delta = LowerAscii(str1[i]) - LowerAscii(str2[i]);
|
|
3239
|
+
} while (str1[i++] && !delta);
|
|
3240
|
+
return !delta;
|
|
3312
3241
|
}
|
|
3313
3242
|
|
|
3314
|
-
static inline
|
|
3315
|
-
{
|
|
3316
|
-
FmtArg arg;
|
|
3317
|
-
arg.type = FmtType::FlagOptions;
|
|
3318
|
-
arg.u.flags.flags = flags & ((1ull << options.len) - 1);
|
|
3319
|
-
arg.u.flags.u.options = options;
|
|
3320
|
-
arg.u.flags.separator = sep;
|
|
3321
|
-
return arg;
|
|
3322
|
-
}
|
|
3323
|
-
|
|
3324
|
-
template <typename T>
|
|
3325
|
-
FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
|
|
3326
|
-
{
|
|
3327
|
-
FmtArg arg;
|
|
3328
|
-
arg.type = FmtType::Span;
|
|
3329
|
-
arg.u.span.type = type;
|
|
3330
|
-
arg.u.span.type_len = RG_SIZE(T);
|
|
3331
|
-
arg.u.span.ptr = (const void *)arr.ptr;
|
|
3332
|
-
arg.u.span.len = arr.len;
|
|
3333
|
-
arg.u.span.separator = sep;
|
|
3334
|
-
return arg;
|
|
3335
|
-
}
|
|
3336
|
-
template <typename T>
|
|
3337
|
-
FmtArg FmtSpan(Span<T> arr, const char *sep = ", ") { return FmtSpan(arr, FmtArg(T()).type, sep); }
|
|
3338
|
-
template <typename T, Size N>
|
|
3339
|
-
FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSpan(MakeSpan(arr), type, sep); }
|
|
3340
|
-
template <typename T, Size N>
|
|
3341
|
-
FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
|
|
3342
|
-
|
|
3343
|
-
enum class LogLevel {
|
|
3344
|
-
Debug,
|
|
3345
|
-
Info,
|
|
3346
|
-
Warning,
|
|
3347
|
-
Error
|
|
3348
|
-
};
|
|
3349
|
-
|
|
3350
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Span<char> out_buf);
|
|
3351
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, HeapArray<char> *out_buf);
|
|
3352
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Allocator *alloc);
|
|
3353
|
-
void PrintFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3354
|
-
void PrintFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3355
|
-
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3356
|
-
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3357
|
-
|
|
3358
|
-
#define DEFINE_FMT_VARIANT(Name, Ret, Type) \
|
|
3359
|
-
static inline Ret Name(Type out, const char *fmt) \
|
|
3360
|
-
{ \
|
|
3361
|
-
return Name##Fmt(fmt, {}, out); \
|
|
3362
|
-
} \
|
|
3363
|
-
template <typename... Args> \
|
|
3364
|
-
Ret Name(Type out, const char *fmt, Args... args) \
|
|
3365
|
-
{ \
|
|
3366
|
-
const FmtArg fmt_args[] = { FmtArg(args)... }; \
|
|
3367
|
-
return Name##Fmt(fmt, fmt_args, out); \
|
|
3368
|
-
}
|
|
3369
|
-
|
|
3370
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, Span<char>)
|
|
3371
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, HeapArray<char> *)
|
|
3372
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, Allocator *)
|
|
3373
|
-
DEFINE_FMT_VARIANT(Print, void, StreamWriter *)
|
|
3374
|
-
DEFINE_FMT_VARIANT(Print, void, FILE *)
|
|
3375
|
-
DEFINE_FMT_VARIANT(PrintLn, void, StreamWriter *)
|
|
3376
|
-
DEFINE_FMT_VARIANT(PrintLn, void, FILE *)
|
|
3377
|
-
|
|
3378
|
-
#undef DEFINE_FMT_VARIANT
|
|
3379
|
-
|
|
3380
|
-
// Print formatted strings to stdout
|
|
3381
|
-
template <typename... Args>
|
|
3382
|
-
void Print(const char *fmt, Args... args)
|
|
3383
|
-
{
|
|
3384
|
-
Print(stdout, fmt, args...);
|
|
3385
|
-
}
|
|
3386
|
-
template <typename... Args>
|
|
3387
|
-
void PrintLn(const char *fmt, Args... args)
|
|
3388
|
-
{
|
|
3389
|
-
PrintLn(stdout, fmt, args...);
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
// PrintLn variants without format strings
|
|
3393
|
-
static inline void PrintLn(StreamWriter *out_st) { out_st->Write('\n'); }
|
|
3394
|
-
static inline void PrintLn(FILE *out_fp) { fputc('\n', out_fp); }
|
|
3395
|
-
static inline void PrintLn() { putchar('\n'); }
|
|
3396
|
-
|
|
3397
|
-
// ------------------------------------------------------------------------
|
|
3398
|
-
// Debug and errors
|
|
3399
|
-
// ------------------------------------------------------------------------
|
|
3400
|
-
|
|
3401
|
-
typedef void LogFunc(LogLevel level, const char *ctx, const char *msg);
|
|
3402
|
-
typedef void LogFilterFunc(LogLevel level, const char *ctx, const char *msg,
|
|
3403
|
-
FunctionRef<LogFunc> func);
|
|
3404
|
-
|
|
3405
|
-
const char *GetQualifiedEnv(const char *name);
|
|
3406
|
-
bool GetDebugFlag(const char *name);
|
|
3407
|
-
|
|
3408
|
-
void LogFmt(LogLevel level, const char *ctx, const char *fmt, Span<const FmtArg> args);
|
|
3409
|
-
|
|
3410
|
-
static inline void Log(LogLevel level, const char *ctx)
|
|
3411
|
-
{
|
|
3412
|
-
LogFmt(level, ctx, "", {});
|
|
3413
|
-
}
|
|
3414
|
-
static inline void Log(LogLevel level, const char *ctx, const char *fmt)
|
|
3415
|
-
{
|
|
3416
|
-
LogFmt(level, ctx, fmt, {});
|
|
3417
|
-
}
|
|
3418
|
-
template <typename... Args>
|
|
3419
|
-
static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args... args)
|
|
3420
|
-
{
|
|
3421
|
-
const FmtArg fmt_args[] = { FmtArg(args)... };
|
|
3422
|
-
LogFmt(level, ctx, fmt, fmt_args);
|
|
3423
|
-
}
|
|
3424
|
-
|
|
3425
|
-
// Shortcut log functions
|
|
3426
|
-
#ifdef RG_DEBUG
|
|
3427
|
-
template <typename... Args>
|
|
3428
|
-
static inline void LogDebug(Args... args) { Log(LogLevel::Debug, "Debug", args...); }
|
|
3429
|
-
#else
|
|
3430
|
-
template <typename... Args>
|
|
3431
|
-
static inline void LogDebug(Args...) {}
|
|
3432
|
-
#endif
|
|
3433
|
-
template <typename... Args>
|
|
3434
|
-
static inline void LogInfo(Args... args) { Log(LogLevel::Info, nullptr, args...); }
|
|
3435
|
-
template <typename... Args>
|
|
3436
|
-
static inline void LogError(Args... args) { Log(LogLevel::Error, "Error", args...); }
|
|
3437
|
-
|
|
3438
|
-
void SetLogHandler(const std::function<LogFunc> &func);
|
|
3439
|
-
void DefaultLogHandler(LogLevel level, const char *ctx, const char *msg);
|
|
3440
|
-
|
|
3441
|
-
void PushLogFilter(const std::function<LogFilterFunc> &func);
|
|
3442
|
-
void PopLogFilter();
|
|
3443
|
-
|
|
3444
|
-
#ifdef _WIN32
|
|
3445
|
-
bool RedirectLogToWindowsEvents(const char *name);
|
|
3446
|
-
#endif
|
|
3447
|
-
|
|
3448
|
-
// ------------------------------------------------------------------------
|
|
3449
|
-
// Strings
|
|
3450
|
-
// ------------------------------------------------------------------------
|
|
3451
|
-
|
|
3452
|
-
bool CopyString(const char *str, Span<char> buf);
|
|
3453
|
-
bool CopyString(Span<const char> str, Span<char> buf);
|
|
3454
|
-
Span<char> DuplicateString(Span<const char> str, Allocator *alloc);
|
|
3455
|
-
|
|
3456
|
-
static inline bool IsAsciiAlpha(int c)
|
|
3457
|
-
{
|
|
3458
|
-
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
3459
|
-
}
|
|
3460
|
-
static inline bool IsAsciiDigit(int c)
|
|
3461
|
-
{
|
|
3462
|
-
return (c >= '0' && c <= '9');
|
|
3463
|
-
}
|
|
3464
|
-
static inline bool IsAsciiAlphaOrDigit(int c)
|
|
3465
|
-
{
|
|
3466
|
-
return IsAsciiAlpha(c) || IsAsciiDigit(c);
|
|
3467
|
-
}
|
|
3468
|
-
static inline bool IsAsciiWhite(int c)
|
|
3469
|
-
{
|
|
3470
|
-
return c == ' ' || c == '\t' || c == '\v' ||
|
|
3471
|
-
c == '\n' || c == '\r' || c == '\f';
|
|
3472
|
-
}
|
|
3473
|
-
|
|
3474
|
-
static inline char UpperAscii(int c)
|
|
3475
|
-
{
|
|
3476
|
-
if (c >= 'a' && c <= 'z') {
|
|
3477
|
-
return (char)(c - 32);
|
|
3478
|
-
} else {
|
|
3479
|
-
return (char)c;
|
|
3480
|
-
}
|
|
3481
|
-
}
|
|
3482
|
-
static inline char LowerAscii(int c)
|
|
3483
|
-
{
|
|
3484
|
-
if (c >= 'A' && c <= 'Z') {
|
|
3485
|
-
return (char)(c + 32);
|
|
3486
|
-
} else {
|
|
3487
|
-
return (char)c;
|
|
3488
|
-
}
|
|
3489
|
-
}
|
|
3490
|
-
|
|
3491
|
-
static inline bool TestStr(Span<const char> str1, Span<const char> str2)
|
|
3492
|
-
{
|
|
3493
|
-
if (str1.len != str2.len)
|
|
3494
|
-
return false;
|
|
3495
|
-
for (Size i = 0; i < str1.len; i++) {
|
|
3496
|
-
if (str1[i] != str2[i])
|
|
3497
|
-
return false;
|
|
3498
|
-
}
|
|
3499
|
-
return true;
|
|
3500
|
-
}
|
|
3501
|
-
static inline bool TestStr(Span<const char> str1, const char *str2)
|
|
3502
|
-
{
|
|
3503
|
-
Size i;
|
|
3504
|
-
for (i = 0; i < str1.len && str2[i]; i++) {
|
|
3505
|
-
if (str1[i] != str2[i])
|
|
3506
|
-
return false;
|
|
3507
|
-
}
|
|
3508
|
-
return (i == str1.len) && !str2[i];
|
|
3509
|
-
}
|
|
3510
|
-
static inline bool TestStr(const char *str1, Span<const char> str2)
|
|
3511
|
-
{ return TestStr(str2, str1); }
|
|
3512
|
-
static inline bool TestStr(const char *str1, const char *str2)
|
|
3513
|
-
{ return !strcmp(str1, str2); }
|
|
3514
|
-
|
|
3515
|
-
// Allow direct Span<const char> equality comparison
|
|
3516
|
-
inline bool Span<const char>::operator==(Span<const char> other) const
|
|
3517
|
-
{ return TestStr(*this, other); }
|
|
3518
|
-
inline bool Span<const char>::operator==(const char *other) const
|
|
3519
|
-
{ return TestStr(*this, other); }
|
|
3520
|
-
|
|
3521
|
-
// Case insensitive (ASCII) versions
|
|
3522
|
-
static inline bool TestStrI(Span<const char> str1, Span<const char> str2)
|
|
3523
|
-
{
|
|
3524
|
-
if (str1.len != str2.len)
|
|
3525
|
-
return false;
|
|
3526
|
-
for (Size i = 0; i < str1.len; i++) {
|
|
3527
|
-
if (LowerAscii(str1[i]) != LowerAscii(str2[i]))
|
|
3528
|
-
return false;
|
|
3529
|
-
}
|
|
3530
|
-
return true;
|
|
3531
|
-
}
|
|
3532
|
-
static inline bool TestStrI(Span<const char> str1, const char *str2)
|
|
3533
|
-
{
|
|
3534
|
-
Size i;
|
|
3535
|
-
for (i = 0; i < str1.len && str2[i]; i++) {
|
|
3536
|
-
if (LowerAscii(str1[i]) != LowerAscii(str2[i]))
|
|
3537
|
-
return false;
|
|
3538
|
-
}
|
|
3539
|
-
return (i == str1.len) && !str2[i];
|
|
3540
|
-
}
|
|
3541
|
-
static inline bool TestStrI(const char *str1, Span<const char> str2)
|
|
3542
|
-
{ return TestStr(str2, str1); }
|
|
3543
|
-
static inline bool TestStrI(const char *str1, const char *str2)
|
|
3544
|
-
{
|
|
3545
|
-
Size i = 0;
|
|
3546
|
-
int delta;
|
|
3547
|
-
do {
|
|
3548
|
-
delta = LowerAscii(str1[i]) - LowerAscii(str2[i]);
|
|
3549
|
-
} while (str1[i++] && !delta);
|
|
3550
|
-
return !delta;
|
|
3551
|
-
}
|
|
3552
|
-
|
|
3553
|
-
static inline int CmpStr(Span<const char> str1, Span<const char> str2)
|
|
3243
|
+
static inline int CmpStr(Span<const char> str1, Span<const char> str2)
|
|
3554
3244
|
{
|
|
3555
3245
|
for (Size i = 0; i < str1.len && i < str2.len; i++) {
|
|
3556
3246
|
int delta = str1[i] - str2[i];
|
|
@@ -3615,729 +3305,1173 @@ static inline Size StartsWith(const char *str, const char *prefix)
|
|
|
3615
3305
|
if (str[i] != prefix[i])
|
|
3616
3306
|
return 0;
|
|
3617
3307
|
|
|
3618
|
-
i++;
|
|
3619
|
-
}
|
|
3308
|
+
i++;
|
|
3309
|
+
}
|
|
3310
|
+
|
|
3311
|
+
return !prefix[i] ? i : 0;
|
|
3312
|
+
}
|
|
3313
|
+
|
|
3314
|
+
static inline bool EndsWith(Span<const char> str, const char *suffix)
|
|
3315
|
+
{
|
|
3316
|
+
Size i = str.len - 1;
|
|
3317
|
+
Size j = (Size)strlen(suffix) - 1;
|
|
3318
|
+
while (i >= 0 && j >= 0) {
|
|
3319
|
+
if (str[i] != suffix[j])
|
|
3320
|
+
return false;
|
|
3321
|
+
|
|
3322
|
+
i--;
|
|
3323
|
+
j--;
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
return j < 0;
|
|
3327
|
+
}
|
|
3328
|
+
|
|
3329
|
+
static inline Size FindStr(Span<const char> str, Span<const char> needle)
|
|
3330
|
+
{
|
|
3331
|
+
if (!needle.len)
|
|
3332
|
+
return 0;
|
|
3333
|
+
if (needle.len > str.len)
|
|
3334
|
+
return -1;
|
|
3335
|
+
|
|
3336
|
+
Size end = str.len - needle.len;
|
|
3337
|
+
|
|
3338
|
+
for (Size i = 0; i <= end; i++) {
|
|
3339
|
+
if (!memcmp(str.ptr + i, needle.ptr, (size_t)needle.len))
|
|
3340
|
+
return i;
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
return -1;
|
|
3344
|
+
}
|
|
3345
|
+
static inline Size FindStr(const char *str, const char *needle)
|
|
3346
|
+
{
|
|
3347
|
+
const char *ret = strstr(str, needle);
|
|
3348
|
+
return ret ? ret - str : -1;
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
static inline Span<char> SplitStr(Span<char> str, char split_char, Span<char> *out_remainder = nullptr)
|
|
3352
|
+
{
|
|
3353
|
+
Size part_len = 0;
|
|
3354
|
+
while (part_len < str.len) {
|
|
3355
|
+
if (str[part_len] == split_char) {
|
|
3356
|
+
if (out_remainder) {
|
|
3357
|
+
*out_remainder = str.Take(part_len + 1, str.len - part_len - 1);
|
|
3358
|
+
}
|
|
3359
|
+
return str.Take(0, part_len);
|
|
3360
|
+
}
|
|
3361
|
+
part_len++;
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
if (out_remainder) {
|
|
3365
|
+
*out_remainder = str.Take(str.len, 0);
|
|
3366
|
+
}
|
|
3367
|
+
return str;
|
|
3368
|
+
}
|
|
3369
|
+
static inline Span<char> SplitStr(char *str, char split_char, char **out_remainder = nullptr)
|
|
3370
|
+
{
|
|
3371
|
+
Size part_len = 0;
|
|
3372
|
+
while (str[part_len]) {
|
|
3373
|
+
if (str[part_len] == split_char) {
|
|
3374
|
+
if (out_remainder) {
|
|
3375
|
+
*out_remainder = str + part_len + 1;
|
|
3376
|
+
}
|
|
3377
|
+
return MakeSpan(str, part_len);
|
|
3378
|
+
}
|
|
3379
|
+
part_len++;
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
if (out_remainder) {
|
|
3383
|
+
*out_remainder = str + part_len;
|
|
3384
|
+
}
|
|
3385
|
+
return MakeSpan(str, part_len);
|
|
3386
|
+
}
|
|
3387
|
+
static inline Span<const char> SplitStr(Span<const char> str, char split_char, Span<const char> *out_remainder = nullptr)
|
|
3388
|
+
{ return SplitStr(MakeSpan((char *)str.ptr, str.len), split_char, (Span<char> *)out_remainder); }
|
|
3389
|
+
static inline Span<const char> SplitStr(const char *str, char split_char, const char **out_remainder = nullptr)
|
|
3390
|
+
{ return SplitStr((char *)str, split_char, (char **)out_remainder); }
|
|
3391
|
+
|
|
3392
|
+
static inline Span<char> SplitStrLine(Span<char> str, Span<char> *out_remainder = nullptr)
|
|
3393
|
+
{
|
|
3394
|
+
Span<char> part = SplitStr(str, '\n', out_remainder);
|
|
3395
|
+
if (part.len < str.len && part.len && part[part.len - 1] == '\r') {
|
|
3396
|
+
part.len--;
|
|
3397
|
+
}
|
|
3398
|
+
return part;
|
|
3399
|
+
}
|
|
3400
|
+
static inline Span<char> SplitStrLine(char *str, char **out_remainder = nullptr)
|
|
3401
|
+
{
|
|
3402
|
+
Span<char> part = SplitStr(str, '\n', out_remainder);
|
|
3403
|
+
if (str[part.len] && part.len && part[part.len - 1] == '\r') {
|
|
3404
|
+
part.len--;
|
|
3405
|
+
}
|
|
3406
|
+
return part;
|
|
3407
|
+
}
|
|
3408
|
+
static inline Span<const char> SplitStrLine(Span<const char> str, Span<const char> *out_remainder = nullptr)
|
|
3409
|
+
{ return SplitStrLine(MakeSpan((char *)str.ptr, str.len), (Span<char> *)out_remainder); }
|
|
3410
|
+
static inline Span<const char> SplitStrLine(const char *str, const char **out_remainder = nullptr)
|
|
3411
|
+
{ return SplitStrLine((char *)str, (char **)out_remainder); }
|
|
3412
|
+
|
|
3413
|
+
static inline Span<char> SplitStrAny(Span<char> str, const char *split_chars, Span<char> *out_remainder = nullptr)
|
|
3414
|
+
{
|
|
3415
|
+
Bitset<256> split_mask;
|
|
3416
|
+
for (Size i = 0; split_chars[i]; i++) {
|
|
3417
|
+
uint8_t c = (uint8_t)split_chars[i];
|
|
3418
|
+
split_mask.Set(c);
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
|
+
Size part_len = 0;
|
|
3422
|
+
while (part_len < str.len) {
|
|
3423
|
+
uint8_t c = (uint8_t)str[part_len];
|
|
3424
|
+
|
|
3425
|
+
if (split_mask.Test(c)) {
|
|
3426
|
+
if (out_remainder) {
|
|
3427
|
+
*out_remainder = str.Take(part_len + 1, str.len - part_len - 1);
|
|
3428
|
+
}
|
|
3429
|
+
return str.Take(0, part_len);
|
|
3430
|
+
}
|
|
3431
|
+
part_len++;
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
if (out_remainder) {
|
|
3435
|
+
*out_remainder = str.Take(str.len, 0);
|
|
3436
|
+
}
|
|
3437
|
+
return str;
|
|
3438
|
+
}
|
|
3439
|
+
static inline Span<char> SplitStrAny(char *str, const char *split_chars, char **out_remainder = nullptr)
|
|
3440
|
+
{
|
|
3441
|
+
Bitset<256> split_mask;
|
|
3442
|
+
for (Size i = 0; split_chars[i]; i++) {
|
|
3443
|
+
uint8_t c = (uint8_t)split_chars[i];
|
|
3444
|
+
split_mask.Set(c);
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
Size part_len = 0;
|
|
3448
|
+
while (str[part_len]) {
|
|
3449
|
+
uint8_t c = (uint8_t)str[part_len];
|
|
3450
|
+
|
|
3451
|
+
if (split_mask.Test(c)) {
|
|
3452
|
+
if (out_remainder) {
|
|
3453
|
+
*out_remainder = str + part_len + 1;
|
|
3454
|
+
}
|
|
3455
|
+
return MakeSpan(str, part_len);
|
|
3456
|
+
}
|
|
3457
|
+
part_len++;
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3460
|
+
if (out_remainder) {
|
|
3461
|
+
*out_remainder = str + part_len;
|
|
3462
|
+
}
|
|
3463
|
+
return MakeSpan(str, part_len);
|
|
3464
|
+
}
|
|
3465
|
+
static inline Span<const char> SplitStrAny(Span<const char> str, const char *split_chars, Span<const char> *out_remainder = nullptr)
|
|
3466
|
+
{ return SplitStrAny(MakeSpan((char *)str.ptr, str.len), split_chars, (Span<char> *)out_remainder); }
|
|
3467
|
+
static inline Span<const char> SplitStrAny(const char *str, const char *split_chars, const char **out_remainder = nullptr)
|
|
3468
|
+
{ return SplitStrAny((char *)str, split_chars, (char **)out_remainder); }
|
|
3469
|
+
|
|
3470
|
+
static inline Span<const char> SplitStrReverse(Span<const char> str, char split_char,
|
|
3471
|
+
Span<const char> *out_remainder = nullptr)
|
|
3472
|
+
{
|
|
3473
|
+
Size remainder_len = str.len - 1;
|
|
3474
|
+
while (remainder_len >= 0) {
|
|
3475
|
+
if (str[remainder_len] == split_char) {
|
|
3476
|
+
if (out_remainder) {
|
|
3477
|
+
*out_remainder = str.Take(0, remainder_len);
|
|
3478
|
+
}
|
|
3479
|
+
return str.Take(remainder_len + 1, str.len - remainder_len - 1);
|
|
3480
|
+
}
|
|
3481
|
+
remainder_len--;
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
if (out_remainder) {
|
|
3485
|
+
*out_remainder = str.Take(0, 0);
|
|
3486
|
+
}
|
|
3487
|
+
return str;
|
|
3488
|
+
}
|
|
3489
|
+
static inline Span<const char> SplitStrReverse(const char *str, char split_char,
|
|
3490
|
+
Span<const char> *out_remainder = nullptr)
|
|
3491
|
+
{ return SplitStrReverse(MakeSpan(str, strlen(str)), split_char, out_remainder); }
|
|
3492
|
+
|
|
3493
|
+
static inline Span<const char> SplitStrReverseAny(Span<const char> str, const char *split_chars,
|
|
3494
|
+
Span<const char> *out_remainder = nullptr)
|
|
3495
|
+
{
|
|
3496
|
+
Bitset<256> split_mask;
|
|
3497
|
+
for (Size i = 0; split_chars[i]; i++) {
|
|
3498
|
+
uint8_t c = (uint8_t)split_chars[i];
|
|
3499
|
+
split_mask.Set(c);
|
|
3500
|
+
}
|
|
3501
|
+
|
|
3502
|
+
Size remainder_len = str.len - 1;
|
|
3503
|
+
while (remainder_len >= 0) {
|
|
3504
|
+
uint8_t c = (uint8_t)str[remainder_len];
|
|
3505
|
+
|
|
3506
|
+
if (split_mask.Test(c)) {
|
|
3507
|
+
if (out_remainder) {
|
|
3508
|
+
*out_remainder = str.Take(0, remainder_len);
|
|
3509
|
+
}
|
|
3510
|
+
return str.Take(remainder_len + 1, str.len - remainder_len - 1);
|
|
3511
|
+
}
|
|
3512
|
+
remainder_len--;
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
if (out_remainder) {
|
|
3516
|
+
*out_remainder = str.Take(0, 0);
|
|
3517
|
+
}
|
|
3518
|
+
return str;
|
|
3519
|
+
}
|
|
3520
|
+
static inline Span<const char> SplitStrReverseAny(const char *str, const char *split_chars,
|
|
3521
|
+
Span<const char> *out_remainder = nullptr)
|
|
3522
|
+
{ return SplitStrReverseAny(MakeSpan(str, strlen(str)), split_chars, out_remainder); }
|
|
3523
|
+
|
|
3524
|
+
static inline Span<char> TrimStrLeft(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3525
|
+
{
|
|
3526
|
+
while (str.len && strchr(trim_chars, str[0]) && str[0]) {
|
|
3527
|
+
str.ptr++;
|
|
3528
|
+
str.len--;
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3531
|
+
return str;
|
|
3532
|
+
}
|
|
3533
|
+
static inline Span<char> TrimStrRight(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3534
|
+
{
|
|
3535
|
+
while (str.len && strchr(trim_chars, str[str.len - 1]) && str[str.len - 1]) {
|
|
3536
|
+
str.len--;
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
return str;
|
|
3540
|
+
}
|
|
3541
|
+
static inline Span<char> TrimStr(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3542
|
+
{
|
|
3543
|
+
str = TrimStrRight(str, trim_chars);
|
|
3544
|
+
str = TrimStrLeft(str, trim_chars);
|
|
3545
|
+
|
|
3546
|
+
return str;
|
|
3547
|
+
}
|
|
3548
|
+
static inline Span<const char> TrimStrLeft(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3549
|
+
{ return TrimStrLeft(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
3550
|
+
static inline Span<const char> TrimStrRight(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3551
|
+
{ return TrimStrRight(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
3552
|
+
static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3553
|
+
{ return TrimStr(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
3554
|
+
|
|
3555
|
+
template <typename T>
|
|
3556
|
+
bool ParseInt(Span<const char> str, T *out_value, unsigned int flags = RG_DEFAULT_PARSE_FLAGS,
|
|
3557
|
+
Span<const char> *out_remaining = nullptr)
|
|
3558
|
+
{
|
|
3559
|
+
if (RG_UNLIKELY(!str.len)) {
|
|
3560
|
+
if (flags & (int)ParseFlag::Log) {
|
|
3561
|
+
LogError("Cannot convert empty string to integer");
|
|
3562
|
+
}
|
|
3563
|
+
return false;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
uint64_t value = 0;
|
|
3567
|
+
|
|
3568
|
+
Size pos = 0;
|
|
3569
|
+
uint64_t neg = 0;
|
|
3570
|
+
if (str.len >= 2) {
|
|
3571
|
+
if (std::numeric_limits<T>::min() < 0 && str[0] == '-') {
|
|
3572
|
+
pos = 1;
|
|
3573
|
+
neg = UINT64_MAX;
|
|
3574
|
+
} else if (str[0] == '+') {
|
|
3575
|
+
pos = 1;
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
|
|
3579
|
+
for (; pos < str.len; pos++) {
|
|
3580
|
+
unsigned int digit = (unsigned int)(str[pos] - '0');
|
|
3581
|
+
if (RG_UNLIKELY(digit > 9)) {
|
|
3582
|
+
if (!pos || flags & (int)ParseFlag::End) {
|
|
3583
|
+
if (flags & (int)ParseFlag::Log) {
|
|
3584
|
+
LogError("Malformed integer number '%1'", str);
|
|
3585
|
+
}
|
|
3586
|
+
return false;
|
|
3587
|
+
} else {
|
|
3588
|
+
break;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3592
|
+
uint64_t new_value = (value * 10) + digit;
|
|
3593
|
+
if (RG_UNLIKELY(new_value < value))
|
|
3594
|
+
goto overflow;
|
|
3595
|
+
value = new_value;
|
|
3596
|
+
}
|
|
3597
|
+
if (RG_UNLIKELY(value > (uint64_t)std::numeric_limits<T>::max()))
|
|
3598
|
+
goto overflow;
|
|
3599
|
+
value = ((value ^ neg) - neg);
|
|
3600
|
+
|
|
3601
|
+
if (out_remaining) {
|
|
3602
|
+
*out_remaining = str.Take(pos, str.len - pos);
|
|
3603
|
+
}
|
|
3604
|
+
*out_value = (T)value;
|
|
3605
|
+
return true;
|
|
3606
|
+
|
|
3607
|
+
overflow:
|
|
3608
|
+
if (flags & (int)ParseFlag::Log) {
|
|
3609
|
+
LogError("Integer overflow for number '%1' (max = %2)", str,
|
|
3610
|
+
std::numeric_limits<T>::max());
|
|
3611
|
+
}
|
|
3612
|
+
return false;
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags = RG_DEFAULT_PARSE_FLAGS,
|
|
3616
|
+
Span<const char> *out_remaining = nullptr);
|
|
3617
|
+
|
|
3618
|
+
static inline Size EncodeUtf8(int32_t c, char out_buf[4])
|
|
3619
|
+
{
|
|
3620
|
+
if (c < 0x80) {
|
|
3621
|
+
out_buf[0] = (char)c;
|
|
3622
|
+
return 1;
|
|
3623
|
+
} else if (c < 0x800) {
|
|
3624
|
+
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
3625
|
+
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
3626
|
+
return 2;
|
|
3627
|
+
} else if (c >= 0xD800 && c < 0xE000) {
|
|
3628
|
+
return 0;
|
|
3629
|
+
} else if (c < 0x10000) {
|
|
3630
|
+
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
3631
|
+
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3632
|
+
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
3633
|
+
return 3;
|
|
3634
|
+
} else if (c < 0x110000) {
|
|
3635
|
+
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
3636
|
+
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
3637
|
+
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3638
|
+
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
3639
|
+
return 4;
|
|
3640
|
+
} else {
|
|
3641
|
+
return 0;
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
static inline int CountUtf8Bytes(char c)
|
|
3646
|
+
{
|
|
3647
|
+
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
3648
|
+
return std::min(std::max(ones, 1), 4);
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
static inline Size DecodeUtf8(const char *str, int32_t *out_c)
|
|
3652
|
+
{
|
|
3653
|
+
RG_ASSERT(str[0]);
|
|
3654
|
+
|
|
3655
|
+
const uint8_t *ptr = (const uint8_t *)str;
|
|
3656
|
+
|
|
3657
|
+
if (ptr[0] < 0x80) {
|
|
3658
|
+
*out_c = ptr[0];
|
|
3659
|
+
return 1;
|
|
3660
|
+
} else if (RG_UNLIKELY(ptr[0] - 0xC2 > 0xF4 - 0xC2)) {
|
|
3661
|
+
return 0;
|
|
3662
|
+
} else if (RG_LIKELY(ptr[1])) {
|
|
3663
|
+
if (ptr[0] < 0xE0 && (ptr[1] & 0xC0) == 0x80) {
|
|
3664
|
+
*out_c = ((ptr[0] & 0x1F) << 6) | (ptr[1] & 0x3F);
|
|
3665
|
+
return 2;
|
|
3666
|
+
} else if (RG_LIKELY(ptr[2])) {
|
|
3667
|
+
if (ptr[0] < 0xF0 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3668
|
+
(ptr[2] & 0xC0) == 0x80) {
|
|
3669
|
+
*out_c = ((ptr[0] & 0xF) << 12) | ((ptr[1] & 0x3F) << 6) | (ptr[2] & 0x3F);
|
|
3670
|
+
return 3;
|
|
3671
|
+
} else if (RG_LIKELY(ptr[3])) {
|
|
3672
|
+
if ((ptr[1] & 0xC0) == 0x80 &&
|
|
3673
|
+
(ptr[2] & 0xC0) == 0x80 &&
|
|
3674
|
+
(ptr[3] & 0xC0) == 0x80) {
|
|
3675
|
+
*out_c = ((ptr[0] & 0x7) << 18) | ((ptr[1] & 0x3F) << 12) | ((ptr[2] & 0x3F) << 6) | (ptr[3] & 0x3F);
|
|
3676
|
+
return 4;
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
|
|
3682
|
+
return 0;
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3685
|
+
static inline Size DecodeUtf8(Span<const char> str, Size offset, int32_t *out_c)
|
|
3686
|
+
{
|
|
3687
|
+
RG_ASSERT(offset < str.len);
|
|
3688
|
+
|
|
3689
|
+
const uint8_t *ptr = (const uint8_t *)(str.ptr + offset);
|
|
3690
|
+
Size available = str.len - offset;
|
|
3691
|
+
|
|
3692
|
+
if (ptr[0] < 0x80) {
|
|
3693
|
+
*out_c = ptr[0];
|
|
3694
|
+
return 1;
|
|
3695
|
+
} else if (RG_UNLIKELY(ptr[0] - 0xC2 > 0xF4 - 0xC2)) {
|
|
3696
|
+
return 0;
|
|
3697
|
+
} else if (ptr[0] < 0xE0 &&
|
|
3698
|
+
RG_LIKELY(available >= 2 && (ptr[1] & 0xC0) == 0x80)) {
|
|
3699
|
+
*out_c = ((ptr[0] & 0x1F) << 6) | (ptr[1] & 0x3F);
|
|
3700
|
+
return 2;
|
|
3701
|
+
} else if (ptr[0] < 0xF0 &&
|
|
3702
|
+
RG_LIKELY(available >= 3 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3703
|
+
(ptr[2] & 0xC0) == 0x80)) {
|
|
3704
|
+
*out_c = ((ptr[0] & 0xF) << 12) | ((ptr[1] & 0x3F) << 6) | (ptr[2] & 0x3F);
|
|
3705
|
+
return 3;
|
|
3706
|
+
} else if (RG_LIKELY(available >= 4 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3707
|
+
(ptr[2] & 0xC0) == 0x80 &&
|
|
3708
|
+
(ptr[3] & 0xC0) == 0x80)) {
|
|
3709
|
+
*out_c = ((ptr[0] & 0x7) << 18) | ((ptr[1] & 0x3F) << 12) | ((ptr[2] & 0x3F) << 6) | (ptr[3] & 0x3F);
|
|
3710
|
+
return 4;
|
|
3711
|
+
} else {
|
|
3712
|
+
return 0;
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
|
|
3716
|
+
// ------------------------------------------------------------------------
|
|
3717
|
+
// System
|
|
3718
|
+
// ------------------------------------------------------------------------
|
|
3719
|
+
|
|
3720
|
+
#ifdef _WIN32
|
|
3721
|
+
#define RG_PATH_SEPARATORS "\\/"
|
|
3722
|
+
#define RG_PATH_DELIMITER ';'
|
|
3723
|
+
#define RG_SHARED_LIBRARY_EXTENSION ".dll"
|
|
3724
|
+
#else
|
|
3725
|
+
#define RG_PATH_SEPARATORS "/"
|
|
3726
|
+
#define RG_PATH_DELIMITER ':'
|
|
3727
|
+
#define RG_SHARED_LIBRARY_EXTENSION ".so"
|
|
3728
|
+
#endif
|
|
3729
|
+
|
|
3730
|
+
#ifdef _WIN32
|
|
3731
|
+
bool IsWin32Utf8();
|
|
3732
|
+
Size ConvertUtf8ToWin32Wide(Span<const char> str, Span<wchar_t> out_str_w);
|
|
3733
|
+
Size ConvertWin32WideToUtf8(const wchar_t *str_w, Span<char> out_str);
|
|
3734
|
+
char *GetWin32ErrorString(uint32_t error_code = UINT32_MAX);
|
|
3735
|
+
#endif
|
|
3736
|
+
|
|
3737
|
+
void SetEnvironmentVar(const char *name, const char *value);
|
|
3738
|
+
void DeleteEnvironmentVar(const char *name);
|
|
3739
|
+
|
|
3740
|
+
static inline bool IsPathSeparator(char c)
|
|
3741
|
+
{
|
|
3742
|
+
#ifdef _WIN32
|
|
3743
|
+
return c == '/' || c == '\\';
|
|
3744
|
+
#else
|
|
3745
|
+
return c == '/';
|
|
3746
|
+
#endif
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
enum class CompressionType {
|
|
3750
|
+
None,
|
|
3751
|
+
Zlib,
|
|
3752
|
+
Gzip,
|
|
3753
|
+
Brotli
|
|
3754
|
+
};
|
|
3755
|
+
static const char *const CompressionTypeNames[] = {
|
|
3756
|
+
"None",
|
|
3757
|
+
"Zlib",
|
|
3758
|
+
"Gzip",
|
|
3759
|
+
"Brotli"
|
|
3760
|
+
};
|
|
3761
|
+
|
|
3762
|
+
Span<const char> GetPathDirectory(Span<const char> filename);
|
|
3763
|
+
Span<const char> GetPathExtension(Span<const char> filename,
|
|
3764
|
+
CompressionType *out_compression_type = nullptr);
|
|
3765
|
+
CompressionType GetPathCompression(Span<const char> filename);
|
|
3766
|
+
|
|
3767
|
+
Span<char> NormalizePath(Span<const char> path, Span<const char> root_directory, Allocator *alloc);
|
|
3768
|
+
static inline Span<char> NormalizePath(Span<const char> path, Allocator *alloc)
|
|
3769
|
+
{ return NormalizePath(path, {}, alloc); }
|
|
3770
|
+
|
|
3771
|
+
bool PathIsAbsolute(const char *path);
|
|
3772
|
+
bool PathIsAbsolute(Span<const char> path);
|
|
3773
|
+
bool PathContainsDotDot(const char *path);
|
|
3774
|
+
|
|
3775
|
+
enum class StatFlag {
|
|
3776
|
+
IgnoreMissing = 1 << 0,
|
|
3777
|
+
FollowSymlink = 1 << 1
|
|
3778
|
+
};
|
|
3779
|
+
|
|
3780
|
+
enum class FileType {
|
|
3781
|
+
Directory,
|
|
3782
|
+
File,
|
|
3783
|
+
Link,
|
|
3784
|
+
Device,
|
|
3785
|
+
Pipe,
|
|
3786
|
+
Socket
|
|
3787
|
+
};
|
|
3788
|
+
static const char *const FileTypeNames[] = {
|
|
3789
|
+
"Directory",
|
|
3790
|
+
"File",
|
|
3791
|
+
"Link",
|
|
3792
|
+
"Device",
|
|
3793
|
+
"Pipe",
|
|
3794
|
+
"Socket"
|
|
3795
|
+
};
|
|
3796
|
+
|
|
3797
|
+
struct FileInfo {
|
|
3798
|
+
FileType type;
|
|
3799
|
+
|
|
3800
|
+
int64_t size;
|
|
3801
|
+
int64_t mtime;
|
|
3802
|
+
unsigned int mode;
|
|
3803
|
+
};
|
|
3804
|
+
|
|
3805
|
+
enum class StatResult {
|
|
3806
|
+
Success,
|
|
3807
|
+
|
|
3808
|
+
MissingPath,
|
|
3809
|
+
AccessDenied,
|
|
3810
|
+
PartialEnum,
|
|
3811
|
+
CallbackFail,
|
|
3812
|
+
OtherError
|
|
3813
|
+
};
|
|
3814
|
+
|
|
3815
|
+
StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info);
|
|
3816
|
+
static inline StatResult StatFile(const char *filename, FileInfo *out_info)
|
|
3817
|
+
{ return StatFile(filename, 0, out_info); }
|
|
3818
|
+
|
|
3819
|
+
enum class RenameFlag {
|
|
3820
|
+
Overwrite = 1 << 0,
|
|
3821
|
+
Sync = 1 << 1
|
|
3822
|
+
};
|
|
3823
|
+
|
|
3824
|
+
// Sync failures are logged but not reported as errors (function returns true)
|
|
3825
|
+
bool RenameFile(const char *src_filename, const char *dest_filename, unsigned int flags);
|
|
3826
|
+
|
|
3827
|
+
enum class EnumResult {
|
|
3828
|
+
Success,
|
|
3829
|
+
|
|
3830
|
+
MissingPath,
|
|
3831
|
+
AccessDenied,
|
|
3832
|
+
PartialEnum,
|
|
3833
|
+
CallbackFail,
|
|
3834
|
+
OtherError
|
|
3835
|
+
};
|
|
3836
|
+
|
|
3837
|
+
EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_files,
|
|
3838
|
+
FunctionRef<bool(const char *, FileType)> func);
|
|
3839
|
+
bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Size max_files,
|
|
3840
|
+
Allocator *str_alloc, HeapArray<const char *> *out_files);
|
|
3841
|
+
bool IsDirectoryEmpty(const char *dirname);
|
|
3842
|
+
|
|
3843
|
+
bool TestFile(const char *filename);
|
|
3844
|
+
bool TestFile(const char *filename, FileType type);
|
|
3845
|
+
|
|
3846
|
+
bool MatchPathName(const char *path, const char *spec);
|
|
3847
|
+
bool MatchPathSpec(const char *path, const char *spec);
|
|
3848
|
+
|
|
3849
|
+
bool FindExecutableInPath(const char *path, const char *name,
|
|
3850
|
+
Allocator *alloc = nullptr, const char **out_path = nullptr);
|
|
3851
|
+
bool FindExecutableInPath(const char *name, Allocator *alloc = nullptr,
|
|
3852
|
+
const char **out_path = nullptr);
|
|
3620
3853
|
|
|
3621
|
-
|
|
3622
|
-
|
|
3854
|
+
bool SetWorkingDirectory(const char *directory);
|
|
3855
|
+
const char *GetWorkingDirectory();
|
|
3623
3856
|
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
Size i = str.len - 1;
|
|
3627
|
-
Size j = (Size)strlen(suffix) - 1;
|
|
3628
|
-
while (i >= 0 && j >= 0) {
|
|
3629
|
-
if (str[i] != suffix[j])
|
|
3630
|
-
return false;
|
|
3857
|
+
const char *GetApplicationExecutable(); // Can be NULL (EmSDK)
|
|
3858
|
+
const char *GetApplicationDirectory(); // Can be NULL (EmSDK)
|
|
3631
3859
|
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3860
|
+
bool MakeDirectory(const char *directory, bool error_if_exists = true);
|
|
3861
|
+
bool MakeDirectoryRec(Span<const char> directory);
|
|
3862
|
+
bool UnlinkDirectory(const char *directory, bool error_if_missing = false);
|
|
3863
|
+
bool UnlinkFile(const char *filename, bool error_if_missing = false);
|
|
3864
|
+
bool EnsureDirectoryExists(const char *filename);
|
|
3635
3865
|
|
|
3636
|
-
|
|
3637
|
-
|
|
3866
|
+
enum class OpenFlag {
|
|
3867
|
+
Read = 1 << 0,
|
|
3868
|
+
Write = 1 << 1,
|
|
3869
|
+
Append = 1 << 2,
|
|
3638
3870
|
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
if (!needle.len)
|
|
3642
|
-
return 0;
|
|
3643
|
-
if (needle.len > str.len)
|
|
3644
|
-
return -1;
|
|
3871
|
+
Exclusive = 1 << 3
|
|
3872
|
+
};
|
|
3645
3873
|
|
|
3646
|
-
|
|
3874
|
+
enum class OpenResult {
|
|
3875
|
+
Success = 0,
|
|
3647
3876
|
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3877
|
+
MissingPath = 1 << 0,
|
|
3878
|
+
FileExists = 1 << 1,
|
|
3879
|
+
AccessDenied = 1 << 2,
|
|
3880
|
+
OtherError = 1 << 3
|
|
3881
|
+
};
|
|
3652
3882
|
|
|
3653
|
-
|
|
3883
|
+
OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int silent, int *out_fd);
|
|
3884
|
+
OpenResult OpenFile(const char *filename, unsigned int flags, unsigned int silent, FILE **out_fp);
|
|
3885
|
+
|
|
3886
|
+
static inline OpenResult OpenDescriptor(const char *filename, unsigned int flags, int *out_fd)
|
|
3887
|
+
{ return OpenDescriptor(filename, flags, 0, out_fd); }
|
|
3888
|
+
static inline OpenResult OpenFile(const char *filename, unsigned int flags, FILE **out_fp)
|
|
3889
|
+
{ return OpenFile(filename, flags, 0, out_fp); }
|
|
3890
|
+
static inline int OpenDescriptor(const char *filename, unsigned int flags)
|
|
3891
|
+
{
|
|
3892
|
+
int fd = -1;
|
|
3893
|
+
if (OpenDescriptor(filename, flags, &fd) != OpenResult::Success)
|
|
3894
|
+
return -1;
|
|
3895
|
+
return fd;
|
|
3654
3896
|
}
|
|
3655
|
-
static inline
|
|
3897
|
+
static inline FILE *OpenFile(const char *filename, unsigned int flags)
|
|
3656
3898
|
{
|
|
3657
|
-
|
|
3658
|
-
|
|
3899
|
+
FILE *fp;
|
|
3900
|
+
if (OpenFile(filename, flags, &fp) != OpenResult::Success)
|
|
3901
|
+
return nullptr;
|
|
3902
|
+
return fp;
|
|
3659
3903
|
}
|
|
3660
3904
|
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
Size part_len = 0;
|
|
3664
|
-
while (part_len < str.len) {
|
|
3665
|
-
if (str[part_len] == split_char) {
|
|
3666
|
-
if (out_remainder) {
|
|
3667
|
-
*out_remainder = str.Take(part_len + 1, str.len - part_len - 1);
|
|
3668
|
-
}
|
|
3669
|
-
return str.Take(0, part_len);
|
|
3670
|
-
}
|
|
3671
|
-
part_len++;
|
|
3672
|
-
}
|
|
3905
|
+
bool FlushFile(int fd, const char *filename);
|
|
3906
|
+
bool FlushFile(FILE *fp, const char *filename);
|
|
3673
3907
|
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3908
|
+
bool FileIsVt100(FILE *fp);
|
|
3909
|
+
|
|
3910
|
+
#ifdef _WIN32
|
|
3911
|
+
enum class PipeMode {
|
|
3912
|
+
Byte,
|
|
3913
|
+
Message
|
|
3914
|
+
};
|
|
3915
|
+
|
|
3916
|
+
bool CreateOverlappedPipe(bool overlap0, bool overlap1, PipeMode mode, void *out_handles[2]); // HANDLE
|
|
3917
|
+
void CloseHandleSafe(void **handle_ptr); // HANDLE
|
|
3918
|
+
#else
|
|
3919
|
+
void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev = nullptr);
|
|
3920
|
+
|
|
3921
|
+
bool CreatePipe(int pfd[2]);
|
|
3922
|
+
void CloseDescriptorSafe(int *fd_ptr);
|
|
3923
|
+
#endif
|
|
3924
|
+
|
|
3925
|
+
bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()> in_func,
|
|
3926
|
+
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code);
|
|
3927
|
+
bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf, Size max_len,
|
|
3928
|
+
HeapArray<uint8_t> *out_buf, int *out_code);
|
|
3929
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, int *out_code) {
|
|
3930
|
+
return ExecuteCommandLine(cmd_line, {}, {}, out_code);
|
|
3678
3931
|
}
|
|
3679
|
-
static inline
|
|
3932
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf,
|
|
3933
|
+
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
3680
3934
|
{
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
}
|
|
3687
|
-
return MakeSpan(str, part_len);
|
|
3688
|
-
}
|
|
3689
|
-
part_len++;
|
|
3690
|
-
}
|
|
3935
|
+
const auto read_once = [&]() {
|
|
3936
|
+
Span<const uint8_t> buf = in_buf;
|
|
3937
|
+
in_buf = {};
|
|
3938
|
+
return buf;
|
|
3939
|
+
};
|
|
3691
3940
|
|
|
3692
|
-
|
|
3693
|
-
*out_remainder = str + part_len;
|
|
3694
|
-
}
|
|
3695
|
-
return MakeSpan(str, part_len);
|
|
3941
|
+
return ExecuteCommandLine(cmd_line, read_once, out_func, out_code);
|
|
3696
3942
|
}
|
|
3697
|
-
static inline
|
|
3698
|
-
|
|
3699
|
-
static inline Span<const char> SplitStr(const char *str, char split_char, const char **out_remainder = nullptr)
|
|
3700
|
-
{ return SplitStr((char *)str, split_char, (char **)out_remainder); }
|
|
3701
|
-
|
|
3702
|
-
static inline Span<char> SplitStrLine(Span<char> str, Span<char> *out_remainder = nullptr)
|
|
3943
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf,
|
|
3944
|
+
FunctionRef<void(Span<char> buf)> out_func, int *out_code)
|
|
3703
3945
|
{
|
|
3704
|
-
Span<
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
}
|
|
3708
|
-
return part;
|
|
3946
|
+
const auto write = [&](Span<uint8_t> buf) { out_func(buf.As<char>()); };
|
|
3947
|
+
|
|
3948
|
+
return ExecuteCommandLine(cmd_line, in_buf.As<const uint8_t>(), write, out_code);
|
|
3709
3949
|
}
|
|
3710
|
-
static inline
|
|
3950
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf, Size max_len,
|
|
3951
|
+
HeapArray<char> *out_buf, int *out_code)
|
|
3711
3952
|
{
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
part.len--;
|
|
3715
|
-
}
|
|
3716
|
-
return part;
|
|
3953
|
+
return ExecuteCommandLine(cmd_line, in_buf.As<const uint8_t>(), max_len,
|
|
3954
|
+
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
3717
3955
|
}
|
|
3718
|
-
static inline Span<const char> SplitStrLine(Span<const char> str, Span<const char> *out_remainder = nullptr)
|
|
3719
|
-
{ return SplitStrLine(MakeSpan((char *)str.ptr, str.len), (Span<char> *)out_remainder); }
|
|
3720
|
-
static inline Span<const char> SplitStrLine(const char *str, const char **out_remainder = nullptr)
|
|
3721
|
-
{ return SplitStrLine((char *)str, (char **)out_remainder); }
|
|
3722
3956
|
|
|
3723
|
-
|
|
3724
|
-
{
|
|
3725
|
-
Bitset<256> split_mask;
|
|
3726
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3727
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3728
|
-
split_mask.Set(c);
|
|
3729
|
-
}
|
|
3957
|
+
void WaitDelay(int64_t delay);
|
|
3730
3958
|
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3959
|
+
enum class WaitForResult {
|
|
3960
|
+
Interrupt,
|
|
3961
|
+
Message,
|
|
3962
|
+
Timeout
|
|
3963
|
+
};
|
|
3734
3964
|
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
}
|
|
3741
|
-
part_len++;
|
|
3742
|
-
}
|
|
3965
|
+
// After WaitForInterrupt() has been called once (even with timeout 0), a few
|
|
3966
|
+
// signals (such as SIGINT, SIGHUP) and their Windows equivalent will be permanently ignored.
|
|
3967
|
+
// Beware, on Unix platforms, this may not work correctly if not called from the main thread.
|
|
3968
|
+
WaitForResult WaitForInterrupt(int64_t timeout = -1);
|
|
3969
|
+
void SignalWaitFor();
|
|
3743
3970
|
|
|
3744
|
-
|
|
3745
|
-
*out_remainder = str.Take(str.len, 0);
|
|
3746
|
-
}
|
|
3747
|
-
return str;
|
|
3748
|
-
}
|
|
3749
|
-
static inline Span<char> SplitStrAny(char *str, const char *split_chars, char **out_remainder = nullptr)
|
|
3750
|
-
{
|
|
3751
|
-
Bitset<256> split_mask;
|
|
3752
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3753
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3754
|
-
split_mask.Set(c);
|
|
3755
|
-
}
|
|
3971
|
+
int GetCoreCount();
|
|
3756
3972
|
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3973
|
+
#ifndef _WIN32
|
|
3974
|
+
bool DropRootIdentity();
|
|
3975
|
+
#endif
|
|
3976
|
+
#ifdef __linux__
|
|
3977
|
+
bool NotifySystemd();
|
|
3978
|
+
#endif
|
|
3760
3979
|
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3980
|
+
#ifndef _WIN32
|
|
3981
|
+
#define RG_POSIX_RESTART_EINTR(CallCode, ErrorCond) \
|
|
3982
|
+
([&]() { \
|
|
3983
|
+
decltype(CallCode) ret; \
|
|
3984
|
+
while ((ret = (CallCode)) ErrorCond && errno == EINTR); \
|
|
3985
|
+
return ret; \
|
|
3986
|
+
})()
|
|
3987
|
+
#endif
|
|
3769
3988
|
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
return MakeSpan(str, part_len);
|
|
3774
|
-
}
|
|
3775
|
-
static inline Span<const char> SplitStrAny(Span<const char> str, const char *split_chars, Span<const char> *out_remainder = nullptr)
|
|
3776
|
-
{ return SplitStrAny(MakeSpan((char *)str.ptr, str.len), split_chars, (Span<char> *)out_remainder); }
|
|
3777
|
-
static inline Span<const char> SplitStrAny(const char *str, const char *split_chars, const char **out_remainder = nullptr)
|
|
3778
|
-
{ return SplitStrAny((char *)str, split_chars, (char **)out_remainder); }
|
|
3989
|
+
// ------------------------------------------------------------------------
|
|
3990
|
+
// Standard paths
|
|
3991
|
+
// ------------------------------------------------------------------------
|
|
3779
3992
|
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3993
|
+
const char *GetUserConfigPath(const char *name, Allocator *alloc);
|
|
3994
|
+
const char *GetUserCachePath(const char *name, Allocator *alloc);
|
|
3995
|
+
const char *GetTemporaryDirectory();
|
|
3996
|
+
|
|
3997
|
+
const char *FindConfigFile(const char *name, Allocator *alloc, LocalArray<const char *, 4> *out_possibilities = nullptr);
|
|
3998
|
+
|
|
3999
|
+
const char *CreateUniqueFile(Span<const char> directory, const char *prefix, const char *extension,
|
|
4000
|
+
Allocator *alloc, FILE **out_fp = nullptr);
|
|
4001
|
+
const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix, Allocator *alloc);
|
|
4002
|
+
|
|
4003
|
+
// ------------------------------------------------------------------------
|
|
4004
|
+
// Random
|
|
4005
|
+
// ------------------------------------------------------------------------
|
|
4006
|
+
|
|
4007
|
+
class FastRandom {
|
|
4008
|
+
uint64_t state[4];
|
|
4009
|
+
|
|
4010
|
+
public:
|
|
4011
|
+
FastRandom();
|
|
4012
|
+
FastRandom(uint64_t seed);
|
|
3793
4013
|
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
}
|
|
3797
|
-
return str;
|
|
3798
|
-
}
|
|
3799
|
-
static inline Span<const char> SplitStrReverse(const char *str, char split_char,
|
|
3800
|
-
Span<const char> *out_remainder = nullptr)
|
|
3801
|
-
{ return SplitStrReverse(MakeSpan(str, strlen(str)), split_char, out_remainder); }
|
|
4014
|
+
void Fill(void *buf, Size len);
|
|
4015
|
+
void Fill(Span<uint8_t> buf) { Fill(buf.ptr, buf.len); }
|
|
3802
4016
|
|
|
3803
|
-
|
|
3804
|
-
Span<const char> *out_remainder = nullptr)
|
|
3805
|
-
{
|
|
3806
|
-
Bitset<256> split_mask;
|
|
3807
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3808
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3809
|
-
split_mask.Set(c);
|
|
3810
|
-
}
|
|
4017
|
+
int GetInt(int min, int max);
|
|
3811
4018
|
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
4019
|
+
private:
|
|
4020
|
+
uint64_t Next();
|
|
4021
|
+
};
|
|
3815
4022
|
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
return str.Take(remainder_len + 1, str.len - remainder_len - 1);
|
|
3821
|
-
}
|
|
3822
|
-
remainder_len--;
|
|
3823
|
-
}
|
|
4023
|
+
template <int Min = 0, int Max = INT_MAX>
|
|
4024
|
+
class FastRandomInt {
|
|
4025
|
+
RG_STATIC_ASSERT(Min >= 0);
|
|
4026
|
+
RG_STATIC_ASSERT(Max > Min);
|
|
3824
4027
|
|
|
3825
|
-
|
|
3826
|
-
*out_remainder = str.Take(0, 0);
|
|
3827
|
-
}
|
|
3828
|
-
return str;
|
|
3829
|
-
}
|
|
3830
|
-
static inline Span<const char> SplitStrReverseAny(const char *str, const char *split_chars,
|
|
3831
|
-
Span<const char> *out_remainder = nullptr)
|
|
3832
|
-
{ return SplitStrReverseAny(MakeSpan(str, strlen(str)), split_chars, out_remainder); }
|
|
4028
|
+
FastRandom rng;
|
|
3833
4029
|
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
while (str.len && strchr(trim_chars, str[0])) {
|
|
3837
|
-
str.ptr++;
|
|
3838
|
-
str.len--;
|
|
3839
|
-
}
|
|
4030
|
+
public:
|
|
4031
|
+
typedef int result_type;
|
|
3840
4032
|
|
|
3841
|
-
return
|
|
3842
|
-
}
|
|
3843
|
-
static inline Span<char> TrimStrRight(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3844
|
-
{
|
|
3845
|
-
while (str.len && strchr(trim_chars, str[str.len - 1])) {
|
|
3846
|
-
str.len--;
|
|
3847
|
-
}
|
|
4033
|
+
static constexpr int min() { return Min; }
|
|
4034
|
+
static constexpr int max() { return Max; }
|
|
3848
4035
|
|
|
3849
|
-
return
|
|
3850
|
-
}
|
|
3851
|
-
static inline Span<char> TrimStr(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3852
|
-
{
|
|
3853
|
-
str = TrimStrRight(str, trim_chars);
|
|
3854
|
-
str = TrimStrLeft(str, trim_chars);
|
|
4036
|
+
int operator()() { return rng.GetInt(Min, Max); }
|
|
4037
|
+
};
|
|
3855
4038
|
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
static inline
|
|
3859
|
-
|
|
3860
|
-
static inline Span<const char> TrimStrRight(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3861
|
-
{ return TrimStrRight(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
3862
|
-
static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3863
|
-
{ return TrimStr(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
4039
|
+
void ZeroMemorySafe(void *ptr, Size len);
|
|
4040
|
+
void FillRandomSafe(void *buf, Size len);
|
|
4041
|
+
static inline void FillRandomSafe(Span<uint8_t> buf) { FillRandomSafe(buf.ptr, buf.len); }
|
|
4042
|
+
int GetRandomIntSafe(int min, int max);
|
|
3864
4043
|
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
{
|
|
3869
|
-
if (RG_UNLIKELY(!str.len)) {
|
|
3870
|
-
if (flags & (int)ParseFlag::Log) {
|
|
3871
|
-
LogError("Cannot convert empty string to integer");
|
|
3872
|
-
}
|
|
3873
|
-
return false;
|
|
3874
|
-
}
|
|
4044
|
+
// ------------------------------------------------------------------------
|
|
4045
|
+
// Sockets
|
|
4046
|
+
// ------------------------------------------------------------------------
|
|
3875
4047
|
|
|
3876
|
-
|
|
4048
|
+
enum class SocketType {
|
|
4049
|
+
Dual,
|
|
4050
|
+
IPv4,
|
|
4051
|
+
IPv6,
|
|
4052
|
+
Unix
|
|
4053
|
+
};
|
|
4054
|
+
static const char *const SocketTypeNames[] = {
|
|
4055
|
+
"Dual",
|
|
4056
|
+
"IPv4",
|
|
4057
|
+
"IPv6",
|
|
4058
|
+
"Unix"
|
|
4059
|
+
};
|
|
3877
4060
|
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
pos = 1;
|
|
3883
|
-
neg = UINT64_MAX;
|
|
3884
|
-
} else if (str[0] == '+') {
|
|
3885
|
-
pos = 1;
|
|
3886
|
-
}
|
|
3887
|
-
}
|
|
4061
|
+
enum class SocketMode {
|
|
4062
|
+
Stream,
|
|
4063
|
+
Messages
|
|
4064
|
+
};
|
|
3888
4065
|
|
|
3889
|
-
|
|
3890
|
-
unsigned int digit = (unsigned int)(str[pos] - '0');
|
|
3891
|
-
if (RG_UNLIKELY(digit > 9)) {
|
|
3892
|
-
if (!pos || flags & (int)ParseFlag::End) {
|
|
3893
|
-
if (flags & (int)ParseFlag::Log) {
|
|
3894
|
-
LogError("Malformed integer number '%1'", str);
|
|
3895
|
-
}
|
|
3896
|
-
return false;
|
|
3897
|
-
} else {
|
|
3898
|
-
break;
|
|
3899
|
-
}
|
|
3900
|
-
}
|
|
4066
|
+
int OpenIPSocket(SocketType type, int port, SocketMode mode = SocketMode::Stream);
|
|
3901
4067
|
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
goto overflow;
|
|
3905
|
-
value = new_value;
|
|
3906
|
-
}
|
|
3907
|
-
if (RG_UNLIKELY(value > (uint64_t)std::numeric_limits<T>::max()))
|
|
3908
|
-
goto overflow;
|
|
3909
|
-
value = ((value ^ neg) - neg);
|
|
4068
|
+
int OpenUnixSocket(const char *path, SocketMode mode = SocketMode::Stream);
|
|
4069
|
+
int ConnectToUnixSocket(const char *path, SocketMode mode = SocketMode::Stream);
|
|
3910
4070
|
|
|
3911
|
-
|
|
3912
|
-
*out_remaining = str.Take(pos, str.len - pos);
|
|
3913
|
-
}
|
|
3914
|
-
*out_value = (T)value;
|
|
3915
|
-
return true;
|
|
4071
|
+
void CloseSocket(int fd);
|
|
3916
4072
|
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
std::numeric_limits<T>::max());
|
|
3921
|
-
}
|
|
3922
|
-
return false;
|
|
3923
|
-
}
|
|
4073
|
+
// ------------------------------------------------------------------------
|
|
4074
|
+
// Tasks
|
|
4075
|
+
// ------------------------------------------------------------------------
|
|
3924
4076
|
|
|
3925
|
-
|
|
3926
|
-
|
|
4077
|
+
class Async {
|
|
4078
|
+
RG_DELETE_COPY(Async)
|
|
3927
4079
|
|
|
3928
|
-
|
|
3929
|
-
{
|
|
3930
|
-
|
|
3931
|
-
out_buf[0] = (char)c;
|
|
3932
|
-
return 1;
|
|
3933
|
-
} else if (c < 0x800) {
|
|
3934
|
-
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
3935
|
-
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
3936
|
-
return 2;
|
|
3937
|
-
} else if (c >= 0xD800 && c < 0xE000) {
|
|
3938
|
-
return 0;
|
|
3939
|
-
} else if (c < 0x10000) {
|
|
3940
|
-
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
3941
|
-
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3942
|
-
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
3943
|
-
return 3;
|
|
3944
|
-
} else if (c < 0x110000) {
|
|
3945
|
-
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
3946
|
-
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
3947
|
-
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3948
|
-
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
3949
|
-
return 4;
|
|
3950
|
-
} else {
|
|
3951
|
-
return 0;
|
|
3952
|
-
}
|
|
3953
|
-
}
|
|
4080
|
+
bool stop_after_error;
|
|
4081
|
+
std::atomic_bool success {true};
|
|
4082
|
+
std::atomic_int remaining_tasks {0};
|
|
3954
4083
|
|
|
3955
|
-
|
|
3956
|
-
{
|
|
3957
|
-
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
3958
|
-
return std::min(std::max(ones, 1), 4);
|
|
3959
|
-
}
|
|
4084
|
+
class AsyncPool *pool;
|
|
3960
4085
|
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
4086
|
+
public:
|
|
4087
|
+
Async(int threads = -1, bool stop_after_error = true);
|
|
4088
|
+
Async(Async *parent, bool stop_after_error = true);
|
|
4089
|
+
~Async();
|
|
3964
4090
|
|
|
3965
|
-
|
|
3966
|
-
|
|
4091
|
+
void Run(const std::function<bool()> &f);
|
|
4092
|
+
bool Sync();
|
|
3967
4093
|
|
|
3968
|
-
|
|
3969
|
-
*out_c = ptr[0];
|
|
3970
|
-
return 1;
|
|
3971
|
-
} else if (RG_UNLIKELY(ptr[0] - 0xC2 > 0xF4 - 0xC2)) {
|
|
3972
|
-
return 0;
|
|
3973
|
-
} else if (ptr[0] < 0xE0 &&
|
|
3974
|
-
RG_LIKELY(available >= 2 && (ptr[1] & 0xC0) == 0x80)) {
|
|
3975
|
-
*out_c = ((ptr[0] & 0x1F) << 6) | (ptr[1] & 0x3F);
|
|
3976
|
-
return 2;
|
|
3977
|
-
} else if (ptr[0] < 0xF0 &&
|
|
3978
|
-
RG_LIKELY(available >= 3 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3979
|
-
(ptr[2] & 0xC0) == 0x80)) {
|
|
3980
|
-
*out_c = ((ptr[0] & 0xF) << 12) | ((ptr[1] & 0x3F) << 6) | (ptr[2] & 0x3F);
|
|
3981
|
-
return 3;
|
|
3982
|
-
} else if (RG_LIKELY(available >= 4 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3983
|
-
(ptr[2] & 0xC0) == 0x80 &&
|
|
3984
|
-
(ptr[3] & 0xC0) == 0x80)) {
|
|
3985
|
-
*out_c = ((ptr[0] & 0x7) << 18) | ((ptr[1] & 0x3F) << 12) | ((ptr[2] & 0x3F) << 6) | (ptr[3] & 0x3F);
|
|
3986
|
-
return 4;
|
|
3987
|
-
} else {
|
|
3988
|
-
return 0;
|
|
3989
|
-
}
|
|
3990
|
-
}
|
|
4094
|
+
int CountPendingTasks();
|
|
3991
4095
|
|
|
3992
|
-
static
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
4096
|
+
static bool IsTaskRunning();
|
|
4097
|
+
static int GetWorkerIdx();
|
|
4098
|
+
static int GetWorkerCount();
|
|
4099
|
+
|
|
4100
|
+
friend class AsyncPool;
|
|
4101
|
+
};
|
|
3997
4102
|
|
|
3998
4103
|
// ------------------------------------------------------------------------
|
|
3999
|
-
//
|
|
4104
|
+
// Fibers
|
|
4000
4105
|
// ------------------------------------------------------------------------
|
|
4001
4106
|
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
#define RG_PATH_DELIMITER ';'
|
|
4005
|
-
#define RG_SHARED_LIBRARY_EXTENSION ".dll"
|
|
4006
|
-
#else
|
|
4007
|
-
#define RG_PATH_SEPARATORS "/"
|
|
4008
|
-
#define RG_PATH_DELIMITER ':'
|
|
4009
|
-
#define RG_SHARED_LIBRARY_EXTENSION ".so"
|
|
4010
|
-
#endif
|
|
4011
|
-
|
|
4012
|
-
#ifdef _WIN32
|
|
4013
|
-
bool IsWin32Utf8();
|
|
4014
|
-
Size ConvertUtf8ToWin32Wide(Span<const char> str, Span<wchar_t> out_str_w);
|
|
4015
|
-
Size ConvertWin32WideToUtf8(const wchar_t *str_w, Span<char> out_str);
|
|
4016
|
-
char *GetWin32ErrorString(uint32_t error_code = UINT32_MAX);
|
|
4017
|
-
#endif
|
|
4107
|
+
class Fiber {
|
|
4108
|
+
RG_DELETE_COPY(Fiber)
|
|
4018
4109
|
|
|
4019
|
-
|
|
4020
|
-
void DeleteEnvironmentVar(const char *name);
|
|
4110
|
+
std::function<bool()> f;
|
|
4021
4111
|
|
|
4022
|
-
static inline bool IsPathSeparator(char c)
|
|
4023
|
-
{
|
|
4024
4112
|
#ifdef _WIN32
|
|
4025
|
-
|
|
4113
|
+
void *fiber = nullptr;
|
|
4114
|
+
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4115
|
+
ucontext_t ucp = {};
|
|
4026
4116
|
#else
|
|
4027
|
-
|
|
4117
|
+
std::thread thread;
|
|
4118
|
+
|
|
4119
|
+
std::mutex mutex;
|
|
4120
|
+
std::condition_variable cv;
|
|
4121
|
+
std::unique_lock<std::mutex> lock { mutex };
|
|
4122
|
+
int toggle = 1;
|
|
4028
4123
|
#endif
|
|
4029
|
-
}
|
|
4030
4124
|
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
CompressionType *out_compression_type = nullptr);
|
|
4034
|
-
CompressionType GetPathCompression(Span<const char> filename);
|
|
4125
|
+
bool done = true;
|
|
4126
|
+
bool success = false;
|
|
4035
4127
|
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4128
|
+
public:
|
|
4129
|
+
Fiber(const std::function<bool()> &f, Size stack_size = RG_FIBER_DEFAULT_STACK_SIZE);
|
|
4130
|
+
~Fiber();
|
|
4039
4131
|
|
|
4040
|
-
|
|
4041
|
-
bool
|
|
4042
|
-
bool PathContainsDotDot(const char *path);
|
|
4132
|
+
void SwitchTo();
|
|
4133
|
+
bool Finalize();
|
|
4043
4134
|
|
|
4044
|
-
|
|
4045
|
-
IgnoreMissing = 1 << 0,
|
|
4046
|
-
FollowSymlink = 1 << 1
|
|
4047
|
-
};
|
|
4135
|
+
static bool SwitchBack();
|
|
4048
4136
|
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4137
|
+
private:
|
|
4138
|
+
#if defined(_WIN64)
|
|
4139
|
+
static void FiberCallback(void *udata);
|
|
4140
|
+
#elif defined(_WIN32)
|
|
4141
|
+
static void __stdcall FiberCallback(void *udata);
|
|
4142
|
+
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4143
|
+
static void FiberCallback(unsigned int high, unsigned int low);
|
|
4144
|
+
#else
|
|
4145
|
+
static void ThreadCallback(void *udata);
|
|
4146
|
+
void Toggle(int to, std::unique_lock<std::mutex> *lock);
|
|
4147
|
+
#endif
|
|
4056
4148
|
};
|
|
4057
4149
|
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
int64_t size;
|
|
4062
|
-
int64_t mtime;
|
|
4063
|
-
};
|
|
4150
|
+
// ------------------------------------------------------------------------
|
|
4151
|
+
// Streams
|
|
4152
|
+
// ------------------------------------------------------------------------
|
|
4064
4153
|
|
|
4065
|
-
enum class
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
Complete
|
|
4154
|
+
enum class CompressionSpeed {
|
|
4155
|
+
Default,
|
|
4156
|
+
Slow,
|
|
4157
|
+
Fast
|
|
4070
4158
|
};
|
|
4071
4159
|
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
{ return StatFile(filename, 0, out_info); }
|
|
4160
|
+
class StreamReader {
|
|
4161
|
+
RG_DELETE_COPY(StreamReader)
|
|
4075
4162
|
|
|
4076
|
-
|
|
4077
|
-
|
|
4163
|
+
enum class SourceType {
|
|
4164
|
+
Memory,
|
|
4165
|
+
File,
|
|
4166
|
+
Function
|
|
4167
|
+
};
|
|
4078
4168
|
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Size max_files,
|
|
4082
|
-
Allocator *str_alloc, HeapArray<const char *> *out_files);
|
|
4083
|
-
bool IsDirectoryEmpty(const char *dirname);
|
|
4169
|
+
const char *filename = nullptr;
|
|
4170
|
+
bool error = true;
|
|
4084
4171
|
|
|
4085
|
-
|
|
4086
|
-
|
|
4172
|
+
struct {
|
|
4173
|
+
SourceType type = SourceType::Memory;
|
|
4174
|
+
union U {
|
|
4175
|
+
struct {
|
|
4176
|
+
Span<const uint8_t> buf;
|
|
4177
|
+
Size pos;
|
|
4178
|
+
} memory;
|
|
4179
|
+
struct {
|
|
4180
|
+
FILE *fp;
|
|
4181
|
+
bool owned;
|
|
4182
|
+
} file;
|
|
4183
|
+
std::function<Size(Span<uint8_t> buf)> func;
|
|
4087
4184
|
|
|
4088
|
-
|
|
4089
|
-
|
|
4185
|
+
// StreamReader deals with func destructor
|
|
4186
|
+
U() {}
|
|
4187
|
+
~U() {}
|
|
4188
|
+
} u;
|
|
4090
4189
|
|
|
4091
|
-
bool
|
|
4092
|
-
|
|
4093
|
-
bool FindExecutableInPath(const char *name, Allocator *alloc = nullptr,
|
|
4094
|
-
const char **out_path = nullptr);
|
|
4190
|
+
bool eof = false;
|
|
4191
|
+
} source;
|
|
4095
4192
|
|
|
4096
|
-
|
|
4097
|
-
|
|
4193
|
+
struct {
|
|
4194
|
+
CompressionType type = CompressionType::None;
|
|
4195
|
+
union {
|
|
4196
|
+
struct MinizInflateContext *miniz;
|
|
4197
|
+
struct BrotliDecompressContext *brotli;
|
|
4198
|
+
} u;
|
|
4199
|
+
} compression;
|
|
4098
4200
|
|
|
4099
|
-
|
|
4100
|
-
|
|
4201
|
+
int64_t raw_len = -1;
|
|
4202
|
+
Size raw_read = 0;
|
|
4203
|
+
bool eof = false;
|
|
4101
4204
|
|
|
4102
|
-
|
|
4103
|
-
bool MakeDirectoryRec(Span<const char> directory);
|
|
4104
|
-
bool UnlinkDirectory(const char *directory, bool error_if_missing = false);
|
|
4105
|
-
bool UnlinkFile(const char *filename, bool error_if_missing = false);
|
|
4106
|
-
bool EnsureDirectoryExists(const char *filename);
|
|
4205
|
+
BlockAllocator str_alloc;
|
|
4107
4206
|
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4207
|
+
public:
|
|
4208
|
+
StreamReader() { Close(true); }
|
|
4209
|
+
StreamReader(Span<const uint8_t> buf, const char *filename = nullptr,
|
|
4210
|
+
CompressionType compression_type = CompressionType::None)
|
|
4211
|
+
: StreamReader() { Open(buf, filename, compression_type); }
|
|
4212
|
+
StreamReader(FILE *fp, const char *filename,
|
|
4213
|
+
CompressionType compression_type = CompressionType::None)
|
|
4214
|
+
: StreamReader() { Open(fp, filename, compression_type); }
|
|
4215
|
+
StreamReader(const char *filename,
|
|
4216
|
+
CompressionType compression_type = CompressionType::None)
|
|
4217
|
+
: StreamReader() { Open(filename, compression_type); }
|
|
4218
|
+
StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename = nullptr,
|
|
4219
|
+
CompressionType compression_type = CompressionType::None)
|
|
4220
|
+
: StreamReader() { Open(func, filename, compression_type); }
|
|
4221
|
+
~StreamReader() { Close(true); }
|
|
4112
4222
|
|
|
4113
|
-
|
|
4114
|
-
|
|
4223
|
+
bool Open(Span<const uint8_t> buf, const char *filename = nullptr,
|
|
4224
|
+
CompressionType compression_type = CompressionType::None);
|
|
4225
|
+
bool Open(FILE *fp, const char *filename,
|
|
4226
|
+
CompressionType compression_type = CompressionType::None);
|
|
4227
|
+
OpenResult Open(const char *filename, CompressionType compression_type = CompressionType::None);
|
|
4228
|
+
bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename = nullptr,
|
|
4229
|
+
CompressionType compression_type = CompressionType::None);
|
|
4230
|
+
bool Close() { return Close(false); }
|
|
4115
4231
|
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
bool FlushFile(FILE *fp, const char *filename);
|
|
4232
|
+
// File-specific
|
|
4233
|
+
bool Rewind();
|
|
4119
4234
|
|
|
4120
|
-
|
|
4235
|
+
const char *GetFileName() const { return filename; }
|
|
4236
|
+
CompressionType GetCompressionType() const { return compression.type; }
|
|
4237
|
+
bool IsValid() const { return filename && !error; }
|
|
4238
|
+
bool IsEOF() const { return eof; }
|
|
4121
4239
|
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
Byte,
|
|
4125
|
-
Message
|
|
4126
|
-
};
|
|
4240
|
+
FILE *GetFile() const;
|
|
4241
|
+
int GetDescriptor() const;
|
|
4127
4242
|
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev = nullptr);
|
|
4243
|
+
Size Read(Span<uint8_t> out_buf);
|
|
4244
|
+
Size Read(Span<char> out_buf) { return Read(out_buf.As<uint8_t>()); }
|
|
4245
|
+
Size Read(Size max_len, void *out_buf) { return Read(MakeSpan((uint8_t *)out_buf, max_len)); }
|
|
4132
4246
|
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4247
|
+
Size ReadAll(Size max_len, HeapArray<uint8_t> *out_buf);
|
|
4248
|
+
Size ReadAll(Size max_len, HeapArray<char> *out_buf)
|
|
4249
|
+
{ return ReadAll(max_len, (HeapArray<uint8_t> *)out_buf); }
|
|
4136
4250
|
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf, Size max_len,
|
|
4140
|
-
HeapArray<uint8_t> *out_buf, int *out_code);
|
|
4141
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, int *out_code) {
|
|
4142
|
-
return ExecuteCommandLine(cmd_line, {}, {}, out_code);
|
|
4143
|
-
}
|
|
4144
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf,
|
|
4145
|
-
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
4146
|
-
{
|
|
4147
|
-
const auto read_once = [&]() {
|
|
4148
|
-
Span<const uint8_t> buf = in_buf;
|
|
4149
|
-
in_buf = {};
|
|
4150
|
-
return buf;
|
|
4151
|
-
};
|
|
4251
|
+
int64_t ComputeRawLen();
|
|
4252
|
+
int64_t GetRawRead() const { return raw_read; }
|
|
4152
4253
|
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf,
|
|
4156
|
-
FunctionRef<void(Span<char> buf)> out_func, int *out_code)
|
|
4157
|
-
{
|
|
4158
|
-
const auto write = [&](Span<uint8_t> buf) { out_func(buf.As<char>()); };
|
|
4254
|
+
private:
|
|
4255
|
+
bool Close(bool implicit);
|
|
4159
4256
|
|
|
4160
|
-
|
|
4161
|
-
}
|
|
4162
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf, Size max_len,
|
|
4163
|
-
HeapArray<char> *out_buf, int *out_code)
|
|
4164
|
-
{
|
|
4165
|
-
return ExecuteCommandLine(cmd_line, in_buf.As<const uint8_t>(), max_len,
|
|
4166
|
-
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
4167
|
-
}
|
|
4257
|
+
bool InitDecompressor(CompressionType type);
|
|
4168
4258
|
|
|
4169
|
-
|
|
4259
|
+
Size ReadInflate(Size max_len, void *out_buf);
|
|
4260
|
+
Size ReadBrotli(Size max_len, void *out_buf);
|
|
4170
4261
|
|
|
4171
|
-
|
|
4172
|
-
Interrupt,
|
|
4173
|
-
Message,
|
|
4174
|
-
Timeout
|
|
4262
|
+
Size ReadRaw(Size max_len, void *out_buf);
|
|
4175
4263
|
};
|
|
4176
4264
|
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
return ret; \
|
|
4198
|
-
})()
|
|
4199
|
-
#endif
|
|
4200
|
-
|
|
4201
|
-
// ------------------------------------------------------------------------
|
|
4202
|
-
// Standard paths
|
|
4203
|
-
// ------------------------------------------------------------------------
|
|
4265
|
+
static inline Size ReadFile(const char *filename, CompressionType compression_type, Span<uint8_t> out_buf)
|
|
4266
|
+
{
|
|
4267
|
+
StreamReader st(filename, compression_type);
|
|
4268
|
+
return st.Read(out_buf);
|
|
4269
|
+
}
|
|
4270
|
+
static inline Size ReadFile(const char *filename, Span<uint8_t> out_buf)
|
|
4271
|
+
{
|
|
4272
|
+
StreamReader st(filename);
|
|
4273
|
+
return st.Read(out_buf);
|
|
4274
|
+
}
|
|
4275
|
+
static inline Size ReadFile(const char *filename, CompressionType compression_type, Span<char> out_buf)
|
|
4276
|
+
{
|
|
4277
|
+
StreamReader st(filename, compression_type);
|
|
4278
|
+
return st.Read(out_buf);
|
|
4279
|
+
}
|
|
4280
|
+
static inline Size ReadFile(const char *filename, Span<char> out_buf)
|
|
4281
|
+
{
|
|
4282
|
+
StreamReader st(filename);
|
|
4283
|
+
return st.Read(out_buf);
|
|
4284
|
+
}
|
|
4204
4285
|
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4286
|
+
static inline Size ReadFile(const char *filename, Size max_len, CompressionType compression_type,
|
|
4287
|
+
HeapArray<uint8_t> *out_buf)
|
|
4288
|
+
{
|
|
4289
|
+
StreamReader st(filename, compression_type);
|
|
4290
|
+
return st.ReadAll(max_len, out_buf);
|
|
4291
|
+
}
|
|
4292
|
+
static inline Size ReadFile(const char *filename, Size max_len, HeapArray<uint8_t> *out_buf)
|
|
4293
|
+
{
|
|
4294
|
+
StreamReader st(filename);
|
|
4295
|
+
return st.ReadAll(max_len, out_buf);
|
|
4296
|
+
}
|
|
4297
|
+
static inline Size ReadFile(const char *filename, Size max_len, CompressionType compression_type,
|
|
4298
|
+
HeapArray<char> *out_buf)
|
|
4299
|
+
{
|
|
4300
|
+
StreamReader st(filename, compression_type);
|
|
4301
|
+
return st.ReadAll(max_len, out_buf);
|
|
4302
|
+
}
|
|
4303
|
+
static inline Size ReadFile(const char *filename, Size max_len, HeapArray<char> *out_buf)
|
|
4304
|
+
{
|
|
4305
|
+
StreamReader st(filename);
|
|
4306
|
+
return st.ReadAll(max_len, out_buf);
|
|
4307
|
+
}
|
|
4208
4308
|
|
|
4209
|
-
|
|
4309
|
+
class LineReader {
|
|
4310
|
+
RG_DELETE_COPY(LineReader)
|
|
4210
4311
|
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
const char *CreateTemporaryDirectory(Span<const char> directory, const char *prefix, Allocator *alloc);
|
|
4312
|
+
HeapArray<char> buf;
|
|
4313
|
+
Span<char> view = {};
|
|
4214
4314
|
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4315
|
+
StreamReader *st;
|
|
4316
|
+
bool error;
|
|
4317
|
+
bool eof = false;
|
|
4218
4318
|
|
|
4219
|
-
|
|
4220
|
-
|
|
4319
|
+
Span<char> line = {};
|
|
4320
|
+
int line_number = 0;
|
|
4221
4321
|
|
|
4222
4322
|
public:
|
|
4223
|
-
|
|
4224
|
-
FastRandom(uint64_t seed);
|
|
4323
|
+
LineReader(StreamReader *st) : st(st), error(!st->IsValid()) {}
|
|
4225
4324
|
|
|
4226
|
-
|
|
4227
|
-
|
|
4325
|
+
const char *GetFileName() const { return st->GetFileName(); }
|
|
4326
|
+
int GetLineNumber() const { return line_number; }
|
|
4327
|
+
bool IsValid() const { return !error; }
|
|
4328
|
+
bool IsEOF() const { return eof; }
|
|
4228
4329
|
|
|
4229
|
-
|
|
4330
|
+
bool Next(Span<char> *out_line);
|
|
4331
|
+
bool Next(Span<const char> *out_line) { return Next((Span<char> *)out_line); }
|
|
4230
4332
|
|
|
4231
|
-
|
|
4232
|
-
uint64_t Next();
|
|
4333
|
+
void PushLogFilter();
|
|
4233
4334
|
};
|
|
4234
4335
|
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4336
|
+
enum class StreamWriterFlag {
|
|
4337
|
+
Exclusive = 1 << 0,
|
|
4338
|
+
Atomic = 1 << 1
|
|
4339
|
+
};
|
|
4239
4340
|
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
// ------------------------------------------------------------------------
|
|
4341
|
+
class StreamWriter {
|
|
4342
|
+
RG_DELETE_COPY(StreamWriter)
|
|
4243
4343
|
|
|
4244
|
-
enum class
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
};
|
|
4250
|
-
static const char *const SocketTypeNames[] = {
|
|
4251
|
-
"Dual",
|
|
4252
|
-
"IPv4",
|
|
4253
|
-
"IPv6",
|
|
4254
|
-
"Unix"
|
|
4255
|
-
};
|
|
4344
|
+
enum class DestinationType {
|
|
4345
|
+
Memory,
|
|
4346
|
+
File,
|
|
4347
|
+
Function
|
|
4348
|
+
};
|
|
4256
4349
|
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
Messages
|
|
4260
|
-
};
|
|
4350
|
+
const char *filename = nullptr;
|
|
4351
|
+
bool error = true;
|
|
4261
4352
|
|
|
4262
|
-
|
|
4353
|
+
struct {
|
|
4354
|
+
DestinationType type = DestinationType::Memory;
|
|
4355
|
+
union U {
|
|
4356
|
+
struct {
|
|
4357
|
+
HeapArray<uint8_t> *memory;
|
|
4358
|
+
Size start;
|
|
4359
|
+
} mem;
|
|
4360
|
+
struct {
|
|
4361
|
+
FILE *fp;
|
|
4362
|
+
bool owned;
|
|
4263
4363
|
|
|
4264
|
-
|
|
4265
|
-
|
|
4364
|
+
// Atomic write mode
|
|
4365
|
+
const char *tmp_filename;
|
|
4366
|
+
bool tmp_exclusive;
|
|
4367
|
+
} file;
|
|
4368
|
+
std::function<bool(Span<const uint8_t>)> func;
|
|
4266
4369
|
|
|
4267
|
-
|
|
4370
|
+
// StreamWriter deals with func destructor
|
|
4371
|
+
U() {}
|
|
4372
|
+
~U() {}
|
|
4373
|
+
} u;
|
|
4268
4374
|
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
// ------------------------------------------------------------------------
|
|
4375
|
+
bool vt100;
|
|
4376
|
+
} dest;
|
|
4272
4377
|
|
|
4273
|
-
|
|
4274
|
-
|
|
4378
|
+
struct {
|
|
4379
|
+
CompressionType type = CompressionType::None;
|
|
4380
|
+
CompressionSpeed speed = CompressionSpeed::Default;
|
|
4381
|
+
union {
|
|
4382
|
+
struct MinizDeflateContext *miniz;
|
|
4383
|
+
struct BrotliEncoderStateStruct *brotli;
|
|
4384
|
+
} u;
|
|
4385
|
+
} compression;
|
|
4275
4386
|
|
|
4276
|
-
|
|
4277
|
-
std::atomic_bool success {true};
|
|
4278
|
-
std::atomic_int remaining_tasks {0};
|
|
4387
|
+
int64_t raw_written = 0;
|
|
4279
4388
|
|
|
4280
|
-
|
|
4389
|
+
BlockAllocator str_alloc;
|
|
4281
4390
|
|
|
4282
4391
|
public:
|
|
4283
|
-
|
|
4284
|
-
|
|
4392
|
+
StreamWriter() { Close(true); }
|
|
4393
|
+
StreamWriter(HeapArray<uint8_t> *mem, const char *filename = nullptr,
|
|
4394
|
+
CompressionType compression_type = CompressionType::None,
|
|
4395
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
4396
|
+
: StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
|
|
4397
|
+
StreamWriter(FILE *fp, const char *filename,
|
|
4398
|
+
CompressionType compression_type = CompressionType::None,
|
|
4399
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
4400
|
+
: StreamWriter() { Open(fp, filename, compression_type, compression_speed); }
|
|
4401
|
+
StreamWriter(const char *filename, unsigned int flags = 0,
|
|
4402
|
+
CompressionType compression_type = CompressionType::None,
|
|
4403
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
4404
|
+
: StreamWriter() { Open(filename, flags, compression_type, compression_speed); }
|
|
4405
|
+
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename = nullptr,
|
|
4406
|
+
CompressionType compression_type = CompressionType::None,
|
|
4407
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
4408
|
+
: StreamWriter() { Open(func, filename, compression_type, compression_speed); }
|
|
4409
|
+
~StreamWriter() { Close(true); }
|
|
4285
4410
|
|
|
4286
|
-
|
|
4287
|
-
|
|
4411
|
+
bool Open(HeapArray<uint8_t> *mem, const char *filename = nullptr,
|
|
4412
|
+
CompressionType compression_type = CompressionType::None,
|
|
4413
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
4414
|
+
bool Open(FILE *fp, const char *filename,
|
|
4415
|
+
CompressionType compression_type = CompressionType::None,
|
|
4416
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
4417
|
+
bool Open(const char *filename, unsigned int flags = 0,
|
|
4418
|
+
CompressionType compression_type = CompressionType::None,
|
|
4419
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
4420
|
+
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename = nullptr,
|
|
4421
|
+
CompressionType compression_type = CompressionType::None,
|
|
4422
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
4423
|
+
bool Close() { return Close(false); }
|
|
4288
4424
|
|
|
4289
|
-
|
|
4290
|
-
|
|
4425
|
+
// For compressed streams, Flush may not be complete and only Close() can finalize the file.
|
|
4426
|
+
bool Flush();
|
|
4291
4427
|
|
|
4292
|
-
|
|
4293
|
-
}
|
|
4428
|
+
const char *GetFileName() const { return filename; }
|
|
4429
|
+
CompressionType GetCompressionType() const { return compression.type; }
|
|
4430
|
+
bool IsVt100() const { return dest.vt100; }
|
|
4431
|
+
bool IsValid() const { return filename && !error; }
|
|
4294
4432
|
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
// ------------------------------------------------------------------------
|
|
4433
|
+
FILE *GetFile() const;
|
|
4434
|
+
int GetDescriptor() const;
|
|
4298
4435
|
|
|
4299
|
-
|
|
4300
|
-
|
|
4436
|
+
bool Write(Span<const uint8_t> buf);
|
|
4437
|
+
bool Write(Span<const char> buf) { return Write(buf.As<const uint8_t>()); }
|
|
4438
|
+
bool Write(char buf) { return Write(MakeSpan(&buf, 1)); }
|
|
4439
|
+
bool Write(const void *buf, Size len) { return Write(MakeSpan((const uint8_t *)buf, len)); }
|
|
4301
4440
|
|
|
4302
|
-
|
|
4441
|
+
int64_t GetRawWritten() const { return raw_written; }
|
|
4303
4442
|
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4307
|
-
ucontext_t ucp = {};
|
|
4308
|
-
#else
|
|
4309
|
-
std::thread thread;
|
|
4443
|
+
private:
|
|
4444
|
+
bool Close(bool implicit);
|
|
4310
4445
|
|
|
4311
|
-
|
|
4312
|
-
std::condition_variable cv;
|
|
4313
|
-
std::unique_lock<std::mutex> lock { mutex };
|
|
4314
|
-
int toggle = 1;
|
|
4315
|
-
#endif
|
|
4446
|
+
bool InitCompressor(CompressionType type, CompressionSpeed speed);
|
|
4316
4447
|
|
|
4317
|
-
bool
|
|
4318
|
-
bool
|
|
4448
|
+
bool WriteDeflate(Span<const uint8_t> buf);
|
|
4449
|
+
bool WriteBrotli(Span<const uint8_t> buf);
|
|
4319
4450
|
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
~Fiber();
|
|
4451
|
+
bool WriteRaw(Span<const uint8_t> buf);
|
|
4452
|
+
};
|
|
4323
4453
|
|
|
4324
|
-
|
|
4325
|
-
|
|
4454
|
+
static inline bool WriteFile(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
|
|
4455
|
+
CompressionType compression_type = CompressionType::None)
|
|
4456
|
+
{
|
|
4457
|
+
StreamWriter st(filename, flags, compression_type);
|
|
4458
|
+
st.Write(buf);
|
|
4459
|
+
return st.Close();
|
|
4460
|
+
}
|
|
4461
|
+
static inline bool WriteFile(Span<const char> buf, const char *filename, unsigned int flags = 0,
|
|
4462
|
+
CompressionType compression_type = CompressionType::None)
|
|
4463
|
+
{
|
|
4464
|
+
StreamWriter st(filename, flags, compression_type);
|
|
4465
|
+
st.Write(buf);
|
|
4466
|
+
return st.Close();
|
|
4467
|
+
}
|
|
4326
4468
|
|
|
4327
|
-
|
|
4469
|
+
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer);
|
|
4328
4470
|
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
static void __stdcall FiberCallback(void *udata);
|
|
4334
|
-
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4335
|
-
static void FiberCallback(unsigned int high, unsigned int low);
|
|
4336
|
-
#else
|
|
4337
|
-
static void ThreadCallback(void *udata);
|
|
4338
|
-
void Toggle(int to, std::unique_lock<std::mutex> *lock);
|
|
4339
|
-
#endif
|
|
4340
|
-
};
|
|
4471
|
+
// For convenience, don't close them
|
|
4472
|
+
extern StreamReader stdin_st;
|
|
4473
|
+
extern StreamWriter stdout_st;
|
|
4474
|
+
extern StreamWriter stderr_st;
|
|
4341
4475
|
|
|
4342
4476
|
// ------------------------------------------------------------------------
|
|
4343
4477
|
// INI
|