koffi 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +13 -1
- package/build/qemu/2.1.2/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_x64.tar.gz +0 -0
- package/doc/templates/badges.html +3 -0
- package/package.json +2 -2
- package/src/abi_arm64.cc +35 -1
- package/src/abi_x64_win.cc +2 -8
- package/src/abi_x86.cc +1 -7
- package/src/call.cc +2 -2
- package/src/call.hh +1 -1
- package/src/ffi.hh +1 -1
- package/src/util.hh +6 -0
- package/test/raylib.js +37 -5
- package/vendor/libcc/libcc.cc +488 -254
- package/vendor/libcc/libcc.hh +1463 -1277
- package/vendor/raylib/BINDINGS.md +87 -70
- package/vendor/raylib/CHANGELOG +263 -50
- package/vendor/raylib/CMakeLists.txt +12 -0
- package/vendor/raylib/CMakeOptions.txt +8 -1
- package/vendor/raylib/CONVENTIONS.md +2 -3
- package/vendor/raylib/FAQ.md +137 -0
- package/vendor/raylib/HISTORY.md +62 -29
- package/vendor/raylib/LICENSE +1 -1
- package/vendor/raylib/README.md +22 -17
- package/vendor/raylib/ROADMAP.md +8 -7
- package/vendor/raylib/cmake/CompileDefinitions.cmake +19 -15
- package/vendor/raylib/cmake/GlfwImport.cmake +2 -0
- package/vendor/raylib/cmake/LibraryConfigurations.cmake +22 -16
- package/vendor/raylib/cmake/raylib-config.cmake +52 -49
- package/vendor/raylib/examples/CMakeLists.txt +14 -9
- package/vendor/raylib/examples/Makefile +112 -125
- package/vendor/raylib/examples/Makefile.Android +1 -1
- package/vendor/raylib/examples/Makefile.Web +145 -158
- package/vendor/raylib/examples/README.md +141 -141
- package/vendor/raylib/examples/audio/audio_module_playing.c +9 -4
- package/vendor/raylib/examples/audio/audio_multichannel_sound.c +8 -3
- package/vendor/raylib/examples/audio/audio_music_stream.c +16 -11
- package/vendor/raylib/examples/audio/audio_raw_stream.c +57 -9
- package/vendor/raylib/examples/audio/audio_sound_loading.c +8 -3
- package/vendor/raylib/examples/audio/audio_stream_effects.c +179 -0
- package/vendor/raylib/examples/audio/audio_stream_effects.png +0 -0
- package/vendor/raylib/examples/build.zig +17 -6
- package/vendor/raylib/examples/core/core_2d_camera.c +8 -4
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.c +105 -0
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.png +0 -0
- package/vendor/raylib/examples/core/core_2d_camera_platformer.c +11 -6
- package/vendor/raylib/examples/core/core_3d_camera_first_person.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_free.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_mode.c +8 -3
- package/vendor/raylib/examples/core/core_3d_picking.c +9 -4
- package/vendor/raylib/examples/core/core_basic_screen_manager.c +9 -7
- package/vendor/raylib/examples/core/core_basic_window.c +8 -3
- package/vendor/raylib/examples/core/core_basic_window_web.c +13 -11
- package/vendor/raylib/examples/core/core_custom_frame_control.c +9 -4
- package/vendor/raylib/examples/core/core_custom_logging.c +12 -8
- package/vendor/raylib/examples/core/core_drop_files.c +20 -12
- package/vendor/raylib/examples/core/core_input_gamepad.c +20 -15
- package/vendor/raylib/examples/core/core_input_gestures.c +19 -15
- package/vendor/raylib/examples/core/core_input_keys.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse_wheel.c +8 -3
- package/vendor/raylib/examples/core/core_input_multitouch.c +8 -3
- package/vendor/raylib/examples/core/core_loading_thread.c +10 -6
- package/vendor/raylib/examples/core/core_random_values.c +8 -3
- package/vendor/raylib/examples/core/core_scissor_test.c +8 -3
- package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +9 -4
- package/vendor/raylib/examples/core/core_split_screen.c +8 -3
- package/vendor/raylib/examples/core/core_storage_values.c +109 -3
- package/vendor/raylib/examples/core/core_vr_simulator.c +15 -7
- package/vendor/raylib/examples/core/core_window_flags.c +8 -3
- package/vendor/raylib/examples/core/core_window_letterbox.c +13 -18
- package/vendor/raylib/examples/core/core_window_should_close.c +77 -0
- package/vendor/raylib/examples/core/core_window_should_close.png +0 -0
- package/vendor/raylib/examples/core/core_world_screen.c +9 -4
- package/vendor/raylib/examples/examples_template.c +8 -3
- package/vendor/raylib/examples/models/models_animation.c +11 -7
- package/vendor/raylib/examples/models/models_billboard.c +9 -4
- package/vendor/raylib/examples/models/models_box_collisions.c +8 -3
- package/vendor/raylib/examples/models/models_cubicmap.c +9 -4
- package/vendor/raylib/examples/models/models_first_person_maze.c +9 -4
- package/vendor/raylib/examples/models/models_geometric_shapes.c +8 -3
- package/vendor/raylib/examples/models/models_heightmap.c +9 -4
- package/vendor/raylib/examples/models/models_loading.c +21 -17
- package/vendor/raylib/examples/models/models_loading_gltf.c +15 -41
- package/vendor/raylib/examples/models/models_loading_vox.c +9 -4
- package/vendor/raylib/examples/models/models_mesh_generation.c +71 -58
- package/vendor/raylib/examples/models/models_mesh_picking.c +25 -7
- package/vendor/raylib/examples/models/models_orthographic_projection.c +8 -5
- package/vendor/raylib/examples/models/models_rlgl_solar_system.c +6 -4
- package/vendor/raylib/examples/models/models_skybox.c +16 -12
- package/vendor/raylib/examples/models/models_waving_cubes.c +9 -4
- package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +12 -7
- package/vendor/raylib/examples/models/resources/LICENSE.md +9 -10
- package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +2 -23
- package/vendor/raylib/examples/models/resources/models/gltf/{raylib_32x32.glb → raylib_logo_3d.glb} +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.blend +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.glb +0 -0
- package/vendor/raylib/examples/others/easings_testbed.c +10 -8
- package/vendor/raylib/examples/others/easings_testbed.png +0 -0
- package/vendor/raylib/examples/others/embedded_files_loading.c +10 -5
- package/vendor/raylib/examples/others/embedded_files_loading.png +0 -0
- package/vendor/raylib/examples/others/raylib_opengl_interop.c +10 -6
- package/vendor/raylib/{src/extras/easings.h → examples/others/reasings.h} +38 -38
- package/vendor/raylib/examples/others/rlgl_compute_shader.c +21 -20
- package/vendor/raylib/examples/others/rlgl_compute_shader.png +0 -0
- package/vendor/raylib/examples/others/rlgl_standalone.c +4 -4
- package/vendor/raylib/examples/others/rlgl_standalone.png +0 -0
- package/vendor/raylib/examples/raylib_compile_execute.bat +2 -2
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +1 -1
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/{base_lighting_instanced.vs → lighting_instancing.vs} +2 -2
- package/vendor/raylib/examples/shaders/rlights.h +14 -27
- package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +24 -26
- package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +13 -8
- package/vendor/raylib/examples/shaders/shaders_fog.c +8 -12
- package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_julia_set.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +45 -119
- package/vendor/raylib/examples/shaders/shaders_model_shader.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_palette_switch.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_postprocessing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_raymarching.c +14 -11
- package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_simple_mask.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_spotlight.c +10 -6
- package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_texture_outline.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_texture_waves.c +8 -3
- package/vendor/raylib/{src/extras → examples/shapes}/raygui.h +1290 -1141
- package/vendor/raylib/examples/{others/easings.h → shapes/reasings.h} +40 -40
- package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_collision_area.c +10 -4
- package/vendor/raylib/examples/shapes/shapes_colors_palette.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_ring.c +10 -6
- package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_following_eyes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +14 -5
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.c +355 -0
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.png +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular.ttf +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular_OFL.txt +93 -0
- package/vendor/raylib/examples/text/resources/LICENSE.md +1 -1
- package/vendor/raylib/examples/text/text_codepoints_loading.c +138 -0
- package/vendor/raylib/examples/text/text_codepoints_loading.png +0 -0
- package/vendor/raylib/examples/text/text_draw_3d.c +42 -33
- package/vendor/raylib/examples/text/text_font_filters.c +14 -11
- package/vendor/raylib/examples/text/text_font_loading.c +9 -4
- package/vendor/raylib/examples/text/text_font_sdf.c +9 -4
- package/vendor/raylib/examples/text/text_font_spritefont.c +12 -6
- package/vendor/raylib/examples/text/text_format_text.c +8 -3
- package/vendor/raylib/examples/text/text_input_box.c +8 -3
- package/vendor/raylib/examples/text/text_raylib_fonts.c +9 -4
- package/vendor/raylib/examples/text/text_rectangle_bounds.c +9 -5
- package/vendor/raylib/examples/text/text_unicode.c +9 -7
- package/vendor/raylib/examples/text/text_writing_anim.c +8 -3
- package/vendor/raylib/examples/textures/resources/scarfy_run.gif +0 -0
- package/vendor/raylib/examples/textures/textures_background_scrolling.c +8 -3
- package/vendor/raylib/examples/textures/textures_blend_modes.c +8 -3
- package/vendor/raylib/examples/textures/textures_bunnymark.c +8 -3
- package/vendor/raylib/examples/textures/textures_draw_tiled.c +14 -10
- package/vendor/raylib/examples/textures/textures_fog_of_war.c +154 -0
- package/vendor/raylib/examples/textures/textures_fog_of_war.png +0 -0
- package/vendor/raylib/examples/textures/textures_gif_player.c +121 -0
- package/vendor/raylib/examples/textures/textures_gif_player.png +0 -0
- package/vendor/raylib/examples/textures/textures_image_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_generation.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_loading.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_processing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_text.c +8 -3
- package/vendor/raylib/examples/textures/textures_logo_raylib.c +8 -3
- package/vendor/raylib/examples/textures/textures_mouse_painting.c +9 -4
- package/vendor/raylib/examples/textures/textures_npatch_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_particles_blending.c +8 -3
- package/vendor/raylib/examples/textures/textures_polygon.c +9 -5
- package/vendor/raylib/examples/textures/textures_raw_data.c +8 -3
- package/vendor/raylib/examples/textures/{textures_rectangle.c → textures_sprite_anim.c} +11 -5
- package/vendor/raylib/examples/textures/{textures_rectangle.png → textures_sprite_anim.png} +0 -0
- package/vendor/raylib/examples/textures/textures_sprite_button.c +8 -3
- package/vendor/raylib/examples/textures/textures_sprite_explosion.c +8 -3
- package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +8 -3
- package/vendor/raylib/examples/textures/textures_to_image.c +8 -3
- package/vendor/raylib/parser/LICENSE +1 -1
- package/vendor/raylib/parser/Makefile +28 -0
- package/vendor/raylib/parser/README.md +49 -5
- package/vendor/raylib/parser/output/raylib_api.json +10717 -0
- package/vendor/raylib/parser/output/raylib_api.lua +7435 -0
- package/vendor/raylib/parser/{raylib_api.txt → output/raylib_api.txt} +1371 -824
- package/vendor/raylib/parser/{raylib_api.xml → output/raylib_api.xml} +827 -595
- package/vendor/raylib/parser/raylib_parser.c +1174 -196
- package/vendor/raylib/projects/4coder/Makefile +2 -4
- package/vendor/raylib/projects/4coder/main.c +0 -1
- package/vendor/raylib/projects/CMake/CMakeLists.txt +13 -16
- package/vendor/raylib/projects/CMake/README.md +27 -0
- package/vendor/raylib/projects/CMake/core_basic_window.c +52 -31
- package/vendor/raylib/projects/CodeBlocks/README.md +4 -4
- package/vendor/raylib/projects/Geany/core_basic_window.c +1 -1
- package/vendor/raylib/projects/Notepad++/c_raylib.xml +168 -128
- package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +168 -84
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +67 -51
- package/vendor/raylib/projects/README.md +1 -1
- package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +1 -1
- package/vendor/raylib/projects/VSCode/Makefile +8 -11
- package/vendor/raylib/projects/VSCode/main.c +53 -26
- package/vendor/raylib/projects/VSCode/resources/LICENSE +1 -0
- package/vendor/raylib/projects/scripts/build-linux.sh +6 -6
- package/vendor/raylib/projects/scripts/build-osx.sh +6 -6
- package/vendor/raylib/projects/scripts/build-rpi.sh +6 -6
- package/vendor/raylib/projects/scripts/build-windows.bat +2 -2
- package/vendor/raylib/src/CMakeLists.txt +6 -7
- package/vendor/raylib/src/Makefile +209 -103
- package/vendor/raylib/src/build.zig +56 -20
- package/vendor/raylib/src/config.h +32 -27
- package/vendor/raylib/src/external/cgltf.h +342 -104
- package/vendor/raylib/src/external/dr_wav.h +487 -225
- package/vendor/raylib/src/external/glfw/src/posix_time.c +1 -3
- package/vendor/raylib/src/external/glfw/src/wl_init.c +1 -3
- package/vendor/raylib/src/external/jar_xm.h +2 -1
- package/vendor/raylib/src/external/miniaudio.h +62251 -42061
- package/vendor/raylib/src/external/qoi.h +671 -0
- package/vendor/raylib/src/external/stb_vorbis.h +1 -1
- package/vendor/raylib/src/external/vox_loader.h +30 -25
- package/vendor/raylib/src/minshell.html +82 -0
- package/vendor/raylib/src/raudio.c +359 -201
- package/vendor/raylib/src/raylib.dll.rc +5 -5
- package/vendor/raylib/src/raylib.dll.rc.data +0 -0
- package/vendor/raylib/src/raylib.h +95 -63
- package/vendor/raylib/src/raylib.rc +5 -5
- package/vendor/raylib/src/raylib.rc.data +0 -0
- package/vendor/raylib/src/raymath.h +391 -133
- package/vendor/raylib/src/rcamera.h +32 -41
- package/vendor/raylib/src/rcore.c +775 -471
- package/vendor/raylib/src/rgestures.h +5 -5
- package/vendor/raylib/src/rglfw.c +3 -3
- package/vendor/raylib/src/rlgl.h +184 -144
- package/vendor/raylib/src/rmodels.c +207 -144
- package/vendor/raylib/src/rshapes.c +105 -47
- package/vendor/raylib/src/rtext.c +255 -38
- package/vendor/raylib/src/rtextures.c +167 -71
- package/vendor/raylib/src/shell.html +63 -63
- package/vendor/raylib/src/utils.c +49 -3
- package/vendor/raylib/src/utils.h +3 -3
- package/build/qemu/2.1.0/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_x64.tar.gz +0 -0
- package/vendor/raylib/CONTRIBUTORS.md +0 -63
- package/vendor/raylib/SPONSORS.md +0 -68
- package/vendor/raylib/examples/core/core_quat_conversion.c +0 -132
- package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +0 -118
- package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
- package/vendor/raylib/examples/models/rlights.h +0 -183
- package/vendor/raylib/examples/others/raudio_standalone.c +0 -152
- package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
- package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
- package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
- package/vendor/raylib/examples/physics/physics_demo.c +0 -128
- package/vendor/raylib/examples/physics/physics_demo.png +0 -0
- package/vendor/raylib/examples/physics/physics_friction.c +0 -142
- package/vendor/raylib/examples/physics/physics_friction.png +0 -0
- package/vendor/raylib/examples/physics/physics_movement.c +0 -128
- package/vendor/raylib/examples/physics/physics_movement.png +0 -0
- package/vendor/raylib/examples/physics/physics_restitution.c +0 -129
- package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
- package/vendor/raylib/examples/physics/physics_shatter.c +0 -111
- package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
- package/vendor/raylib/parser/raylib_api.json +0 -6668
- package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
- package/vendor/raylib/projects/VS2019/raylib/resource.h +0 -14
- package/vendor/raylib/src/extras/physac.h +0 -1977
- package/vendor/raylib/src/extras/rmem.h +0 -751
- package/vendor/raylib/src/raudio.h +0 -198
package/vendor/libcc/libcc.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,28 +824,27 @@ 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
|
-
virtual void Resize(void
|
|
841
|
-
virtual void Release(void *ptr, Size size) = 0;
|
|
840
|
+
virtual void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) = 0;
|
|
841
|
+
virtual void Release(const void *ptr, Size size) = 0;
|
|
842
842
|
};
|
|
843
843
|
|
|
844
844
|
Allocator *GetDefaultAllocator();
|
|
845
845
|
Allocator *GetNullAllocator();
|
|
846
846
|
|
|
847
|
-
|
|
848
|
-
Span<T> AllocateMemory(Allocator *alloc, Size size, unsigned int flags = 0)
|
|
847
|
+
static inline void *AllocateRaw(Allocator *alloc, Size size, unsigned int flags = 0)
|
|
849
848
|
{
|
|
850
849
|
RG_ASSERT(size >= 0);
|
|
851
850
|
|
|
@@ -853,13 +852,40 @@ Span<T> AllocateMemory(Allocator *alloc, Size size, unsigned int flags = 0)
|
|
|
853
852
|
alloc = GetDefaultAllocator();
|
|
854
853
|
}
|
|
855
854
|
|
|
855
|
+
void *ptr = alloc->Allocate(size, flags);
|
|
856
|
+
return ptr;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
template <typename T>
|
|
860
|
+
T *AllocateOne(Allocator *alloc, unsigned int flags = 0)
|
|
861
|
+
{
|
|
862
|
+
if (!alloc) {
|
|
863
|
+
alloc = GetDefaultAllocator();
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
Size size = RG_SIZE(T);
|
|
867
|
+
|
|
856
868
|
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
857
|
-
return
|
|
869
|
+
return ptr;
|
|
858
870
|
}
|
|
859
871
|
|
|
860
872
|
template <typename T>
|
|
861
|
-
Span<T>
|
|
862
|
-
|
|
873
|
+
Span<T> AllocateSpan(Allocator *alloc, Size len, unsigned int flags = 0)
|
|
874
|
+
{
|
|
875
|
+
RG_ASSERT(len >= 0);
|
|
876
|
+
|
|
877
|
+
if (!alloc) {
|
|
878
|
+
alloc = GetDefaultAllocator();
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
Size size = len * RG_SIZE(T);
|
|
882
|
+
|
|
883
|
+
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
884
|
+
return MakeSpan(ptr, len);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
static inline void *ResizeRaw(Allocator *alloc, void *ptr, Size old_size, Size new_size,
|
|
888
|
+
unsigned int flags = 0)
|
|
863
889
|
{
|
|
864
890
|
RG_ASSERT(new_size >= 0);
|
|
865
891
|
|
|
@@ -867,28 +893,56 @@ Span<T> ResizeMemory(Allocator *alloc, T *ptr, Size old_size, Size new_size,
|
|
|
867
893
|
alloc = GetDefaultAllocator();
|
|
868
894
|
}
|
|
869
895
|
|
|
870
|
-
alloc->Resize(
|
|
871
|
-
return
|
|
896
|
+
ptr = alloc->Resize(ptr, old_size, new_size, flags);
|
|
897
|
+
return ptr;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
template <typename T>
|
|
901
|
+
Span<T> ResizeSpan(Allocator *alloc, Span<T> mem, Size new_len,
|
|
902
|
+
unsigned int flags = 0)
|
|
903
|
+
{
|
|
904
|
+
RG_ASSERT(new_len >= 0);
|
|
905
|
+
|
|
906
|
+
if (!alloc) {
|
|
907
|
+
alloc = GetDefaultAllocator();
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
Size old_size = mem.len * RG_SIZE(T);
|
|
911
|
+
Size new_size = new_len * RG_SIZE(T);
|
|
912
|
+
|
|
913
|
+
mem.ptr = (T *)alloc->Resize(mem.ptr, old_size, new_size, flags);
|
|
914
|
+
return MakeSpan(mem.ptr, new_len);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
static inline void ReleaseRaw(Allocator *alloc, const void *ptr, Size size)
|
|
918
|
+
{
|
|
919
|
+
if (!alloc) {
|
|
920
|
+
alloc = GetDefaultAllocator();
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
alloc->Release(ptr, size);
|
|
872
924
|
}
|
|
873
925
|
|
|
874
926
|
template<typename T>
|
|
875
|
-
void
|
|
927
|
+
void ReleaseOne(Allocator *alloc, T *ptr)
|
|
876
928
|
{
|
|
877
929
|
if (!alloc) {
|
|
878
930
|
alloc = GetDefaultAllocator();
|
|
879
931
|
}
|
|
880
932
|
|
|
881
|
-
alloc->Release((void *)
|
|
933
|
+
alloc->Release((void *)ptr, RG_SIZE(T));
|
|
882
934
|
}
|
|
883
935
|
|
|
884
936
|
template<typename T>
|
|
885
|
-
void
|
|
937
|
+
void ReleaseSpan(Allocator *alloc, Span<T> mem)
|
|
886
938
|
{
|
|
887
939
|
if (!alloc) {
|
|
888
940
|
alloc = GetDefaultAllocator();
|
|
889
941
|
}
|
|
890
942
|
|
|
891
|
-
|
|
943
|
+
Size size = mem.len * RG_SIZE(T);
|
|
944
|
+
|
|
945
|
+
alloc->Release((void *)mem.ptr, size);
|
|
892
946
|
}
|
|
893
947
|
|
|
894
948
|
class LinkedAllocator final: public Allocator {
|
|
@@ -899,7 +953,7 @@ class LinkedAllocator final: public Allocator {
|
|
|
899
953
|
struct Bucket {
|
|
900
954
|
// Keep head first or stuff will break
|
|
901
955
|
Node head;
|
|
902
|
-
uint8_t data[
|
|
956
|
+
uint8_t data[];
|
|
903
957
|
};
|
|
904
958
|
|
|
905
959
|
Allocator *allocator;
|
|
@@ -917,18 +971,17 @@ public:
|
|
|
917
971
|
void ReleaseAll();
|
|
918
972
|
|
|
919
973
|
void *Allocate(Size size, unsigned int flags = 0) override;
|
|
920
|
-
void Resize(void
|
|
921
|
-
void Release(void *ptr, Size size) override;
|
|
974
|
+
void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) override;
|
|
975
|
+
void Release(const void *ptr, Size size) override;
|
|
922
976
|
|
|
923
977
|
private:
|
|
924
|
-
static Bucket *PointerToBucket(void *ptr)
|
|
925
|
-
{ return (Bucket *)((uint8_t *)ptr - RG_OFFSET_OF(Bucket, data)); }
|
|
978
|
+
static Bucket *PointerToBucket(void *ptr);
|
|
926
979
|
};
|
|
927
980
|
|
|
928
981
|
class BlockAllocatorBase: public Allocator {
|
|
929
982
|
struct Bucket {
|
|
930
983
|
Size used;
|
|
931
|
-
uint8_t data[
|
|
984
|
+
uint8_t data[];
|
|
932
985
|
};
|
|
933
986
|
|
|
934
987
|
Size block_size;
|
|
@@ -944,8 +997,8 @@ public:
|
|
|
944
997
|
}
|
|
945
998
|
|
|
946
999
|
void *Allocate(Size size, unsigned int flags = 0) override;
|
|
947
|
-
void Resize(void
|
|
948
|
-
void Release(void *ptr, Size size) override;
|
|
1000
|
+
void *Resize(void *ptr, Size old_size, Size new_size, unsigned int flags = 0) override;
|
|
1001
|
+
void Release(const void *ptr, Size size) override;
|
|
949
1002
|
|
|
950
1003
|
protected:
|
|
951
1004
|
void CopyFrom(BlockAllocatorBase *other);
|
|
@@ -1315,7 +1368,7 @@ public:
|
|
|
1315
1368
|
len = new_capacity;
|
|
1316
1369
|
}
|
|
1317
1370
|
|
|
1318
|
-
ptr =
|
|
1371
|
+
ptr = (T *)ResizeRaw(allocator, ptr, capacity * RG_SIZE(T), new_capacity * RG_SIZE(T));
|
|
1319
1372
|
capacity = new_capacity;
|
|
1320
1373
|
}
|
|
1321
1374
|
}
|
|
@@ -1327,7 +1380,7 @@ public:
|
|
|
1327
1380
|
}
|
|
1328
1381
|
}
|
|
1329
1382
|
|
|
1330
|
-
|
|
1383
|
+
T *Grow(Size reserve_capacity = 1)
|
|
1331
1384
|
{
|
|
1332
1385
|
RG_ASSERT(capacity >= 0);
|
|
1333
1386
|
RG_ASSERT(reserve_capacity >= 0);
|
|
@@ -1345,6 +1398,8 @@ public:
|
|
|
1345
1398
|
|
|
1346
1399
|
SetCapacity(new_capacity);
|
|
1347
1400
|
}
|
|
1401
|
+
|
|
1402
|
+
return ptr + len;
|
|
1348
1403
|
}
|
|
1349
1404
|
|
|
1350
1405
|
void Trim(Size extra_capacity = 0) { SetCapacity(len + extra_capacity); }
|
|
@@ -1612,9 +1667,9 @@ public:
|
|
|
1612
1667
|
Size bucket_offset = (offset + len) % BucketSize;
|
|
1613
1668
|
|
|
1614
1669
|
if (bucket_idx >= buckets.len) {
|
|
1615
|
-
Bucket *new_bucket =
|
|
1670
|
+
Bucket *new_bucket = AllocateOne<Bucket>(buckets.allocator);
|
|
1616
1671
|
new (&new_bucket->allocator) AllocatorType();
|
|
1617
|
-
new_bucket->values =
|
|
1672
|
+
new_bucket->values = (T *)AllocateRaw(&new_bucket->allocator, BucketSize * RG_SIZE(T));
|
|
1618
1673
|
|
|
1619
1674
|
buckets.Append(new_bucket);
|
|
1620
1675
|
}
|
|
@@ -1731,7 +1786,7 @@ private:
|
|
|
1731
1786
|
void DeleteBucket(Bucket *bucket)
|
|
1732
1787
|
{
|
|
1733
1788
|
bucket->allocator.~AllocatorType();
|
|
1734
|
-
|
|
1789
|
+
ReleaseOne(buckets.allocator, bucket);
|
|
1735
1790
|
}
|
|
1736
1791
|
};
|
|
1737
1792
|
|
|
@@ -2244,10 +2299,10 @@ private:
|
|
|
2244
2299
|
Size old_capacity = capacity;
|
|
2245
2300
|
|
|
2246
2301
|
if (new_capacity) {
|
|
2247
|
-
used =
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
data =
|
|
2302
|
+
used = (size_t *)AllocateRaw(allocator,
|
|
2303
|
+
(new_capacity + (RG_SIZE(size_t) * 8) - 1) / RG_SIZE(size_t),
|
|
2304
|
+
(int)AllocFlag::Zero);
|
|
2305
|
+
data = (ValueType *)AllocateRaw(allocator, new_capacity * RG_SIZE(ValueType));
|
|
2251
2306
|
for (Size i = 0; i < new_capacity; i++) {
|
|
2252
2307
|
new (&data[i]) ValueType();
|
|
2253
2308
|
}
|
|
@@ -2269,9 +2324,8 @@ private:
|
|
|
2269
2324
|
capacity = 0;
|
|
2270
2325
|
}
|
|
2271
2326
|
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
ReleaseMemory(allocator, old_data, old_capacity * RG_SIZE(ValueType));
|
|
2327
|
+
ReleaseRaw(allocator, old_used, (old_capacity + (RG_SIZE(size_t) * 8) - 1) / RG_SIZE(size_t));
|
|
2328
|
+
ReleaseRaw(allocator, old_data, old_capacity * RG_SIZE(ValueType));
|
|
2275
2329
|
}
|
|
2276
2330
|
|
|
2277
2331
|
void MarkUsed(Size idx)
|
|
@@ -2742,723 +2796,411 @@ static const char *const TimeModeNames[] = {
|
|
|
2742
2796
|
TimeSpec DecomposeTime(int64_t time, TimeMode mode = TimeMode::Local);
|
|
2743
2797
|
|
|
2744
2798
|
// ------------------------------------------------------------------------
|
|
2745
|
-
//
|
|
2799
|
+
// Format
|
|
2746
2800
|
// ------------------------------------------------------------------------
|
|
2747
2801
|
|
|
2748
|
-
|
|
2749
|
-
None,
|
|
2750
|
-
Zlib,
|
|
2751
|
-
Gzip,
|
|
2752
|
-
Brotli
|
|
2753
|
-
};
|
|
2754
|
-
static const char *const CompressionTypeNames[] = {
|
|
2755
|
-
"None",
|
|
2756
|
-
"Zlib",
|
|
2757
|
-
"Gzip",
|
|
2758
|
-
"Brotli"
|
|
2759
|
-
};
|
|
2802
|
+
class StreamWriter;
|
|
2760
2803
|
|
|
2761
|
-
enum class
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
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
|
|
2765
2826
|
};
|
|
2766
2827
|
|
|
2767
|
-
class
|
|
2768
|
-
RG_DELETE_COPY(StreamReader)
|
|
2769
|
-
|
|
2770
|
-
enum class SourceType {
|
|
2771
|
-
Memory,
|
|
2772
|
-
File,
|
|
2773
|
-
Function
|
|
2774
|
-
};
|
|
2775
|
-
|
|
2776
|
-
const char *filename = nullptr;
|
|
2777
|
-
bool error = true;
|
|
2778
|
-
|
|
2779
|
-
struct {
|
|
2780
|
-
SourceType type = SourceType::Memory;
|
|
2781
|
-
union U {
|
|
2782
|
-
struct {
|
|
2783
|
-
Span<const uint8_t> buf;
|
|
2784
|
-
Size pos;
|
|
2785
|
-
} memory;
|
|
2786
|
-
struct {
|
|
2787
|
-
FILE *fp;
|
|
2788
|
-
bool owned;
|
|
2789
|
-
} file;
|
|
2790
|
-
std::function<Size(Span<uint8_t> buf)> func;
|
|
2791
|
-
|
|
2792
|
-
// StreamReader deals with func destructor
|
|
2793
|
-
U() {}
|
|
2794
|
-
~U() {}
|
|
2795
|
-
} u;
|
|
2796
|
-
|
|
2797
|
-
bool eof = false;
|
|
2798
|
-
} source;
|
|
2799
|
-
|
|
2800
|
-
struct {
|
|
2801
|
-
CompressionType type = CompressionType::None;
|
|
2802
|
-
union {
|
|
2803
|
-
struct MinizInflateContext *miniz;
|
|
2804
|
-
struct BrotliDecompressContext *brotli;
|
|
2805
|
-
} u;
|
|
2806
|
-
} compression;
|
|
2807
|
-
|
|
2808
|
-
int64_t raw_len = -1;
|
|
2809
|
-
Size raw_read = 0;
|
|
2810
|
-
bool eof = false;
|
|
2811
|
-
|
|
2812
|
-
BlockAllocator str_alloc;
|
|
2813
|
-
|
|
2828
|
+
class FmtArg {
|
|
2814
2829
|
public:
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
Size ReadAll(Size max_len, HeapArray<char> *out_buf)
|
|
2853
|
-
{ return ReadAll(max_len, (HeapArray<uint8_t> *)out_buf); }
|
|
2854
|
-
|
|
2855
|
-
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;
|
|
2856
2867
|
|
|
2857
|
-
|
|
2858
|
-
|
|
2868
|
+
struct {
|
|
2869
|
+
FmtType type;
|
|
2870
|
+
int type_len;
|
|
2871
|
+
const void *ptr;
|
|
2872
|
+
Size len;
|
|
2873
|
+
const char *separator;
|
|
2874
|
+
} span;
|
|
2875
|
+
} u;
|
|
2859
2876
|
|
|
2860
|
-
|
|
2877
|
+
int repeat = 1;
|
|
2878
|
+
int pad_len = 0;
|
|
2879
|
+
char pad_char = 0;
|
|
2861
2880
|
|
|
2862
|
-
|
|
2863
|
-
|
|
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; }
|
|
2864
2900
|
|
|
2865
|
-
|
|
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'); }
|
|
2866
2904
|
};
|
|
2867
2905
|
|
|
2868
|
-
static inline
|
|
2906
|
+
static inline FmtArg FmtBin(uint64_t u)
|
|
2869
2907
|
{
|
|
2870
|
-
|
|
2871
|
-
|
|
2908
|
+
FmtArg arg;
|
|
2909
|
+
arg.type = FmtType::Binary;
|
|
2910
|
+
arg.u.u = u;
|
|
2911
|
+
return arg;
|
|
2872
2912
|
}
|
|
2873
|
-
static inline
|
|
2913
|
+
static inline FmtArg FmtHex(uint64_t u, FmtType type = FmtType::BigHex)
|
|
2874
2914
|
{
|
|
2875
|
-
|
|
2876
|
-
|
|
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;
|
|
2877
2921
|
}
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
StreamReader st(filename, compression_type);
|
|
2881
|
-
return st.Read(out_buf);
|
|
2882
|
-
}
|
|
2883
|
-
static inline Size ReadFile(const char *filename, Span<char> out_buf)
|
|
2922
|
+
|
|
2923
|
+
static inline FmtArg FmtFloat(float f, int min_prec, int max_prec)
|
|
2884
2924
|
{
|
|
2885
|
-
|
|
2886
|
-
|
|
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;
|
|
2887
2931
|
}
|
|
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); }
|
|
2888
2934
|
|
|
2889
|
-
static inline
|
|
2890
|
-
HeapArray<uint8_t> *out_buf)
|
|
2935
|
+
static inline FmtArg FmtDouble(double d, int min_prec, int max_prec)
|
|
2891
2936
|
{
|
|
2892
|
-
|
|
2893
|
-
|
|
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;
|
|
2894
2943
|
}
|
|
2895
|
-
static inline
|
|
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); }
|
|
2946
|
+
|
|
2947
|
+
static inline FmtArg FmtMemSize(int64_t size)
|
|
2896
2948
|
{
|
|
2897
|
-
|
|
2898
|
-
|
|
2949
|
+
FmtArg arg;
|
|
2950
|
+
arg.type = FmtType::MemorySize;
|
|
2951
|
+
arg.u.i = size;
|
|
2952
|
+
return arg;
|
|
2899
2953
|
}
|
|
2900
|
-
static inline
|
|
2901
|
-
HeapArray<char> *out_buf)
|
|
2954
|
+
static inline FmtArg FmtDiskSize(int64_t size)
|
|
2902
2955
|
{
|
|
2903
|
-
|
|
2904
|
-
|
|
2956
|
+
FmtArg arg;
|
|
2957
|
+
arg.type = FmtType::DiskSize;
|
|
2958
|
+
arg.u.i = size;
|
|
2959
|
+
return arg;
|
|
2905
2960
|
}
|
|
2906
|
-
|
|
2961
|
+
|
|
2962
|
+
static inline FmtArg FmtTimeISO(TimeSpec spec, bool ms = false)
|
|
2907
2963
|
{
|
|
2908
|
-
|
|
2909
|
-
|
|
2964
|
+
FmtArg arg;
|
|
2965
|
+
arg.type = FmtType::TimeISO;
|
|
2966
|
+
arg.u.time.spec = spec;
|
|
2967
|
+
arg.u.time.ms = ms;
|
|
2968
|
+
return arg;
|
|
2910
2969
|
}
|
|
2911
2970
|
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
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
|
+
}
|
|
2917
2979
|
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2980
|
+
static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
|
|
2981
|
+
{
|
|
2982
|
+
RG_ASSERT(len < 256);
|
|
2983
|
+
len = std::min(len, (Size)256);
|
|
2921
2984
|
|
|
2922
|
-
|
|
2923
|
-
|
|
2985
|
+
FmtArg arg;
|
|
2986
|
+
arg.type = FmtType::Random;
|
|
2987
|
+
arg.u.random.len = len;
|
|
2988
|
+
arg.u.random.chars = chars;
|
|
2989
|
+
return arg;
|
|
2990
|
+
}
|
|
2924
2991
|
|
|
2925
|
-
|
|
2926
|
-
|
|
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
|
+
}
|
|
2927
3001
|
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
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
|
+
}
|
|
2932
3011
|
|
|
2933
|
-
|
|
2934
|
-
|
|
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); }
|
|
2935
3030
|
|
|
2936
|
-
|
|
3031
|
+
enum class LogLevel {
|
|
3032
|
+
Debug,
|
|
3033
|
+
Info,
|
|
3034
|
+
Warning,
|
|
3035
|
+
Error
|
|
2937
3036
|
};
|
|
2938
3037
|
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
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);
|
|
2943
3045
|
|
|
2944
|
-
|
|
2945
|
-
|
|
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
|
+
}
|
|
2946
3057
|
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
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 *)
|
|
2952
3065
|
|
|
2953
|
-
|
|
2954
|
-
bool error = true;
|
|
3066
|
+
#undef DEFINE_FMT_VARIANT
|
|
2955
3067
|
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
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
|
+
}
|
|
2966
3079
|
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
std::function<bool(Span<const uint8_t>)> func;
|
|
3080
|
+
// PrintLn variants without format strings
|
|
3081
|
+
void PrintLn(StreamWriter *out_st);
|
|
3082
|
+
void PrintLn(FILE *out_fp);
|
|
3083
|
+
void PrintLn();
|
|
2972
3084
|
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
} u;
|
|
3085
|
+
// ------------------------------------------------------------------------
|
|
3086
|
+
// Debug and errors
|
|
3087
|
+
// ------------------------------------------------------------------------
|
|
2977
3088
|
|
|
2978
|
-
|
|
2979
|
-
|
|
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);
|
|
2980
3092
|
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
CompressionSpeed speed = CompressionSpeed::Default;
|
|
2984
|
-
union {
|
|
2985
|
-
struct MinizDeflateContext *miniz;
|
|
2986
|
-
struct BrotliEncoderStateStruct *brotli;
|
|
2987
|
-
} u;
|
|
2988
|
-
} compression;
|
|
3093
|
+
const char *GetQualifiedEnv(const char *name);
|
|
3094
|
+
bool GetDebugFlag(const char *name);
|
|
2989
3095
|
|
|
2990
|
-
|
|
3096
|
+
void LogFmt(LogLevel level, const char *ctx, const char *fmt, Span<const FmtArg> args);
|
|
2991
3097
|
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename = nullptr,
|
|
3007
|
-
CompressionType compression_type = CompressionType::None,
|
|
3008
|
-
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
3009
|
-
: StreamWriter() { Open(func, filename, compression_type, compression_speed); }
|
|
3010
|
-
~StreamWriter() { Close(true); }
|
|
3098
|
+
static inline void Log(LogLevel level, const char *ctx)
|
|
3099
|
+
{
|
|
3100
|
+
LogFmt(level, ctx, "", {});
|
|
3101
|
+
}
|
|
3102
|
+
static inline void Log(LogLevel level, const char *ctx, const char *fmt)
|
|
3103
|
+
{
|
|
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);
|
|
3111
|
+
}
|
|
3011
3112
|
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
// For compressed streams, Flush may not be complete and only Close() can finalize the file.
|
|
3027
|
-
bool Flush();
|
|
3028
|
-
|
|
3029
|
-
const char *GetFileName() const { return filename; }
|
|
3030
|
-
CompressionType GetCompressionType() const { return compression.type; }
|
|
3031
|
-
bool IsVt100() const { return dest.vt100; }
|
|
3032
|
-
bool IsValid() const { return filename && !error; }
|
|
3033
|
-
|
|
3034
|
-
bool Write(Span<const uint8_t> buf);
|
|
3035
|
-
bool Write(Span<const char> buf) { return Write(buf.As<const uint8_t>()); }
|
|
3036
|
-
bool Write(char buf) { return Write(MakeSpan(&buf, 1)); }
|
|
3037
|
-
bool Write(const void *buf, Size len) { return Write(MakeSpan((const uint8_t *)buf, len)); }
|
|
3038
|
-
|
|
3039
|
-
private:
|
|
3040
|
-
bool Close(bool implicit);
|
|
3041
|
-
|
|
3042
|
-
bool InitCompressor(CompressionType type, CompressionSpeed speed);
|
|
3043
|
-
|
|
3044
|
-
bool WriteDeflate(Span<const uint8_t> buf);
|
|
3045
|
-
bool WriteBrotli(Span<const uint8_t> buf);
|
|
3046
|
-
|
|
3047
|
-
bool WriteRaw(Span<const uint8_t> buf);
|
|
3048
|
-
};
|
|
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...); }
|
|
3049
3127
|
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
{
|
|
3053
|
-
StreamWriter st(filename, flags, compression_type);
|
|
3054
|
-
st.Write(buf);
|
|
3055
|
-
return st.Close();
|
|
3056
|
-
}
|
|
3057
|
-
static inline bool WriteFile(Span<const char> buf, const char *filename, unsigned int flags = 0,
|
|
3058
|
-
CompressionType compression_type = CompressionType::None)
|
|
3059
|
-
{
|
|
3060
|
-
StreamWriter st(filename, flags, compression_type);
|
|
3061
|
-
st.Write(buf);
|
|
3062
|
-
return st.Close();
|
|
3063
|
-
}
|
|
3128
|
+
void SetLogHandler(const std::function<LogFunc> &func);
|
|
3129
|
+
void DefaultLogHandler(LogLevel level, const char *ctx, const char *msg);
|
|
3064
3130
|
|
|
3065
|
-
|
|
3131
|
+
void PushLogFilter(const std::function<LogFilterFunc> &func);
|
|
3132
|
+
void PopLogFilter();
|
|
3066
3133
|
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
extern StreamWriter stderr_st;
|
|
3134
|
+
#ifdef _WIN32
|
|
3135
|
+
bool RedirectLogToWindowsEvents(const char *name);
|
|
3136
|
+
#endif
|
|
3071
3137
|
|
|
3072
3138
|
// ------------------------------------------------------------------------
|
|
3073
|
-
//
|
|
3139
|
+
// Strings
|
|
3074
3140
|
// ------------------------------------------------------------------------
|
|
3075
3141
|
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
Buffer,
|
|
3080
|
-
Char,
|
|
3081
|
-
Bool,
|
|
3082
|
-
Integer,
|
|
3083
|
-
Unsigned,
|
|
3084
|
-
Float,
|
|
3085
|
-
Double,
|
|
3086
|
-
Binary,
|
|
3087
|
-
Hexadecimal,
|
|
3088
|
-
MemorySize,
|
|
3089
|
-
DiskSize,
|
|
3090
|
-
Date,
|
|
3091
|
-
TimeISO,
|
|
3092
|
-
TimeNice,
|
|
3093
|
-
Random,
|
|
3094
|
-
FlagNames,
|
|
3095
|
-
FlagOptions,
|
|
3096
|
-
Span
|
|
3097
|
-
};
|
|
3098
|
-
|
|
3099
|
-
class FmtArg {
|
|
3100
|
-
public:
|
|
3101
|
-
FmtType type;
|
|
3102
|
-
union {
|
|
3103
|
-
const char *str1;
|
|
3104
|
-
Span<const char> str2;
|
|
3105
|
-
char buf[32];
|
|
3106
|
-
char ch;
|
|
3107
|
-
bool b;
|
|
3108
|
-
int64_t i;
|
|
3109
|
-
uint64_t u;
|
|
3110
|
-
struct {
|
|
3111
|
-
float value;
|
|
3112
|
-
int min_prec;
|
|
3113
|
-
int max_prec;
|
|
3114
|
-
} f;
|
|
3115
|
-
struct {
|
|
3116
|
-
double value;
|
|
3117
|
-
int min_prec;
|
|
3118
|
-
int max_prec;
|
|
3119
|
-
} d;
|
|
3120
|
-
const void *ptr;
|
|
3121
|
-
LocalDate date;
|
|
3122
|
-
TimeSpec time;
|
|
3123
|
-
Size random_len;
|
|
3124
|
-
struct {
|
|
3125
|
-
uint64_t flags;
|
|
3126
|
-
union {
|
|
3127
|
-
Span<const char *const> names;
|
|
3128
|
-
Span<const struct OptionDesc> options;
|
|
3129
|
-
} u;
|
|
3130
|
-
const char *separator;
|
|
3131
|
-
} flags;
|
|
3132
|
-
|
|
3133
|
-
struct {
|
|
3134
|
-
FmtType type;
|
|
3135
|
-
int type_len;
|
|
3136
|
-
const void *ptr;
|
|
3137
|
-
Size len;
|
|
3138
|
-
const char *separator;
|
|
3139
|
-
} span;
|
|
3140
|
-
} u;
|
|
3141
|
-
|
|
3142
|
-
int repeat = 1;
|
|
3143
|
-
int pad_len = 0;
|
|
3144
|
-
char pad_char = 0;
|
|
3145
|
-
|
|
3146
|
-
FmtArg() = default;
|
|
3147
|
-
FmtArg(std::nullptr_t) : type(FmtType::Str1) { u.str1 = "(null)"; }
|
|
3148
|
-
FmtArg(const char *str) : type(FmtType::Str1) { u.str1 = str ? str : "(null)"; }
|
|
3149
|
-
FmtArg(Span<const char> str) : type(FmtType::Str2) { u.str2 = str; }
|
|
3150
|
-
FmtArg(char c) : type(FmtType::Char) { u.ch = c; }
|
|
3151
|
-
FmtArg(bool b) : type(FmtType::Bool) { u.b = b; }
|
|
3152
|
-
FmtArg(unsigned char i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3153
|
-
FmtArg(short i) : type(FmtType::Integer) { u.i = i; }
|
|
3154
|
-
FmtArg(unsigned short i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3155
|
-
FmtArg(int i) : type(FmtType::Integer) { u.i = i; }
|
|
3156
|
-
FmtArg(unsigned int i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3157
|
-
FmtArg(long i) : type(FmtType::Integer) { u.i = i; }
|
|
3158
|
-
FmtArg(unsigned long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3159
|
-
FmtArg(long long i) : type(FmtType::Integer) { u.i = i; }
|
|
3160
|
-
FmtArg(unsigned long long i) : type(FmtType::Unsigned) { u.u = i; }
|
|
3161
|
-
FmtArg(float f) : type(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
|
|
3162
|
-
FmtArg(double d) : type(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
|
|
3163
|
-
FmtArg(const void *ptr) : type(FmtType::Hexadecimal) { u.u = (uint64_t)ptr; }
|
|
3164
|
-
FmtArg(const LocalDate &date) : type(FmtType::Date) { u.date = date; }
|
|
3165
|
-
|
|
3166
|
-
FmtArg &Repeat(int new_repeat) { repeat = new_repeat; return *this; }
|
|
3167
|
-
FmtArg &Pad(int len, char c = ' ') { pad_char = c; pad_len = len; return *this; }
|
|
3168
|
-
FmtArg &Pad0(int len) { return Pad(len, '0'); }
|
|
3169
|
-
};
|
|
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);
|
|
3170
3145
|
|
|
3171
|
-
static inline
|
|
3146
|
+
static inline bool IsAsciiAlpha(int c)
|
|
3172
3147
|
{
|
|
3173
|
-
|
|
3174
|
-
arg.type = FmtType::Binary;
|
|
3175
|
-
arg.u.u = u;
|
|
3176
|
-
return arg;
|
|
3148
|
+
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
3177
3149
|
}
|
|
3178
|
-
static inline
|
|
3150
|
+
static inline bool IsAsciiDigit(int c)
|
|
3179
3151
|
{
|
|
3180
|
-
|
|
3181
|
-
arg.type = FmtType::Hexadecimal;
|
|
3182
|
-
arg.u.u = u;
|
|
3183
|
-
return arg;
|
|
3152
|
+
return (c >= '0' && c <= '9');
|
|
3184
3153
|
}
|
|
3185
|
-
|
|
3186
|
-
static inline FmtArg FmtFloat(float f, int min_prec, int max_prec)
|
|
3154
|
+
static inline bool IsAsciiAlphaOrDigit(int c)
|
|
3187
3155
|
{
|
|
3188
|
-
|
|
3189
|
-
arg.type = FmtType::Float;
|
|
3190
|
-
arg.u.f.value = f;
|
|
3191
|
-
arg.u.f.min_prec = min_prec;
|
|
3192
|
-
arg.u.f.max_prec = max_prec;
|
|
3193
|
-
return arg;
|
|
3156
|
+
return IsAsciiAlpha(c) || IsAsciiDigit(c);
|
|
3194
3157
|
}
|
|
3195
|
-
static inline
|
|
3196
|
-
static inline FmtArg FmtFloat(float f) { return FmtFloat(f, 0, INT_MAX); }
|
|
3197
|
-
|
|
3198
|
-
static inline FmtArg FmtDouble(double d, int min_prec, int max_prec)
|
|
3158
|
+
static inline bool IsAsciiWhite(int c)
|
|
3199
3159
|
{
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
arg.u.d.value = d;
|
|
3203
|
-
arg.u.d.min_prec = min_prec;
|
|
3204
|
-
arg.u.d.max_prec = max_prec;
|
|
3205
|
-
return arg;
|
|
3160
|
+
return c == ' ' || c == '\t' || c == '\v' ||
|
|
3161
|
+
c == '\n' || c == '\r' || c == '\f';
|
|
3206
3162
|
}
|
|
3207
|
-
static inline FmtArg FmtDouble(double d, int prec) { return FmtDouble(d, prec, prec); }
|
|
3208
|
-
static inline FmtArg FmtDouble(double d) { return FmtDouble(d, 0, INT_MAX); }
|
|
3209
3163
|
|
|
3210
|
-
static inline
|
|
3164
|
+
static inline char UpperAscii(int c)
|
|
3211
3165
|
{
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3166
|
+
if (c >= 'a' && c <= 'z') {
|
|
3167
|
+
return (char)(c - 32);
|
|
3168
|
+
} else {
|
|
3169
|
+
return (char)c;
|
|
3170
|
+
}
|
|
3216
3171
|
}
|
|
3217
|
-
static inline
|
|
3172
|
+
static inline char LowerAscii(int c)
|
|
3218
3173
|
{
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3174
|
+
if (c >= 'A' && c <= 'Z') {
|
|
3175
|
+
return (char)(c + 32);
|
|
3176
|
+
} else {
|
|
3177
|
+
return (char)c;
|
|
3178
|
+
}
|
|
3223
3179
|
}
|
|
3224
3180
|
|
|
3225
|
-
static inline
|
|
3181
|
+
static inline bool TestStr(Span<const char> str1, Span<const char> str2)
|
|
3226
3182
|
{
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
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;
|
|
3231
3190
|
}
|
|
3232
|
-
|
|
3233
|
-
static inline FmtArg FmtTimeNice(TimeSpec spec)
|
|
3191
|
+
static inline bool TestStr(Span<const char> str1, const char *str2)
|
|
3234
3192
|
{
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
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];
|
|
3239
3199
|
}
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
len = std::min(len, (Size)256);
|
|
3245
|
-
|
|
3246
|
-
FmtArg arg;
|
|
3247
|
-
arg.type = FmtType::Random;
|
|
3248
|
-
arg.u.random_len = len;
|
|
3249
|
-
return arg;
|
|
3250
|
-
}
|
|
3251
|
-
|
|
3252
|
-
static inline FmtArg FmtFlags(uint64_t flags, Span<const char *const> names, const char *sep = ", ")
|
|
3253
|
-
{
|
|
3254
|
-
FmtArg arg;
|
|
3255
|
-
arg.type = FmtType::FlagNames;
|
|
3256
|
-
arg.u.flags.flags = flags & ((1ull << names.len) - 1);
|
|
3257
|
-
arg.u.flags.u.names = names;
|
|
3258
|
-
arg.u.flags.separator = sep;
|
|
3259
|
-
return arg;
|
|
3260
|
-
}
|
|
3261
|
-
|
|
3262
|
-
static inline FmtArg FmtFlags(uint64_t flags, Span<const struct OptionDesc> options, const char *sep = ", ")
|
|
3263
|
-
{
|
|
3264
|
-
FmtArg arg;
|
|
3265
|
-
arg.type = FmtType::FlagOptions;
|
|
3266
|
-
arg.u.flags.flags = flags & ((1ull << options.len) - 1);
|
|
3267
|
-
arg.u.flags.u.options = options;
|
|
3268
|
-
arg.u.flags.separator = sep;
|
|
3269
|
-
return arg;
|
|
3270
|
-
}
|
|
3271
|
-
|
|
3272
|
-
template <typename T>
|
|
3273
|
-
FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
|
|
3274
|
-
{
|
|
3275
|
-
FmtArg arg;
|
|
3276
|
-
arg.type = FmtType::Span;
|
|
3277
|
-
arg.u.span.type = type;
|
|
3278
|
-
arg.u.span.type_len = RG_SIZE(T);
|
|
3279
|
-
arg.u.span.ptr = (const void *)arr.ptr;
|
|
3280
|
-
arg.u.span.len = arr.len;
|
|
3281
|
-
arg.u.span.separator = sep;
|
|
3282
|
-
return arg;
|
|
3283
|
-
}
|
|
3284
|
-
template <typename T>
|
|
3285
|
-
FmtArg FmtSpan(Span<T> arr, const char *sep = ", ") { return FmtSpan(arr, FmtArg(T()).type, sep); }
|
|
3286
|
-
template <typename T, Size N>
|
|
3287
|
-
FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSpan(MakeSpan(arr), type, sep); }
|
|
3288
|
-
template <typename T, Size N>
|
|
3289
|
-
FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
|
|
3290
|
-
|
|
3291
|
-
enum class LogLevel {
|
|
3292
|
-
Debug,
|
|
3293
|
-
Info,
|
|
3294
|
-
Warning,
|
|
3295
|
-
Error
|
|
3296
|
-
};
|
|
3297
|
-
|
|
3298
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Span<char> out_buf);
|
|
3299
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, HeapArray<char> *out_buf);
|
|
3300
|
-
Span<char> FmtFmt(const char *fmt, Span<const FmtArg> args, Allocator *alloc);
|
|
3301
|
-
void PrintFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3302
|
-
void PrintFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3303
|
-
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, StreamWriter *out_st);
|
|
3304
|
-
void PrintLnFmt(const char *fmt, Span<const FmtArg> args, FILE *out_fp);
|
|
3305
|
-
|
|
3306
|
-
#define DEFINE_FMT_VARIANT(Name, Ret, Type) \
|
|
3307
|
-
static inline Ret Name(Type out, const char *fmt) \
|
|
3308
|
-
{ \
|
|
3309
|
-
return Name##Fmt(fmt, {}, out); \
|
|
3310
|
-
} \
|
|
3311
|
-
template <typename... Args> \
|
|
3312
|
-
Ret Name(Type out, const char *fmt, Args... args) \
|
|
3313
|
-
{ \
|
|
3314
|
-
const FmtArg fmt_args[] = { FmtArg(args)... }; \
|
|
3315
|
-
return Name##Fmt(fmt, fmt_args, out); \
|
|
3316
|
-
}
|
|
3317
|
-
|
|
3318
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, Span<char>)
|
|
3319
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, HeapArray<char> *)
|
|
3320
|
-
DEFINE_FMT_VARIANT(Fmt, Span<char>, Allocator *)
|
|
3321
|
-
DEFINE_FMT_VARIANT(Print, void, StreamWriter *)
|
|
3322
|
-
DEFINE_FMT_VARIANT(Print, void, FILE *)
|
|
3323
|
-
DEFINE_FMT_VARIANT(PrintLn, void, StreamWriter *)
|
|
3324
|
-
DEFINE_FMT_VARIANT(PrintLn, void, FILE *)
|
|
3325
|
-
|
|
3326
|
-
#undef DEFINE_FMT_VARIANT
|
|
3327
|
-
|
|
3328
|
-
// Print formatted strings to stdout
|
|
3329
|
-
template <typename... Args>
|
|
3330
|
-
void Print(const char *fmt, Args... args)
|
|
3331
|
-
{
|
|
3332
|
-
Print(stdout, fmt, args...);
|
|
3333
|
-
}
|
|
3334
|
-
template <typename... Args>
|
|
3335
|
-
void PrintLn(const char *fmt, Args... args)
|
|
3336
|
-
{
|
|
3337
|
-
PrintLn(stdout, fmt, args...);
|
|
3338
|
-
}
|
|
3339
|
-
|
|
3340
|
-
// PrintLn variants without format strings
|
|
3341
|
-
static inline void PrintLn(StreamWriter *out_st) { out_st->Write('\n'); }
|
|
3342
|
-
static inline void PrintLn(FILE *out_fp) { fputc('\n', out_fp); }
|
|
3343
|
-
static inline void PrintLn() { putchar('\n'); }
|
|
3344
|
-
|
|
3345
|
-
// ------------------------------------------------------------------------
|
|
3346
|
-
// Debug and errors
|
|
3347
|
-
// ------------------------------------------------------------------------
|
|
3348
|
-
|
|
3349
|
-
typedef void LogFunc(LogLevel level, const char *ctx, const char *msg);
|
|
3350
|
-
typedef void LogFilterFunc(LogLevel level, const char *ctx, const char *msg,
|
|
3351
|
-
FunctionRef<LogFunc> func);
|
|
3352
|
-
|
|
3353
|
-
const char *GetQualifiedEnv(const char *name);
|
|
3354
|
-
bool GetDebugFlag(const char *name);
|
|
3355
|
-
|
|
3356
|
-
void LogFmt(LogLevel level, const char *ctx, const char *fmt, Span<const FmtArg> args);
|
|
3357
|
-
|
|
3358
|
-
static inline void Log(LogLevel level, const char *ctx)
|
|
3359
|
-
{
|
|
3360
|
-
LogFmt(level, ctx, "", {});
|
|
3361
|
-
}
|
|
3362
|
-
static inline void Log(LogLevel level, const char *ctx, const char *fmt)
|
|
3363
|
-
{
|
|
3364
|
-
LogFmt(level, ctx, fmt, {});
|
|
3365
|
-
}
|
|
3366
|
-
template <typename... Args>
|
|
3367
|
-
static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args... args)
|
|
3368
|
-
{
|
|
3369
|
-
const FmtArg fmt_args[] = { FmtArg(args)... };
|
|
3370
|
-
LogFmt(level, ctx, fmt, fmt_args);
|
|
3371
|
-
}
|
|
3372
|
-
|
|
3373
|
-
// Shortcut log functions
|
|
3374
|
-
#ifdef RG_DEBUG
|
|
3375
|
-
template <typename... Args>
|
|
3376
|
-
static inline void LogDebug(Args... args) { Log(LogLevel::Debug, "Debug", args...); }
|
|
3377
|
-
#else
|
|
3378
|
-
template <typename... Args>
|
|
3379
|
-
static inline void LogDebug(Args...) {}
|
|
3380
|
-
#endif
|
|
3381
|
-
template <typename... Args>
|
|
3382
|
-
static inline void LogInfo(Args... args) { Log(LogLevel::Info, nullptr, args...); }
|
|
3383
|
-
template <typename... Args>
|
|
3384
|
-
static inline void LogError(Args... args) { Log(LogLevel::Error, "Error", args...); }
|
|
3385
|
-
|
|
3386
|
-
void SetLogHandler(const std::function<LogFunc> &func);
|
|
3387
|
-
void DefaultLogHandler(LogLevel level, const char *ctx, const char *msg);
|
|
3388
|
-
|
|
3389
|
-
void PushLogFilter(const std::function<LogFilterFunc> &func);
|
|
3390
|
-
void PopLogFilter();
|
|
3391
|
-
|
|
3392
|
-
#ifdef _WIN32
|
|
3393
|
-
bool RedirectLogToWindowsEvents(const char *name);
|
|
3394
|
-
#endif
|
|
3395
|
-
|
|
3396
|
-
// ------------------------------------------------------------------------
|
|
3397
|
-
// Strings
|
|
3398
|
-
// ------------------------------------------------------------------------
|
|
3399
|
-
|
|
3400
|
-
bool CopyString(const char *str, Span<char> buf);
|
|
3401
|
-
bool CopyString(Span<const char> str, Span<char> buf);
|
|
3402
|
-
Span<char> DuplicateString(Span<const char> str, Allocator *alloc);
|
|
3403
|
-
|
|
3404
|
-
static inline bool IsAsciiAlpha(int c)
|
|
3405
|
-
{
|
|
3406
|
-
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
3407
|
-
}
|
|
3408
|
-
static inline bool IsAsciiDigit(int c)
|
|
3409
|
-
{
|
|
3410
|
-
return (c >= '0' && c <= '9');
|
|
3411
|
-
}
|
|
3412
|
-
static inline bool IsAsciiAlphaOrDigit(int c)
|
|
3413
|
-
{
|
|
3414
|
-
return IsAsciiAlpha(c) || IsAsciiDigit(c);
|
|
3415
|
-
}
|
|
3416
|
-
static inline bool IsAsciiWhite(int c)
|
|
3417
|
-
{
|
|
3418
|
-
return c == ' ' || c == '\t' || c == '\v' ||
|
|
3419
|
-
c == '\n' || c == '\r' || c == '\f';
|
|
3420
|
-
}
|
|
3421
|
-
|
|
3422
|
-
static inline char UpperAscii(int c)
|
|
3423
|
-
{
|
|
3424
|
-
if (c >= 'a' && c <= 'z') {
|
|
3425
|
-
return (char)(c - 32);
|
|
3426
|
-
} else {
|
|
3427
|
-
return (char)c;
|
|
3428
|
-
}
|
|
3429
|
-
}
|
|
3430
|
-
static inline char LowerAscii(int c)
|
|
3431
|
-
{
|
|
3432
|
-
if (c >= 'A' && c <= 'Z') {
|
|
3433
|
-
return (char)(c + 32);
|
|
3434
|
-
} else {
|
|
3435
|
-
return (char)c;
|
|
3436
|
-
}
|
|
3437
|
-
}
|
|
3438
|
-
|
|
3439
|
-
static inline bool TestStr(Span<const char> str1, Span<const char> str2)
|
|
3440
|
-
{
|
|
3441
|
-
if (str1.len != str2.len)
|
|
3442
|
-
return false;
|
|
3443
|
-
for (Size i = 0; i < str1.len; i++) {
|
|
3444
|
-
if (str1[i] != str2[i])
|
|
3445
|
-
return false;
|
|
3446
|
-
}
|
|
3447
|
-
return true;
|
|
3448
|
-
}
|
|
3449
|
-
static inline bool TestStr(Span<const char> str1, const char *str2)
|
|
3450
|
-
{
|
|
3451
|
-
Size i;
|
|
3452
|
-
for (i = 0; i < str1.len && str2[i]; i++) {
|
|
3453
|
-
if (str1[i] != str2[i])
|
|
3454
|
-
return false;
|
|
3455
|
-
}
|
|
3456
|
-
return (i == str1.len) && !str2[i];
|
|
3457
|
-
}
|
|
3458
|
-
static inline bool TestStr(const char *str1, Span<const char> str2)
|
|
3459
|
-
{ return TestStr(str2, str1); }
|
|
3460
|
-
static inline bool TestStr(const char *str1, const char *str2)
|
|
3461
|
-
{ return !strcmp(str1, str2); }
|
|
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); }
|
|
3462
3204
|
|
|
3463
3205
|
// Allow direct Span<const char> equality comparison
|
|
3464
3206
|
inline bool Span<const char>::operator==(Span<const char> other) const
|
|
@@ -3563,729 +3305,1173 @@ static inline Size StartsWith(const char *str, const char *prefix)
|
|
|
3563
3305
|
if (str[i] != prefix[i])
|
|
3564
3306
|
return 0;
|
|
3565
3307
|
|
|
3566
|
-
i++;
|
|
3567
|
-
}
|
|
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);
|
|
3568
3853
|
|
|
3569
|
-
|
|
3570
|
-
|
|
3854
|
+
bool SetWorkingDirectory(const char *directory);
|
|
3855
|
+
const char *GetWorkingDirectory();
|
|
3571
3856
|
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
Size i = str.len - 1;
|
|
3575
|
-
Size j = (Size)strlen(suffix) - 1;
|
|
3576
|
-
while (i >= 0 && j >= 0) {
|
|
3577
|
-
if (str[i] != suffix[j])
|
|
3578
|
-
return false;
|
|
3857
|
+
const char *GetApplicationExecutable(); // Can be NULL (EmSDK)
|
|
3858
|
+
const char *GetApplicationDirectory(); // Can be NULL (EmSDK)
|
|
3579
3859
|
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
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);
|
|
3583
3865
|
|
|
3584
|
-
|
|
3585
|
-
|
|
3866
|
+
enum class OpenFlag {
|
|
3867
|
+
Read = 1 << 0,
|
|
3868
|
+
Write = 1 << 1,
|
|
3869
|
+
Append = 1 << 2,
|
|
3586
3870
|
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
if (!needle.len)
|
|
3590
|
-
return 0;
|
|
3591
|
-
if (needle.len > str.len)
|
|
3592
|
-
return -1;
|
|
3871
|
+
Exclusive = 1 << 3
|
|
3872
|
+
};
|
|
3593
3873
|
|
|
3594
|
-
|
|
3874
|
+
enum class OpenResult {
|
|
3875
|
+
Success = 0,
|
|
3595
3876
|
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3877
|
+
MissingPath = 1 << 0,
|
|
3878
|
+
FileExists = 1 << 1,
|
|
3879
|
+
AccessDenied = 1 << 2,
|
|
3880
|
+
OtherError = 1 << 3
|
|
3881
|
+
};
|
|
3600
3882
|
|
|
3601
|
-
|
|
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;
|
|
3602
3896
|
}
|
|
3603
|
-
static inline
|
|
3897
|
+
static inline FILE *OpenFile(const char *filename, unsigned int flags)
|
|
3604
3898
|
{
|
|
3605
|
-
|
|
3606
|
-
|
|
3899
|
+
FILE *fp;
|
|
3900
|
+
if (OpenFile(filename, flags, &fp) != OpenResult::Success)
|
|
3901
|
+
return nullptr;
|
|
3902
|
+
return fp;
|
|
3607
3903
|
}
|
|
3608
3904
|
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
Size part_len = 0;
|
|
3612
|
-
while (part_len < str.len) {
|
|
3613
|
-
if (str[part_len] == split_char) {
|
|
3614
|
-
if (out_remainder) {
|
|
3615
|
-
*out_remainder = str.Take(part_len + 1, str.len - part_len - 1);
|
|
3616
|
-
}
|
|
3617
|
-
return str.Take(0, part_len);
|
|
3618
|
-
}
|
|
3619
|
-
part_len++;
|
|
3620
|
-
}
|
|
3905
|
+
bool FlushFile(int fd, const char *filename);
|
|
3906
|
+
bool FlushFile(FILE *fp, const char *filename);
|
|
3621
3907
|
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
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);
|
|
3626
3931
|
}
|
|
3627
|
-
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)
|
|
3628
3934
|
{
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
}
|
|
3635
|
-
return MakeSpan(str, part_len);
|
|
3636
|
-
}
|
|
3637
|
-
part_len++;
|
|
3638
|
-
}
|
|
3935
|
+
const auto read_once = [&]() {
|
|
3936
|
+
Span<const uint8_t> buf = in_buf;
|
|
3937
|
+
in_buf = {};
|
|
3938
|
+
return buf;
|
|
3939
|
+
};
|
|
3639
3940
|
|
|
3640
|
-
|
|
3641
|
-
*out_remainder = str + part_len;
|
|
3642
|
-
}
|
|
3643
|
-
return MakeSpan(str, part_len);
|
|
3941
|
+
return ExecuteCommandLine(cmd_line, read_once, out_func, out_code);
|
|
3644
3942
|
}
|
|
3645
|
-
static inline
|
|
3646
|
-
|
|
3647
|
-
static inline Span<const char> SplitStr(const char *str, char split_char, const char **out_remainder = nullptr)
|
|
3648
|
-
{ return SplitStr((char *)str, split_char, (char **)out_remainder); }
|
|
3649
|
-
|
|
3650
|
-
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)
|
|
3651
3945
|
{
|
|
3652
|
-
Span<
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
}
|
|
3656
|
-
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);
|
|
3657
3949
|
}
|
|
3658
|
-
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)
|
|
3659
3952
|
{
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
part.len--;
|
|
3663
|
-
}
|
|
3664
|
-
return part;
|
|
3953
|
+
return ExecuteCommandLine(cmd_line, in_buf.As<const uint8_t>(), max_len,
|
|
3954
|
+
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
3665
3955
|
}
|
|
3666
|
-
static inline Span<const char> SplitStrLine(Span<const char> str, Span<const char> *out_remainder = nullptr)
|
|
3667
|
-
{ return SplitStrLine(MakeSpan((char *)str.ptr, str.len), (Span<char> *)out_remainder); }
|
|
3668
|
-
static inline Span<const char> SplitStrLine(const char *str, const char **out_remainder = nullptr)
|
|
3669
|
-
{ return SplitStrLine((char *)str, (char **)out_remainder); }
|
|
3670
3956
|
|
|
3671
|
-
|
|
3672
|
-
{
|
|
3673
|
-
Bitset<256> split_mask;
|
|
3674
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3675
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3676
|
-
split_mask.Set(c);
|
|
3677
|
-
}
|
|
3957
|
+
void WaitDelay(int64_t delay);
|
|
3678
3958
|
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3959
|
+
enum class WaitForResult {
|
|
3960
|
+
Interrupt,
|
|
3961
|
+
Message,
|
|
3962
|
+
Timeout
|
|
3963
|
+
};
|
|
3682
3964
|
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
}
|
|
3689
|
-
part_len++;
|
|
3690
|
-
}
|
|
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();
|
|
3691
3970
|
|
|
3692
|
-
|
|
3693
|
-
*out_remainder = str.Take(str.len, 0);
|
|
3694
|
-
}
|
|
3695
|
-
return str;
|
|
3696
|
-
}
|
|
3697
|
-
static inline Span<char> SplitStrAny(char *str, const char *split_chars, char **out_remainder = nullptr)
|
|
3698
|
-
{
|
|
3699
|
-
Bitset<256> split_mask;
|
|
3700
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3701
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3702
|
-
split_mask.Set(c);
|
|
3703
|
-
}
|
|
3971
|
+
int GetCoreCount();
|
|
3704
3972
|
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3973
|
+
#ifndef _WIN32
|
|
3974
|
+
bool DropRootIdentity();
|
|
3975
|
+
#endif
|
|
3976
|
+
#ifdef __linux__
|
|
3977
|
+
bool NotifySystemd();
|
|
3978
|
+
#endif
|
|
3708
3979
|
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
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
|
|
3717
3988
|
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
return MakeSpan(str, part_len);
|
|
3722
|
-
}
|
|
3723
|
-
static inline Span<const char> SplitStrAny(Span<const char> str, const char *split_chars, Span<const char> *out_remainder = nullptr)
|
|
3724
|
-
{ return SplitStrAny(MakeSpan((char *)str.ptr, str.len), split_chars, (Span<char> *)out_remainder); }
|
|
3725
|
-
static inline Span<const char> SplitStrAny(const char *str, const char *split_chars, const char **out_remainder = nullptr)
|
|
3726
|
-
{ return SplitStrAny((char *)str, split_chars, (char **)out_remainder); }
|
|
3989
|
+
// ------------------------------------------------------------------------
|
|
3990
|
+
// Standard paths
|
|
3991
|
+
// ------------------------------------------------------------------------
|
|
3727
3992
|
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
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);
|
|
3741
4013
|
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
}
|
|
3745
|
-
return str;
|
|
3746
|
-
}
|
|
3747
|
-
static inline Span<const char> SplitStrReverse(const char *str, char split_char,
|
|
3748
|
-
Span<const char> *out_remainder = nullptr)
|
|
3749
|
-
{ 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); }
|
|
3750
4016
|
|
|
3751
|
-
|
|
3752
|
-
Span<const char> *out_remainder = nullptr)
|
|
3753
|
-
{
|
|
3754
|
-
Bitset<256> split_mask;
|
|
3755
|
-
for (Size i = 0; split_chars[i]; i++) {
|
|
3756
|
-
uint8_t c = (uint8_t)split_chars[i];
|
|
3757
|
-
split_mask.Set(c);
|
|
3758
|
-
}
|
|
4017
|
+
int GetInt(int min, int max);
|
|
3759
4018
|
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
4019
|
+
private:
|
|
4020
|
+
uint64_t Next();
|
|
4021
|
+
};
|
|
3763
4022
|
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
return str.Take(remainder_len + 1, str.len - remainder_len - 1);
|
|
3769
|
-
}
|
|
3770
|
-
remainder_len--;
|
|
3771
|
-
}
|
|
4023
|
+
template <int Min = 0, int Max = INT_MAX>
|
|
4024
|
+
class FastRandomInt {
|
|
4025
|
+
RG_STATIC_ASSERT(Min >= 0);
|
|
4026
|
+
RG_STATIC_ASSERT(Max > Min);
|
|
3772
4027
|
|
|
3773
|
-
|
|
3774
|
-
*out_remainder = str.Take(0, 0);
|
|
3775
|
-
}
|
|
3776
|
-
return str;
|
|
3777
|
-
}
|
|
3778
|
-
static inline Span<const char> SplitStrReverseAny(const char *str, const char *split_chars,
|
|
3779
|
-
Span<const char> *out_remainder = nullptr)
|
|
3780
|
-
{ return SplitStrReverseAny(MakeSpan(str, strlen(str)), split_chars, out_remainder); }
|
|
4028
|
+
FastRandom rng;
|
|
3781
4029
|
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
while (str.len && strchr(trim_chars, str[0])) {
|
|
3785
|
-
str.ptr++;
|
|
3786
|
-
str.len--;
|
|
3787
|
-
}
|
|
4030
|
+
public:
|
|
4031
|
+
typedef int result_type;
|
|
3788
4032
|
|
|
3789
|
-
return
|
|
3790
|
-
}
|
|
3791
|
-
static inline Span<char> TrimStrRight(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3792
|
-
{
|
|
3793
|
-
while (str.len && strchr(trim_chars, str[str.len - 1])) {
|
|
3794
|
-
str.len--;
|
|
3795
|
-
}
|
|
4033
|
+
static constexpr int min() { return Min; }
|
|
4034
|
+
static constexpr int max() { return Max; }
|
|
3796
4035
|
|
|
3797
|
-
return
|
|
3798
|
-
}
|
|
3799
|
-
static inline Span<char> TrimStr(Span<char> str, const char *trim_chars = " \t\r\n")
|
|
3800
|
-
{
|
|
3801
|
-
str = TrimStrRight(str, trim_chars);
|
|
3802
|
-
str = TrimStrLeft(str, trim_chars);
|
|
4036
|
+
int operator()() { return rng.GetInt(Min, Max); }
|
|
4037
|
+
};
|
|
3803
4038
|
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
static inline
|
|
3807
|
-
|
|
3808
|
-
static inline Span<const char> TrimStrRight(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3809
|
-
{ return TrimStrRight(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
3810
|
-
static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
3811
|
-
{ 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);
|
|
3812
4043
|
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
{
|
|
3817
|
-
if (RG_UNLIKELY(!str.len)) {
|
|
3818
|
-
if (flags & (int)ParseFlag::Log) {
|
|
3819
|
-
LogError("Cannot convert empty string to integer");
|
|
3820
|
-
}
|
|
3821
|
-
return false;
|
|
3822
|
-
}
|
|
4044
|
+
// ------------------------------------------------------------------------
|
|
4045
|
+
// Sockets
|
|
4046
|
+
// ------------------------------------------------------------------------
|
|
3823
4047
|
|
|
3824
|
-
|
|
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
|
+
};
|
|
3825
4060
|
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
pos = 1;
|
|
3831
|
-
neg = UINT64_MAX;
|
|
3832
|
-
} else if (str[0] == '+') {
|
|
3833
|
-
pos = 1;
|
|
3834
|
-
}
|
|
3835
|
-
}
|
|
4061
|
+
enum class SocketMode {
|
|
4062
|
+
Stream,
|
|
4063
|
+
Messages
|
|
4064
|
+
};
|
|
3836
4065
|
|
|
3837
|
-
|
|
3838
|
-
unsigned int digit = (unsigned int)(str[pos] - '0');
|
|
3839
|
-
if (RG_UNLIKELY(digit > 9)) {
|
|
3840
|
-
if (!pos || flags & (int)ParseFlag::End) {
|
|
3841
|
-
if (flags & (int)ParseFlag::Log) {
|
|
3842
|
-
LogError("Malformed integer number '%1'", str);
|
|
3843
|
-
}
|
|
3844
|
-
return false;
|
|
3845
|
-
} else {
|
|
3846
|
-
break;
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
4066
|
+
int OpenIPSocket(SocketType type, int port, SocketMode mode = SocketMode::Stream);
|
|
3849
4067
|
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
goto overflow;
|
|
3853
|
-
value = new_value;
|
|
3854
|
-
}
|
|
3855
|
-
if (RG_UNLIKELY(value > (uint64_t)std::numeric_limits<T>::max()))
|
|
3856
|
-
goto overflow;
|
|
3857
|
-
value = ((value ^ neg) - neg);
|
|
4068
|
+
int OpenUnixSocket(const char *path, SocketMode mode = SocketMode::Stream);
|
|
4069
|
+
int ConnectToUnixSocket(const char *path, SocketMode mode = SocketMode::Stream);
|
|
3858
4070
|
|
|
3859
|
-
|
|
3860
|
-
*out_remaining = str.Take(pos, str.len - pos);
|
|
3861
|
-
}
|
|
3862
|
-
*out_value = (T)value;
|
|
3863
|
-
return true;
|
|
4071
|
+
void CloseSocket(int fd);
|
|
3864
4072
|
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
std::numeric_limits<T>::max());
|
|
3869
|
-
}
|
|
3870
|
-
return false;
|
|
3871
|
-
}
|
|
4073
|
+
// ------------------------------------------------------------------------
|
|
4074
|
+
// Tasks
|
|
4075
|
+
// ------------------------------------------------------------------------
|
|
3872
4076
|
|
|
3873
|
-
|
|
3874
|
-
|
|
4077
|
+
class Async {
|
|
4078
|
+
RG_DELETE_COPY(Async)
|
|
3875
4079
|
|
|
3876
|
-
|
|
3877
|
-
{
|
|
3878
|
-
|
|
3879
|
-
out_buf[0] = (char)c;
|
|
3880
|
-
return 1;
|
|
3881
|
-
} else if (c < 0x800) {
|
|
3882
|
-
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
3883
|
-
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
3884
|
-
return 2;
|
|
3885
|
-
} else if (c >= 0xD800 && c < 0xE000) {
|
|
3886
|
-
return 0;
|
|
3887
|
-
} else if (c < 0x10000) {
|
|
3888
|
-
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
3889
|
-
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3890
|
-
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
3891
|
-
return 3;
|
|
3892
|
-
} else if (c < 0x110000) {
|
|
3893
|
-
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
3894
|
-
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
3895
|
-
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
3896
|
-
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
3897
|
-
return 4;
|
|
3898
|
-
} else {
|
|
3899
|
-
return 0;
|
|
3900
|
-
}
|
|
3901
|
-
}
|
|
4080
|
+
bool stop_after_error;
|
|
4081
|
+
std::atomic_bool success {true};
|
|
4082
|
+
std::atomic_int remaining_tasks {0};
|
|
3902
4083
|
|
|
3903
|
-
|
|
3904
|
-
{
|
|
3905
|
-
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
3906
|
-
return std::min(std::max(ones, 1), 4);
|
|
3907
|
-
}
|
|
4084
|
+
class AsyncPool *pool;
|
|
3908
4085
|
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
4086
|
+
public:
|
|
4087
|
+
Async(int threads = -1, bool stop_after_error = true);
|
|
4088
|
+
Async(Async *parent, bool stop_after_error = true);
|
|
4089
|
+
~Async();
|
|
3912
4090
|
|
|
3913
|
-
|
|
3914
|
-
|
|
4091
|
+
void Run(const std::function<bool()> &f);
|
|
4092
|
+
bool Sync();
|
|
3915
4093
|
|
|
3916
|
-
|
|
3917
|
-
*out_c = ptr[0];
|
|
3918
|
-
return 1;
|
|
3919
|
-
} else if (RG_UNLIKELY(ptr[0] - 0xC2 > 0xF4 - 0xC2)) {
|
|
3920
|
-
return 0;
|
|
3921
|
-
} else if (ptr[0] < 0xE0 &&
|
|
3922
|
-
RG_LIKELY(available >= 2 && (ptr[1] & 0xC0) == 0x80)) {
|
|
3923
|
-
*out_c = ((ptr[0] & 0x1F) << 6) | (ptr[1] & 0x3F);
|
|
3924
|
-
return 2;
|
|
3925
|
-
} else if (ptr[0] < 0xF0 &&
|
|
3926
|
-
RG_LIKELY(available >= 3 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3927
|
-
(ptr[2] & 0xC0) == 0x80)) {
|
|
3928
|
-
*out_c = ((ptr[0] & 0xF) << 12) | ((ptr[1] & 0x3F) << 6) | (ptr[2] & 0x3F);
|
|
3929
|
-
return 3;
|
|
3930
|
-
} else if (RG_LIKELY(available >= 4 && (ptr[1] & 0xC0) == 0x80 &&
|
|
3931
|
-
(ptr[2] & 0xC0) == 0x80 &&
|
|
3932
|
-
(ptr[3] & 0xC0) == 0x80)) {
|
|
3933
|
-
*out_c = ((ptr[0] & 0x7) << 18) | ((ptr[1] & 0x3F) << 12) | ((ptr[2] & 0x3F) << 6) | (ptr[3] & 0x3F);
|
|
3934
|
-
return 4;
|
|
3935
|
-
} else {
|
|
3936
|
-
return 0;
|
|
3937
|
-
}
|
|
3938
|
-
}
|
|
4094
|
+
int CountPendingTasks();
|
|
3939
4095
|
|
|
3940
|
-
static
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
4096
|
+
static bool IsTaskRunning();
|
|
4097
|
+
static int GetWorkerIdx();
|
|
4098
|
+
static int GetWorkerCount();
|
|
4099
|
+
|
|
4100
|
+
friend class AsyncPool;
|
|
4101
|
+
};
|
|
3945
4102
|
|
|
3946
4103
|
// ------------------------------------------------------------------------
|
|
3947
|
-
//
|
|
4104
|
+
// Fibers
|
|
3948
4105
|
// ------------------------------------------------------------------------
|
|
3949
4106
|
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
#define RG_PATH_DELIMITER ';'
|
|
3953
|
-
#define RG_SHARED_LIBRARY_EXTENSION ".dll"
|
|
3954
|
-
#else
|
|
3955
|
-
#define RG_PATH_SEPARATORS "/"
|
|
3956
|
-
#define RG_PATH_DELIMITER ':'
|
|
3957
|
-
#define RG_SHARED_LIBRARY_EXTENSION ".so"
|
|
3958
|
-
#endif
|
|
3959
|
-
|
|
3960
|
-
#ifdef _WIN32
|
|
3961
|
-
bool IsWin32Utf8();
|
|
3962
|
-
Size ConvertUtf8ToWin32Wide(Span<const char> str, Span<wchar_t> out_str_w);
|
|
3963
|
-
Size ConvertWin32WideToUtf8(const wchar_t *str_w, Span<char> out_str);
|
|
3964
|
-
char *GetWin32ErrorString(uint32_t error_code = UINT32_MAX);
|
|
3965
|
-
#endif
|
|
4107
|
+
class Fiber {
|
|
4108
|
+
RG_DELETE_COPY(Fiber)
|
|
3966
4109
|
|
|
3967
|
-
|
|
3968
|
-
void DeleteEnvironmentVar(const char *name);
|
|
4110
|
+
std::function<bool()> f;
|
|
3969
4111
|
|
|
3970
|
-
static inline bool IsPathSeparator(char c)
|
|
3971
|
-
{
|
|
3972
4112
|
#ifdef _WIN32
|
|
3973
|
-
|
|
4113
|
+
void *fiber = nullptr;
|
|
4114
|
+
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4115
|
+
ucontext_t ucp = {};
|
|
3974
4116
|
#else
|
|
3975
|
-
|
|
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;
|
|
3976
4123
|
#endif
|
|
3977
|
-
}
|
|
3978
4124
|
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
CompressionType *out_compression_type = nullptr);
|
|
3982
|
-
CompressionType GetPathCompression(Span<const char> filename);
|
|
4125
|
+
bool done = true;
|
|
4126
|
+
bool success = false;
|
|
3983
4127
|
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4128
|
+
public:
|
|
4129
|
+
Fiber(const std::function<bool()> &f, Size stack_size = RG_FIBER_DEFAULT_STACK_SIZE);
|
|
4130
|
+
~Fiber();
|
|
3987
4131
|
|
|
3988
|
-
|
|
3989
|
-
bool
|
|
3990
|
-
bool PathContainsDotDot(const char *path);
|
|
4132
|
+
void SwitchTo();
|
|
4133
|
+
bool Finalize();
|
|
3991
4134
|
|
|
3992
|
-
|
|
3993
|
-
IgnoreMissing = 1 << 0,
|
|
3994
|
-
FollowSymlink = 1 << 1
|
|
3995
|
-
};
|
|
4135
|
+
static bool SwitchBack();
|
|
3996
4136
|
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
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
|
|
4004
4148
|
};
|
|
4005
4149
|
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
int64_t size;
|
|
4010
|
-
int64_t mtime;
|
|
4011
|
-
};
|
|
4150
|
+
// ------------------------------------------------------------------------
|
|
4151
|
+
// Streams
|
|
4152
|
+
// ------------------------------------------------------------------------
|
|
4012
4153
|
|
|
4013
|
-
enum class
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
Complete
|
|
4154
|
+
enum class CompressionSpeed {
|
|
4155
|
+
Default,
|
|
4156
|
+
Slow,
|
|
4157
|
+
Fast
|
|
4018
4158
|
};
|
|
4019
4159
|
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
{ return StatFile(filename, 0, out_info); }
|
|
4160
|
+
class StreamReader {
|
|
4161
|
+
RG_DELETE_COPY(StreamReader)
|
|
4023
4162
|
|
|
4024
|
-
|
|
4025
|
-
|
|
4163
|
+
enum class SourceType {
|
|
4164
|
+
Memory,
|
|
4165
|
+
File,
|
|
4166
|
+
Function
|
|
4167
|
+
};
|
|
4026
4168
|
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
bool EnumerateFiles(const char *dirname, const char *filter, Size max_depth, Size max_files,
|
|
4030
|
-
Allocator *str_alloc, HeapArray<const char *> *out_files);
|
|
4031
|
-
bool IsDirectoryEmpty(const char *dirname);
|
|
4169
|
+
const char *filename = nullptr;
|
|
4170
|
+
bool error = true;
|
|
4032
4171
|
|
|
4033
|
-
|
|
4034
|
-
|
|
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;
|
|
4035
4184
|
|
|
4036
|
-
|
|
4037
|
-
|
|
4185
|
+
// StreamReader deals with func destructor
|
|
4186
|
+
U() {}
|
|
4187
|
+
~U() {}
|
|
4188
|
+
} u;
|
|
4038
4189
|
|
|
4039
|
-
bool
|
|
4040
|
-
|
|
4041
|
-
bool FindExecutableInPath(const char *name, Allocator *alloc = nullptr,
|
|
4042
|
-
const char **out_path = nullptr);
|
|
4190
|
+
bool eof = false;
|
|
4191
|
+
} source;
|
|
4043
4192
|
|
|
4044
|
-
|
|
4045
|
-
|
|
4193
|
+
struct {
|
|
4194
|
+
CompressionType type = CompressionType::None;
|
|
4195
|
+
union {
|
|
4196
|
+
struct MinizInflateContext *miniz;
|
|
4197
|
+
struct BrotliDecompressContext *brotli;
|
|
4198
|
+
} u;
|
|
4199
|
+
} compression;
|
|
4046
4200
|
|
|
4047
|
-
|
|
4048
|
-
|
|
4201
|
+
int64_t raw_len = -1;
|
|
4202
|
+
Size raw_read = 0;
|
|
4203
|
+
bool eof = false;
|
|
4049
4204
|
|
|
4050
|
-
|
|
4051
|
-
bool MakeDirectoryRec(Span<const char> directory);
|
|
4052
|
-
bool UnlinkDirectory(const char *directory, bool error_if_missing = false);
|
|
4053
|
-
bool UnlinkFile(const char *filename, bool error_if_missing = false);
|
|
4054
|
-
bool EnsureDirectoryExists(const char *filename);
|
|
4205
|
+
BlockAllocator str_alloc;
|
|
4055
4206
|
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
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); }
|
|
4060
4222
|
|
|
4061
|
-
|
|
4062
|
-
|
|
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); }
|
|
4063
4231
|
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
bool FlushFile(FILE *fp, const char *filename);
|
|
4232
|
+
// File-specific
|
|
4233
|
+
bool Rewind();
|
|
4067
4234
|
|
|
4068
|
-
|
|
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; }
|
|
4069
4239
|
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
Byte,
|
|
4073
|
-
Message
|
|
4074
|
-
};
|
|
4240
|
+
FILE *GetFile() const;
|
|
4241
|
+
int GetDescriptor() const;
|
|
4075
4242
|
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
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)); }
|
|
4080
4246
|
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
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); }
|
|
4084
4250
|
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf, Size max_len,
|
|
4088
|
-
HeapArray<uint8_t> *out_buf, int *out_code);
|
|
4089
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, int *out_code) {
|
|
4090
|
-
return ExecuteCommandLine(cmd_line, {}, {}, out_code);
|
|
4091
|
-
}
|
|
4092
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const uint8_t> in_buf,
|
|
4093
|
-
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
4094
|
-
{
|
|
4095
|
-
const auto read_once = [&]() {
|
|
4096
|
-
Span<const uint8_t> buf = in_buf;
|
|
4097
|
-
in_buf = {};
|
|
4098
|
-
return buf;
|
|
4099
|
-
};
|
|
4251
|
+
int64_t ComputeRawLen();
|
|
4252
|
+
int64_t GetRawRead() const { return raw_read; }
|
|
4100
4253
|
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf,
|
|
4104
|
-
FunctionRef<void(Span<char> buf)> out_func, int *out_code)
|
|
4105
|
-
{
|
|
4106
|
-
const auto write = [&](Span<uint8_t> buf) { out_func(buf.As<char>()); };
|
|
4254
|
+
private:
|
|
4255
|
+
bool Close(bool implicit);
|
|
4107
4256
|
|
|
4108
|
-
|
|
4109
|
-
}
|
|
4110
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, Span<const char> in_buf, Size max_len,
|
|
4111
|
-
HeapArray<char> *out_buf, int *out_code)
|
|
4112
|
-
{
|
|
4113
|
-
return ExecuteCommandLine(cmd_line, in_buf.As<const uint8_t>(), max_len,
|
|
4114
|
-
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
4115
|
-
}
|
|
4257
|
+
bool InitDecompressor(CompressionType type);
|
|
4116
4258
|
|
|
4117
|
-
|
|
4259
|
+
Size ReadInflate(Size max_len, void *out_buf);
|
|
4260
|
+
Size ReadBrotli(Size max_len, void *out_buf);
|
|
4118
4261
|
|
|
4119
|
-
|
|
4120
|
-
Interrupt,
|
|
4121
|
-
Message,
|
|
4122
|
-
Timeout
|
|
4262
|
+
Size ReadRaw(Size max_len, void *out_buf);
|
|
4123
4263
|
};
|
|
4124
4264
|
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
return ret; \
|
|
4146
|
-
})()
|
|
4147
|
-
#endif
|
|
4148
|
-
|
|
4149
|
-
// ------------------------------------------------------------------------
|
|
4150
|
-
// Standard paths
|
|
4151
|
-
// ------------------------------------------------------------------------
|
|
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
|
+
}
|
|
4152
4285
|
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
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
|
+
}
|
|
4156
4308
|
|
|
4157
|
-
|
|
4309
|
+
class LineReader {
|
|
4310
|
+
RG_DELETE_COPY(LineReader)
|
|
4158
4311
|
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
const char *CreateTemporaryDirectory(Span<const char> directory, const char *prefix, Allocator *alloc);
|
|
4312
|
+
HeapArray<char> buf;
|
|
4313
|
+
Span<char> view = {};
|
|
4162
4314
|
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4315
|
+
StreamReader *st;
|
|
4316
|
+
bool error;
|
|
4317
|
+
bool eof = false;
|
|
4166
4318
|
|
|
4167
|
-
|
|
4168
|
-
|
|
4319
|
+
Span<char> line = {};
|
|
4320
|
+
int line_number = 0;
|
|
4169
4321
|
|
|
4170
4322
|
public:
|
|
4171
|
-
|
|
4172
|
-
FastRandom(uint64_t seed);
|
|
4323
|
+
LineReader(StreamReader *st) : st(st), error(!st->IsValid()) {}
|
|
4173
4324
|
|
|
4174
|
-
|
|
4175
|
-
|
|
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; }
|
|
4176
4329
|
|
|
4177
|
-
|
|
4330
|
+
bool Next(Span<char> *out_line);
|
|
4331
|
+
bool Next(Span<const char> *out_line) { return Next((Span<char> *)out_line); }
|
|
4178
4332
|
|
|
4179
|
-
|
|
4180
|
-
uint64_t Next();
|
|
4333
|
+
void PushLogFilter();
|
|
4181
4334
|
};
|
|
4182
4335
|
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4336
|
+
enum class StreamWriterFlag {
|
|
4337
|
+
Exclusive = 1 << 0,
|
|
4338
|
+
Atomic = 1 << 1
|
|
4339
|
+
};
|
|
4187
4340
|
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
// ------------------------------------------------------------------------
|
|
4341
|
+
class StreamWriter {
|
|
4342
|
+
RG_DELETE_COPY(StreamWriter)
|
|
4191
4343
|
|
|
4192
|
-
enum class
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
};
|
|
4198
|
-
static const char *const SocketTypeNames[] = {
|
|
4199
|
-
"Dual",
|
|
4200
|
-
"IPv4",
|
|
4201
|
-
"IPv6",
|
|
4202
|
-
"Unix"
|
|
4203
|
-
};
|
|
4344
|
+
enum class DestinationType {
|
|
4345
|
+
Memory,
|
|
4346
|
+
File,
|
|
4347
|
+
Function
|
|
4348
|
+
};
|
|
4204
4349
|
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
Messages
|
|
4208
|
-
};
|
|
4350
|
+
const char *filename = nullptr;
|
|
4351
|
+
bool error = true;
|
|
4209
4352
|
|
|
4210
|
-
|
|
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;
|
|
4211
4363
|
|
|
4212
|
-
|
|
4213
|
-
|
|
4364
|
+
// Atomic write mode
|
|
4365
|
+
const char *tmp_filename;
|
|
4366
|
+
bool tmp_exclusive;
|
|
4367
|
+
} file;
|
|
4368
|
+
std::function<bool(Span<const uint8_t>)> func;
|
|
4214
4369
|
|
|
4215
|
-
|
|
4370
|
+
// StreamWriter deals with func destructor
|
|
4371
|
+
U() {}
|
|
4372
|
+
~U() {}
|
|
4373
|
+
} u;
|
|
4216
4374
|
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
// ------------------------------------------------------------------------
|
|
4375
|
+
bool vt100;
|
|
4376
|
+
} dest;
|
|
4220
4377
|
|
|
4221
|
-
|
|
4222
|
-
|
|
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;
|
|
4223
4386
|
|
|
4224
|
-
|
|
4225
|
-
std::atomic_bool success {true};
|
|
4226
|
-
std::atomic_int remaining_tasks {0};
|
|
4387
|
+
int64_t raw_written = 0;
|
|
4227
4388
|
|
|
4228
|
-
|
|
4389
|
+
BlockAllocator str_alloc;
|
|
4229
4390
|
|
|
4230
4391
|
public:
|
|
4231
|
-
|
|
4232
|
-
|
|
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); }
|
|
4233
4410
|
|
|
4234
|
-
|
|
4235
|
-
|
|
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); }
|
|
4236
4424
|
|
|
4237
|
-
|
|
4238
|
-
|
|
4425
|
+
// For compressed streams, Flush may not be complete and only Close() can finalize the file.
|
|
4426
|
+
bool Flush();
|
|
4239
4427
|
|
|
4240
|
-
|
|
4241
|
-
}
|
|
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; }
|
|
4242
4432
|
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
// ------------------------------------------------------------------------
|
|
4433
|
+
FILE *GetFile() const;
|
|
4434
|
+
int GetDescriptor() const;
|
|
4246
4435
|
|
|
4247
|
-
|
|
4248
|
-
|
|
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)); }
|
|
4249
4440
|
|
|
4250
|
-
|
|
4441
|
+
int64_t GetRawWritten() const { return raw_written; }
|
|
4251
4442
|
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4255
|
-
ucontext_t ucp = {};
|
|
4256
|
-
#else
|
|
4257
|
-
std::thread thread;
|
|
4443
|
+
private:
|
|
4444
|
+
bool Close(bool implicit);
|
|
4258
4445
|
|
|
4259
|
-
|
|
4260
|
-
std::condition_variable cv;
|
|
4261
|
-
std::unique_lock<std::mutex> lock { mutex };
|
|
4262
|
-
int toggle = 1;
|
|
4263
|
-
#endif
|
|
4446
|
+
bool InitCompressor(CompressionType type, CompressionSpeed speed);
|
|
4264
4447
|
|
|
4265
|
-
bool
|
|
4266
|
-
bool
|
|
4448
|
+
bool WriteDeflate(Span<const uint8_t> buf);
|
|
4449
|
+
bool WriteBrotli(Span<const uint8_t> buf);
|
|
4267
4450
|
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
~Fiber();
|
|
4451
|
+
bool WriteRaw(Span<const uint8_t> buf);
|
|
4452
|
+
};
|
|
4271
4453
|
|
|
4272
|
-
|
|
4273
|
-
|
|
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
|
+
}
|
|
4274
4468
|
|
|
4275
|
-
|
|
4469
|
+
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer);
|
|
4276
4470
|
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
static void __stdcall FiberCallback(void *udata);
|
|
4282
|
-
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4283
|
-
static void FiberCallback(unsigned int high, unsigned int low);
|
|
4284
|
-
#else
|
|
4285
|
-
static void ThreadCallback(void *udata);
|
|
4286
|
-
void Toggle(int to, std::unique_lock<std::mutex> *lock);
|
|
4287
|
-
#endif
|
|
4288
|
-
};
|
|
4471
|
+
// For convenience, don't close them
|
|
4472
|
+
extern StreamReader stdin_st;
|
|
4473
|
+
extern StreamWriter stdout_st;
|
|
4474
|
+
extern StreamWriter stderr_st;
|
|
4289
4475
|
|
|
4290
4476
|
// ------------------------------------------------------------------------
|
|
4291
4477
|
// INI
|