Compare commits

...

56 Commits

Author SHA1 Message Date
Michele Caini
cb15b5aa1b linter: disable avoid-c-arrays (not ready for that yet) 2024-12-05 17:00:08 +01:00
xndcn
93476594ee
doc: fix typo (uwv -> uvw) (#321) 2024-12-03 15:05:12 +01:00
Michele Caini
04cb432e72 linter: disable bugprone-easily-swappable-parameters (too big of an effort today) 2024-10-24 12:46:51 +02:00
Michele Caini
242838e3f3 *: cleanup 2024-10-24 09:28:13 +02:00
Michele Caini
0a993494e2 udp: avoid C-style arrays 2024-10-24 08:31:14 +02:00
Michele Caini
a3f2a6e3ac fs: avoid unnecessary array 2024-10-23 18:01:29 +02:00
Michele Caini
58b8b3d610 util: avoid C-style arrays 2024-10-23 10:38:32 +02:00
Michele Caini
998a86975b stream: avoid C-style arrays 2024-10-23 10:35:37 +02:00
Michele Caini
6bb7a6f291 work: cleanup 2024-10-23 10:33:42 +02:00
Michele Caini
32f06f4fe8 thread: cleanup 2024-10-23 10:33:36 +02:00
Michele Caini
f26fe9dea8 fs: avoid C-style arrays 2024-10-23 10:27:34 +02:00
Michele Caini
d5ea72a18a uv_type: cleanup 2024-10-23 10:22:03 +02:00
Michele Caini
8b2aa01b3d stream: [[nodiscard]] 2024-10-23 09:31:27 +02:00
Michele Caini
35c840ab61 lib: [[nodiscard]] 2024-10-23 09:30:21 +02:00
Michele Caini
08350199e3 request: [[nodiscard]] 2024-10-23 09:30:03 +02:00
Michele Caini
e774913db9 *: perf improvements 2024-10-23 09:28:51 +02:00
Michele Caini
949e46642a util: use std::array 2024-10-23 09:17:06 +02:00
Michele Caini
3a8c06fe5b test: minor changes 2024-10-23 08:56:22 +02:00
Michele Caini
e4bb43bce7 util: thanks msvc for accepting invalid code 2024-10-23 08:56:13 +02:00
Michele Caini
3c57dd9a98 test: minor changes 2024-10-23 08:51:15 +02:00
Michele Caini
3754bfe088 process:: suppress warning due to [[nodiscard]] 2024-10-23 08:51:09 +02:00
Michele Caini
cef9d850d8 util: [[nodiscard]] 2024-10-23 08:50:54 +02:00
Michele Caini
04a7c36e7b fs: explicit override 2024-10-23 08:42:35 +02:00
Michele Caini
9adfaf25ca util: move ctor params as possible 2024-10-23 08:39:19 +02:00
Michele Caini
8c10ef9de7 loop: explicit override 2024-10-23 08:37:03 +02:00
Michele Caini
78e410dc1a resource: [[nodiscard]] 2024-10-23 08:36:11 +02:00
Michele Caini
258ddaed5f uv_type: [[nodiscard]] 2024-10-23 08:35:37 +02:00
Michele Caini
70572c4424 handle: [[nodiscard]] 2024-10-23 08:33:58 +02:00
Michele Caini
5be31bad4c emitter: [[nodiscard]] 2024-10-23 08:33:52 +02:00
Michele Caini
d4f217f9f1 test: avoid deprecated headers 2024-10-23 08:30:45 +02:00
Michele Caini
6e0fe7b8c6 type_info: char to unsigned char conversion before using the value 2024-10-23 08:29:51 +02:00
Michele Caini
2b4a0f158b poll: instruct the linter on libuv callbacks 2024-10-23 08:29:27 +02:00
Michele Caini
34d2b00441 test: instruct the linter 2024-10-22 19:38:03 +02:00
Michele Caini
eb06aed649 fs_event: instruct the linter 2024-10-22 19:37:53 +02:00
Michele Caini
7cb57e0c46 fs: use make_unique if possible 2024-10-22 19:32:03 +02:00
Michele Caini
b771134121 clang-tidy: enable more checks 2024-10-22 19:24:19 +02:00
Michele Caini
dd63b4e225 type_info: internal changes 2024-10-22 19:19:17 +02:00
Michele Caini
b53cd6fd8b util: refine try_read 2024-10-22 09:25:15 +02:00
Michele Caini
a4657c479d util: passwd cannot be noexcept 2024-10-22 09:25:07 +02:00
Michele Caini
39c142fa56 enum: avoid using reserved identifiers 2024-10-22 08:00:46 +02:00
Michele Caini
a578b44788 build: updated workflow 2024-10-21 11:03:14 +02:00
Michele Caini
21372c17e8 build: split h/ipp/cpp and update clang-tidy config 2024-10-21 10:57:36 +02:00
Michele Caini
f70a0dbc2b cmake: a couple of fixes to the build system 2024-10-18 17:31:54 +02:00
Michele Caini
fb2f8d9eff cmake: use UVW_ to avoid polluting parent projects 2024-10-18 15:09:24 +02:00
Michele Caini
4d54eb946f iwyu: basic config to start with 2024-10-18 12:28:03 +02:00
Michele Caini
98dd44b5eb linter: let's start with something simple 2024-10-18 12:27:49 +02:00
Michele Caini
7261037df8 build: add missing \ 2024-10-17 18:36:45 +02:00
Michele Caini
0784a26081 build: rename file 2024-10-17 18:34:05 +02:00
Michele Caini
a89a4155ea build: fix typos 2024-10-17 18:22:51 +02:00
Michele Caini
25feca605d build: tools workflow (first draft, to be tested) 2024-10-08 16:40:59 +02:00
Michele Caini
4a1f1c6daa thread: set/get priority 2024-10-03 17:29:44 +02:00
Michele Caini
1678cdbddd utility: resident_set_memory 2024-10-03 16:08:01 +02:00
Michele Caini
a38f5452d8 build: prepare to work with libuv 1.49 2024-10-03 09:53:46 +02:00
Ruurd Adema
44541bd1bd
event: make error_event copy assignable (#316) 2024-09-05 09:36:57 +02:00
brenfwd
a4436b746e
build(meson): bump libuv to 1.48.0 (#314) 2024-05-15 17:10:40 +02:00
Michele Caini
204e31d481 now working on v3.5.0 2024-05-13 12:28:35 +02:00
101 changed files with 2690 additions and 2572 deletions

12
.clang-tidy Normal file
View File

@ -0,0 +1,12 @@
Checks: >
bugprone-*,
-bugprone-easily-swappable-parameters,
concurrency-*,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-use-trailing-return-type,
performance-*,
portability-*,
CheckOptions:
- key: bugprone-suspicious-include.HeaderFileExtensions
value: ";h;hpp;ipp"

View File

@ -10,12 +10,12 @@ jobs:
strategy:
matrix:
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j2

View File

@ -7,7 +7,7 @@ jobs:
timeout-minutes: 60
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Meson
env:
DEBIAN_FRONTEND: noninteractive

View File

@ -16,12 +16,12 @@ jobs:
- { pkg: clang, exe: 'clang++', version: 9 }
- { pkg: clang, exe: 'clang++', version: 10 }
- { pkg: clang, exe: 'clang++', version: 11 }
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }}
run: |
sudo apt-get update --fix-missing

View File

@ -15,12 +15,12 @@ jobs:
- { pkg: clang, exe: 'clang++', version: 12 }
- { pkg: clang, exe: 'clang++', version: 13 }
- { pkg: clang, exe: 'clang++', version: 14 }
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }}
run: |
sudo apt-get update --fix-missing

View File

@ -11,12 +11,12 @@ jobs:
strategy:
matrix:
generator: [Visual Studio 17 2022]
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF]
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
run: |
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF -DCMAKE_CXX_FLAGS=/W1 -G"${{ matrix.generator }}" ..
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF -DCMAKE_CXX_FLAGS=/W1 -G"${{ matrix.generator }}" ..
cmake --build . -j 2

View File

@ -9,14 +9,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXXFLAGS: "-O0 --coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
CXX: g++
run: |
cmake -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
cmake -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j4
- name: Run tests
working-directory: build

View File

@ -13,7 +13,7 @@ jobs:
steps:
- uses: docker://conanio/gcc8
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@master
with:

View File

@ -15,13 +15,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXX: ${{ matrix.compiler }}
run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF -DUSE_${{ matrix.sanitizer }}=ON ..
cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -DUVW_USE_${{ matrix.sanitizer }}=ON -Dlibuv_buildtests=OFF ..
make -j2
- name: Run tests
working-directory: build

78
.github/workflows/tools.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: tools
on:
push:
branches:
- tools
jobs:
iwyu:
timeout-minutes: 60
env:
IWYU: "0.22"
LLVM: "18"
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install llvm/clang
# see: https://apt.llvm.org/
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM main"
sudo apt update
sudo apt remove -y "llvm*"
sudo apt remove -y "libclang-dev*"
sudo apt remove -y "clang*"
sudo apt install -y llvm-$LLVM-dev
sudo apt install -y libclang-$LLVM-dev
sudo apt install -y clang-$LLVM
- name: Compile iwyu
# see: https://github.com/include-what-you-use/include-what-you-use
working-directory: build
run: |
git clone https://github.com/include-what-you-use/include-what-you-use.git --branch $IWYU --depth 1
mkdir include-what-you-use/build
cd include-what-you-use/build
cmake -DCMAKE_C_COMPILER=clang-$LLVM \
-DCMAKE_CXX_COMPILER=clang++-$LLVM \
-DCMAKE_INSTALL_PREFIX=./ \
..
make -j4
bin/include-what-you-use --version
- name: Compile tests
working-directory: build
run: |
export PATH=$PATH:${GITHUB_WORKSPACE}/build/include-what-you-use/build/bin
cmake -DUVW_BUILD_TESTING=ON \
-Dlibuv_buildtests=OFF \
-DCMAKE_C_COMPILER=clang-$LLVM \
-DCMAKE_CXX_COMPILER=clang++-$LLVM \
-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=${GITHUB_WORKSPACE}/uvw.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--verbose=1" \
..
make -j4
clang-tidy:
timeout-minutes: 60
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXX: clang++
run: |
cmake -DUVW_BUILD_TESTING=ON -DUVW_USE_CLANG_TIDY=ON -Dlibuv_buildtests=OFF ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest -C Debug -j4

View File

@ -16,7 +16,7 @@ endif()
# Project configuration
#
set(UVW_VERSION_MAJOR 3)
set(UVW_VERSION_MINOR 4)
set(UVW_VERSION_MINOR 5)
set(UVW_VERSION_PATCH 0)
project(
@ -31,22 +31,23 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
option(USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." ON)
option(USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF)
option(USE_UBSAN "Use address sanitizer by adding -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer flags" OFF)
option(BUILD_UVW_LIBS "Prepare targets for static library rather than for a header-only library." OFF)
option(BUILD_UVW_SHARED_LIB "Prepare targets for shared library rather than for a header-only library." OFF)
option(FIND_LIBUV "Try finding libuv library development files in the system" OFF)
option(UVW_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." ON)
option(UVW_USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF)
option(UVW_USE_UBSAN "Use address sanitizer by adding -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer flags" OFF)
option(UVW_USE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF)
option(UVW_BUILD_LIBS "Prepare targets for static library rather than for a header-only library." OFF)
option(UVW_BUILD_SHARED_LIB "Prepare targets for shared library rather than for a header-only library." OFF)
option(UVW_FIND_LIBUV "Try finding libuv library development files in the system" OFF)
if(BUILD_UVW_SHARED_LIB)
set(BUILD_UVW_LIBS BOOL:ON)
if(UVW_BUILD_SHARED_LIB)
set(UVW_BUILD_LIBS BOOL:ON)
endif()
#
# Compiler stuff
#
if(NOT WIN32 AND USE_LIBCPP)
if(NOT WIN32 AND UVW_USE_LIBCPP)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
@ -57,27 +58,34 @@ if(NOT WIN32 AND USE_LIBCPP)
check_cxx_source_compiles("
#include<type_traits>
int main() { return std::is_same_v<int, char>; }
" HAS_LIBCPP)
" UVW_HAS_LIBCPP)
if(NOT HAS_LIBCPP)
message(WARNING "The option USE_LIBCPP is set (by default) but libc++ is not available. The flag will not be added to the target.")
if(NOT UVW_HAS_LIBCPP)
message(WARNING "The option UVW_USE_LIBCPP is set (by default) but libc++ is not available. The flag will not be added to the target.")
endif()
cmake_pop_check_state()
endif()
if(UVW_USE_CLANG_TIDY)
find_program(UVW_CLANG_TIDY_EXECUTABLE "clang-tidy")
if(NOT UVW_CLANG_TIDY_EXECUTABLE)
message(VERBOSE "The option UVW_USE_CLANG_TIDY is set but clang-tidy executable is not available.")
endif()
endif()
# Required minimal libuv version
set(LIBUV_VERSION 1.48.0)
set(UVW_LIBUV_VERSION 1.49.0)
function(fetch_libuv)
if (FETCH_LIBUV)
if (UVW_FETCH_LIBUV)
include(FetchContent)
FetchContent_Declare(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG "v${LIBUV_VERSION}"
GIT_TAG "v${UVW_LIBUV_VERSION}"
GIT_SHALLOW 1
)
@ -88,23 +96,24 @@ function(fetch_libuv)
add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
if(BUILD_UVW_SHARED_LIB)
if(UVW_BUILD_SHARED_LIB)
add_library(uv::uv-shared ALIAS uv)
set_target_properties(uv PROPERTIES POSITION_INDEPENDENT_CODE 1)
else()
add_library(uv::uv-static ALIAS uv_a)
set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif()
endif(FETCH_LIBUV)
endif(UVW_FETCH_LIBUV)
endfunction()
function(use_libuv)
set(FETCH_LIBUV_DEFAULT ON)
if (FIND_LIBUV)
set(UVW_FETCH_LIBUV_DEFAULT ON)
if (UVW_FIND_LIBUV)
find_package(libuv ${LIBUV_VERSION} QUIET)
if (libuv_FOUND)
add_library(uv::uv-shared ALIAS uv)
set(FETCH_LIBUV_DEFAULT OFF)
set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via cmake")
else(libuv_FOUND)
find_package(PkgConfig QUIET)
@ -112,14 +121,15 @@ function(use_libuv)
pkg_check_modules(libuv IMPORTED_TARGET libuv>=${LIBUV_VERSION})
if (libuv_FOUND)
add_library(uv::uv-shared ALIAS PkgConfig::libuv)
set(FETCH_LIBUV_DEFAULT OFF)
set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via pkg-config")
endif(libuv_FOUND)
endif(PkgConfig_FOUND)
endif(libuv_FOUND)
endif(FIND_LIBUV)
endif(UVW_FIND_LIBUV)
option(UVW_FETCH_LIBUV "Fetch the libuv repo using CMake FetchContent facility" ${UVW_FETCH_LIBUV_DEFAULT})
option(FETCH_LIBUV "Fetch the libuv repo using CMake FetchContent facility" ${FETCH_LIBUV_DEFAULT})
fetch_libuv()
endfunction()
@ -129,7 +139,7 @@ endfunction()
include(GNUInstallDirs)
if(BUILD_UVW_LIBS)
if(UVW_BUILD_LIBS)
use_libuv()
add_subdirectory(src)
@ -147,21 +157,25 @@ else()
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(USE_ASAN)
if(UVW_USE_ASAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address>)
endif()
if(USE_UBSAN)
if(UVW_USE_UBSAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>)
target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif()
if(HAS_LIBCPP)
if(UVW_CLANG_TIDY_EXECUTABLE)
set(CMAKE_CXX_CLANG_TIDY "${UVW_CLANG_TIDY_EXECUTABLE};--config-file=${uvw_SOURCE_DIR}/.clang-tidy;--header-filter=${uvw_SOURCE_DIR}/src/uvw/.*")
endif()
if(UVW_HAS_LIBCPP)
target_compile_options(uvw BEFORE INTERFACE -stdlib=libc++)
endif()
file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp src/uvw/*.cpp)
file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp)
endif()
#
@ -186,7 +200,7 @@ install(
# Install targets
#
if (BUILD_UVW_LIBS)
if (UVW_BUILD_LIBS)
set_target_properties(
uvw PROPERTIES
VERSION ${UVW_VERSION_MAJOR}.${UVW_VERSION_MINOR}.${UVW_VERSION_PATCH}
@ -208,26 +222,26 @@ install(
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
if(FETCH_LIBUV AND BUILD_UVW_LIBS)
if(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
# libuv is only fetched when both above conditions are true
install(DIRECTORY ${libuv_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/uvw/uv/include)
if (BUILD_UVW_SHARED_LIB)
if (UVW_BUILD_SHARED_LIB)
install(TARGETS uv EXPORT uvwConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
else()
install(TARGETS uv_a EXPORT uvwConfig ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
endif()
endif(FETCH_LIBUV AND BUILD_UVW_LIBS)
endif(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
export(EXPORT uvwConfig)
### Testing
option(BUILD_TESTING "Enable testing with ctest." OFF)
option(UVW_BUILD_TESTING "Enable testing with ctest." OFF)
if(BUILD_TESTING)
option(FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
if(UVW_BUILD_TESTING)
option(UVW_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
if (NOT BUILD_UVW_LIBS)
if (NOT UVW_BUILD_LIBS)
use_libuv()
endif()
@ -239,9 +253,9 @@ endif()
# Documentation
#
option(BUILD_DOCS "Enable building with documentation." OFF)
option(UVW_BUILD_DOCS "Enable building with documentation." OFF)
if(BUILD_DOCS)
if(UVW_BUILD_DOCS)
find_package(Doxygen 1.10)
if(DOXYGEN_FOUND)

View File

@ -24,7 +24,7 @@
"description": "Common (non-OS specific) mode for development",
"inherits": "cmake-pedantic",
"cacheVariables": {
"BUILD_TESTING": true,
"UVW_BUILD_TESTING": true,
"libuv_buildtests": false
}
},

View File

@ -104,8 +104,7 @@ libraries are compiled through `CMake`.
## Meson
You can use `uvw` with [meson](https://mesonbuild.com/) by simply adding it to
your `subprojects` directory in your project. Currently, `uvw` is not available
with `meson wrap`, but this will change with the release of `uvw` 3.4.x.
your `subprojects` directory in your project.
To compile `uvw` from source without using it as a subproject, in the `uvw`
source directory, run:
@ -141,7 +140,7 @@ When used through `CMake`, the `uvw::uvw` target is exported for convenience.
### Static
To use `uvw` as a compiled library, set the `BUILD_UVW_LIBS` options in cmake
To use `uvw` as a compiled library, set the `UVW_BUILD_LIBS` options in cmake
before including the project.<br/>
This option triggers the generation of a targets named
`uvw::uvw-static`. The matching version of `libuv` is also
@ -210,7 +209,7 @@ else.
To build the tests:
* `$ cd build`
* `$ cmake .. -DBUILD_TESTING=ON`
* `$ cmake .. -DUVW_BUILD_TESTING=ON`
* `$ make`
* `$ ctest -j4 -R uvw`
@ -422,7 +421,7 @@ Go the raw way at your own risk, but do not expect any support in case of bugs.
# Related projects
Interested in additional tools and libraries that build upon `uwv`? You might
Interested in additional tools and libraries that build upon `uvw`? You might
find the following useful then:
- [`uvw_net`](https://github.com/mincequi/uvw_net): a networking library with a

View File

@ -13,7 +13,7 @@ class UVWConan(ConanFile):
exports = "LICENSE"
exports_sources = "src/*"
no_copy_source = True
requires = "libuv/1.48.0@bincrafters/stable"
requires = "libuv/1.49.0@bincrafters/stable"
def package(self):
self.copy(pattern="LICENSE", dst="licenses")

View File

@ -6,7 +6,7 @@ project(
default_options: ['cpp_std=c++17'],
)
libuv_dep = dependency('libuv', version: '1.46.0')
libuv_dep = dependency('libuv', version: '1.48.0', required: true)
sources = [
'src/uvw/async.cpp',
@ -35,7 +35,8 @@ sources = [
]
uvw_lib = library(
'uvw', sources,
'uvw',
sources,
include_directories: 'src',
dependencies: [libuv_dep],
cpp_args: ['-DUVW_AS_LIB'],

View File

@ -42,17 +42,17 @@ function(add_uvw_library LIB_NAME)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(USE_ASAN)
if(UVW_USE_ASAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
endif()
if(USE_UBSAN)
if(UVW_USE_UBSAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>)
target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif()
if(HAS_LIBCPP)
if(UVW_HAS_LIBCPP)
target_compile_options(${LIB_NAME} BEFORE PUBLIC -stdlib=libc++)
endif()
endfunction()
@ -61,18 +61,18 @@ endfunction()
# Build and install libraries
#
if (BUILD_UVW_SHARED_LIB)
if (UVW_BUILD_SHARED_LIB)
add_library(uvw SHARED)
add_library(uvw::uvw-shared ALIAS uvw)
# If libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(FETCH_LIBUV OR libuv_FOUND)
if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-shared)
endif()
else()
add_library(uvw STATIC)
add_library(uvw::uvw-static ALIAS uvw)
# If libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(FETCH_LIBUV OR libuv_FOUND)
if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-static)
endif()
endif()

View File

@ -1,22 +1,2 @@
#ifdef UVW_AS_LIB
# include "async.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void async_handle::send_callback(uv_async_t *hndl) {
async_handle &async = *(static_cast<async_handle *>(hndl->data));
async.publish(async_event{});
}
UVW_INLINE int async_handle::init() {
return leak_if(uv_async_init(parent().raw(), raw(), &send_callback));
}
UVW_INLINE int async_handle::send() {
return uv_async_send(raw());
}
} // namespace uvw
#include "async.h"
#include "async.ipp"

View File

@ -52,7 +52,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "async.cpp"
# include "async.ipp"
#endif
#endif // UVW_ASYNC_INCLUDE_H

18
src/uvw/async.ipp Normal file
View File

@ -0,0 +1,18 @@
#include "config.h"
namespace uvw {
UVW_INLINE void async_handle::send_callback(uv_async_t *hndl) {
async_handle &async = *(static_cast<async_handle *>(hndl->data));
async.publish(async_event{});
}
UVW_INLINE int async_handle::init() {
return leak_if(uv_async_init(parent().raw(), raw(), &send_callback));
}
UVW_INLINE int async_handle::send() {
return uv_async_send(raw());
}
} // namespace uvw

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB
# include "check.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void check_handle::start_callback(uv_check_t *hndl) {
check_handle &check = *(static_cast<check_handle *>(hndl->data));
check.publish(check_event{});
}
UVW_INLINE int check_handle::init() {
return leak_if(uv_check_init(parent().raw(), raw()));
}
UVW_INLINE int check_handle::start() {
return uv_check_start(raw(), &start_callback);
}
UVW_INLINE int check_handle::stop() {
return uv_check_stop(raw());
}
} // namespace uvw
#include "check.h"
#include "check.ipp"

View File

@ -50,7 +50,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "check.cpp"
# include "check.ipp"
#endif
#endif // UVW_CHECK_INCLUDE_H

22
src/uvw/check.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void check_handle::start_callback(uv_check_t *hndl) {
check_handle &check = *(static_cast<check_handle *>(hndl->data));
check.publish(check_event{});
}
UVW_INLINE int check_handle::init() {
return leak_if(uv_check_init(parent().raw(), raw()));
}
UVW_INLINE int check_handle::start() {
return uv_check_start(raw(), &start_callback);
}
UVW_INLINE int check_handle::stop() {
return uv_check_stop(raw());
}
} // namespace uvw

View File

@ -1,93 +1,2 @@
#ifdef UVW_AS_LIB
# include "dns.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE addr_info_event::addr_info_event(std::unique_ptr<addrinfo, deleter> addr)
: data{std::move(addr)} {}
UVW_INLINE name_info_event::name_info_event(const char *host, const char *serv)
: hostname{host}, service{serv} {}
UVW_INLINE void get_addr_info_req::addr_info_callback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{res, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
ptr->publish(addr_info_event{std::move(data)});
}
}
UVW_INLINE int get_addr_info_req::node_addr_info(const char *node, const char *service, addrinfo *hints) {
return this->leak_if(uv_getaddrinfo(parent().raw(), raw(), &addr_info_callback, node, service, hints));
}
UVW_INLINE auto get_addr_info_req::node_addr_info_sync(const char *node, const char *service, addrinfo *hints) {
auto req = raw();
auto err = uv_getaddrinfo(parent().raw(), req, nullptr, node, service, hints);
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{req->addrinfo, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
return std::make_pair(!err, std::move(data));
}
UVW_INLINE int get_addr_info_req::node_addr_info(const std::string &node, addrinfo *hints) {
return node_addr_info(node.data(), nullptr, hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::node_addr_info_sync(const std::string &node, addrinfo *hints) {
return node_addr_info_sync(node.data(), nullptr, hints);
}
UVW_INLINE int get_addr_info_req::service_addr_info(const std::string &service, addrinfo *hints) {
return node_addr_info(nullptr, service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::service_addr_info_sync(const std::string &service, addrinfo *hints) {
return node_addr_info_sync(nullptr, service.data(), hints);
}
UVW_INLINE int get_addr_info_req::addr_info(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info(node.data(), service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::addr_info_sync(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info_sync(node.data(), service.data(), hints);
}
UVW_INLINE void get_name_info_req::name_info_callback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(name_info_event{hostname, service});
}
}
UVW_INLINE int get_name_info_req::name_info(const sockaddr &addr, int flags) {
return this->leak_if(uv_getnameinfo(parent().raw(), raw(), &name_info_callback, &addr, flags));
}
UVW_INLINE int get_name_info_req::name_info(const std::string &ip, unsigned int port, int flags) {
return name_info(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE int get_name_info_req::name_info(socket_address addr, int flags) {
return name_info(std::move(addr.ip), addr.port, flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const sockaddr &addr, int flags) {
auto req = raw();
auto err = uv_getnameinfo(parent().raw(), req, nullptr, &addr, flags);
return std::make_pair(!err, std::make_pair(req->host, req->service));
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const std::string &ip, unsigned int port, int flags) {
return name_info_sync(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(socket_address addr, int flags) {
return name_info_sync(addr.ip, addr.port, flags);
}
} // namespace uvw
#include "dns.h"
#include "dns.ipp"

View File

@ -171,7 +171,7 @@ public:
* @param flags Optional flags that modify the behavior of `getnameinfo`.
* @return Underlying return value.
*/
int name_info(socket_address addr, int flags = 0);
int name_info(const socket_address &addr, int flags = 0);
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
@ -214,13 +214,13 @@ public:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(socket_address addr, int flags = 0);
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(const socket_address &addr, int flags = 0);
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "dns.cpp"
# include "dns.ipp"
#endif
#endif // UVW_DNS_INCLUDE_H

89
src/uvw/dns.ipp Normal file
View File

@ -0,0 +1,89 @@
#include "config.h"
namespace uvw {
UVW_INLINE addr_info_event::addr_info_event(std::unique_ptr<addrinfo, deleter> addr)
: data{std::move(addr)} {}
UVW_INLINE name_info_event::name_info_event(const char *host, const char *serv)
: hostname{host}, service{serv} {}
UVW_INLINE void get_addr_info_req::addr_info_callback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{res, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
ptr->publish(addr_info_event{std::move(data)});
}
}
UVW_INLINE int get_addr_info_req::node_addr_info(const char *node, const char *service, addrinfo *hints) {
return this->leak_if(uv_getaddrinfo(parent().raw(), raw(), &addr_info_callback, node, service, hints));
}
UVW_INLINE auto get_addr_info_req::node_addr_info_sync(const char *node, const char *service, addrinfo *hints) {
auto req = raw();
auto err = uv_getaddrinfo(parent().raw(), req, nullptr, node, service, hints);
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{req->addrinfo, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
return std::make_pair(!err, std::move(data));
}
UVW_INLINE int get_addr_info_req::node_addr_info(const std::string &node, addrinfo *hints) {
return node_addr_info(node.data(), nullptr, hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::node_addr_info_sync(const std::string &node, addrinfo *hints) {
return node_addr_info_sync(node.data(), nullptr, hints);
}
UVW_INLINE int get_addr_info_req::service_addr_info(const std::string &service, addrinfo *hints) {
return node_addr_info(nullptr, service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::service_addr_info_sync(const std::string &service, addrinfo *hints) {
return node_addr_info_sync(nullptr, service.data(), hints);
}
UVW_INLINE int get_addr_info_req::addr_info(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info(node.data(), service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::addr_info_sync(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info_sync(node.data(), service.data(), hints);
}
UVW_INLINE void get_name_info_req::name_info_callback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(name_info_event{hostname, service});
}
}
UVW_INLINE int get_name_info_req::name_info(const sockaddr &addr, int flags) {
return this->leak_if(uv_getnameinfo(parent().raw(), raw(), &name_info_callback, &addr, flags));
}
UVW_INLINE int get_name_info_req::name_info(const std::string &ip, unsigned int port, int flags) {
return name_info(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE int get_name_info_req::name_info(const socket_address &addr, int flags) {
return name_info(addr.ip, addr.port, flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const sockaddr &addr, int flags) {
auto req = raw();
auto err = uv_getnameinfo(parent().raw(), req, nullptr, &addr, flags);
return std::make_pair(!err, std::make_pair(req->host, req->service));
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const std::string &ip, unsigned int port, int flags) {
return name_info_sync(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const socket_address &addr, int flags) {
return name_info_sync(addr.ip, addr.port, flags);
}
} // namespace uvw

View File

@ -1,29 +1,2 @@
#ifdef UVW_AS_LIB
# include "emitter.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE int error_event::translate(int sys) noexcept {
return uv_translate_sys_error(sys);
}
UVW_INLINE const char *error_event::what() const noexcept {
return uv_strerror(ec);
}
UVW_INLINE const char *error_event::name() const noexcept {
return uv_err_name(ec);
}
UVW_INLINE int error_event::code() const noexcept {
return ec;
}
UVW_INLINE error_event::operator bool() const noexcept {
return ec < 0;
}
} // namespace uvw
#include "emitter.h"
#include "emitter.ipp"

View File

@ -37,7 +37,7 @@ struct error_event {
* @param sys A platform dependent error code.
* @return The `libuv` error code equivalent to the given platform dependent error code.
*/
static int translate(int sys) noexcept;
[[nodiscard]] static int translate(int sys) noexcept;
/**
* @brief Returns the error message for the given error code.
@ -46,7 +46,7 @@ struct error_event {
*
* @return The error message for the given error code.
*/
const char *what() const noexcept;
[[nodiscard]] const char *what() const noexcept;
/**
* @brief Returns the error name for the given error code.
@ -55,13 +55,13 @@ struct error_event {
*
* @return The error name for the given error code.
*/
const char *name() const noexcept;
[[nodiscard]] const char *name() const noexcept;
/**
* @brief Gets the underlying error code, that is an error constant of `libuv`.
* @return The underlying error code.
*/
int code() const noexcept;
[[nodiscard]] int code() const noexcept;
/**
* @brief Checks if the event contains a valid error code.
@ -70,7 +70,7 @@ struct error_event {
explicit operator bool() const noexcept;
private:
const int ec;
int ec;
};
/**
@ -87,12 +87,12 @@ public:
private:
template<typename Type>
const auto &handler() const noexcept {
[[nodiscard]] const auto &handler() const noexcept {
return std::get<listener_t<Type>>(handlers);
}
template<typename Type>
auto &handler() noexcept {
[[nodiscard]] auto &handler() noexcept {
return std::get<listener_t<Type>>(handlers);
}
@ -142,7 +142,7 @@ public:
* false otherwise.
*/
template<typename Type>
bool has() const noexcept {
[[nodiscard]] bool has() const noexcept {
return static_cast<bool>(handler<Type>());
}
@ -153,7 +153,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "emitter.cpp"
# include "emitter.ipp"
#endif
#endif // UVW_EMITTER_INCLUDE_H

25
src/uvw/emitter.ipp Normal file
View File

@ -0,0 +1,25 @@
#include "config.h"
namespace uvw {
UVW_INLINE int error_event::translate(int sys) noexcept {
return uv_translate_sys_error(sys);
}
UVW_INLINE const char *error_event::what() const noexcept {
return uv_strerror(ec);
}
UVW_INLINE const char *error_event::name() const noexcept {
return uv_err_name(ec);
}
UVW_INLINE int error_event::code() const noexcept {
return ec;
}
UVW_INLINE error_event::operator bool() const noexcept {
return ec < 0;
}
} // namespace uvw

View File

@ -13,21 +13,21 @@
* two values provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator|(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator&(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator^(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
}
@ -40,35 +40,35 @@ operator^(const Type lhs, const Type rhs) noexcept {
* value provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator~(const Type value) noexcept {
return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
}
/*! @copydoc operator~ */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM, bool{})>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM, bool{})>
operator!(const Type value) noexcept {
return !static_cast<std::underlying_type_t<Type>>(value);
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator|=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs | rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator&=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs & rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator^=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs ^ rhs));
}

View File

@ -1,553 +1,2 @@
#ifdef UVW_AS_LIB
# include "fs.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void file_req::fs_open_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = static_cast<uv_file>(req->result);
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_close_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = BAD_FD;
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_read_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->publish(fs_event{*req, std::move(ptr->current)});
}
}
UVW_INLINE file_req::~file_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void file_req::close() {
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), raw(), file, &fs_close_callback);
}
UVW_INLINE bool file_req::close_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), req, file, nullptr);
if(req->result >= 0) {
file = BAD_FD;
}
return !(req->result < 0);
}
UVW_INLINE void file_req::open(const std::string &path, file_open_flags flags, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), raw(), path.data(), static_cast<int>(flags), mode, &fs_open_callback);
}
UVW_INLINE bool file_req::open_sync(const std::string &path, file_open_flags flags, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), req, path.data(), static_cast<int>(flags), mode, nullptr);
if(req->result >= 0) {
file = static_cast<uv_file>(req->result);
}
return !(req->result < 0);
}
UVW_INLINE void file_req::read(int64_t offset, unsigned int len) {
current = std::unique_ptr<char[]>{new char[len]};
buffer = uv_buf_init(current.get(), len);
uv_buf_t bufs[] = {buffer};
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), raw(), file, bufs, 1, offset, &fs_read_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::unique_ptr<const char[]>, std::size_t>> file_req::read_sync(int64_t offset, unsigned int len) {
current = std::unique_ptr<char[]>{new char[len]};
buffer = uv_buf_init(current.get(), len);
uv_buf_t bufs[] = {buffer};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), req, file, bufs, 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(std::move(current), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void file_req::write(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
uv_buf_t bufs[] = {uv_buf_init(current.get(), len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs, 1, offset, &fs_request_callback);
}
UVW_INLINE void file_req::write(char *buf, unsigned int len, int64_t offset) {
uv_buf_t bufs[] = {uv_buf_init(buf, len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs, 1, offset, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::write_sync(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
uv_buf_t bufs[] = {uv_buf_init(current.get(), len)};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), req, file, bufs, 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::stat() {
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> file_req::stat_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), req, file, nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void file_req::sync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::sync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::datasync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::datasync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::truncate(int64_t offset) {
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), raw(), file, offset, &fs_request_callback);
}
UVW_INLINE bool file_req::truncate_sync(int64_t offset) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), req, file, offset, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::sendfile(file_handle out, int64_t offset, std::size_t length) {
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), raw(), out, file, offset, length, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::sendfile_sync(file_handle out, int64_t offset, std::size_t length) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), req, out, file, offset, length, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::chmod(int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), raw(), file, mode, &fs_request_callback);
}
UVW_INLINE bool file_req::chmod_sync(int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), req, file, mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::futime(fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), raw(), file, atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool file_req::futime_sync(fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), req, file, atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::chown(uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), raw(), file, uid, gid, &fs_request_callback);
}
UVW_INLINE bool file_req::chown_sync(uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), req, file, uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE file_req::operator file_handle() const noexcept {
return file;
}
UVW_INLINE fs_req::~fs_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void fs_req::unlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::unlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdir(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::mkdir_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdtemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::mkdtemp_sync(const std::string &tpl) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), req, tpl.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::mkstemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::string, std::size_t>> fs_req::mkstemp_sync(const std::string &tpl) {
std::pair<bool, std::pair<std::string, std::size_t>> ret{false, {}};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), req, tpl.data(), nullptr);
ret.first = !(req->result < 0);
if(ret.first) {
ret.second.first = req->path;
ret.second.second = static_cast<std::size_t>(req->result);
}
return ret;
}
UVW_INLINE void fs_req::lutime(const std::string &path, time atime, time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::lutime_sync(const std::string &path, time atime, time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::rmdir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rmdir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::scandir(const std::string &path, int flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), raw(), path.data(), flags, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> fs_req::scandir_sync(const std::string &path, int flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), req, path.data(), flags, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::scandir_next() {
std::pair<bool, std::pair<entry_type, const char *>> ret{false, {entry_type::UNKNOWN, nullptr}};
uv_fs_req_cleanup(raw());
auto res = uv_fs_scandir_next(raw(), dirents);
if(UV_EOF != res) {
ret.second.first = static_cast<entry_type>(dirents[0].type);
ret.second.second = dirents[0].name;
ret.first = true;
}
return ret;
}
UVW_INLINE void fs_req::stat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::stat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::lstat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::lstat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::statfs(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, fs_info> fs_req::statfs_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), *static_cast<uv_statfs_t *>(req->ptr));
}
UVW_INLINE void fs_req::rename(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rename_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::copyfile(const std::string &old, const std::string &path, copy_file_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::access(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::access_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::chmod(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::chmod_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::utime(const std::string &path, fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::utime_sync(const std::string &path, fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::link(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::link_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::symlink(const std::string &old, const std::string &path, symlink_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::symlink_sync(const std::string &old, const std::string &path, symlink_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), req, old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<const char *, std::size_t>> fs_req::readlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), req, path.data(), nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(static_cast<char *>(req->ptr), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void fs_req::realpath(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::realpath_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::chown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::chown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::lchown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::lchown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::opendir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::opendir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::closedir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE bool fs_req::closedir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readdir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::readdir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, nullptr);
return {req->result != 0, {static_cast<entry_type>(dirents[0].type), dirents[0].name}};
}
UVW_INLINE os_file_descriptor fs_helper::handle(file_handle file) noexcept {
return uv_get_osfhandle(file);
}
UVW_INLINE file_handle fs_helper::open(os_file_descriptor descriptor) noexcept {
return uv_open_osfhandle(descriptor);
}
} // namespace uvw
#include "fs.h"
#include "fs.ipp"

View File

@ -91,20 +91,20 @@ enum class uvw_file_open_flags : int {
TEMPORARY = UV_FS_O_TEMPORARY,
TRUNC = UV_FS_O_TRUNC,
WRONLY = UV_FS_O_WRONLY,
_UVW_ENUM = 0
UVW_ENUM = 0
};
enum class uvw_copy_file_flags : int {
EXCL = UV_FS_COPYFILE_EXCL,
FICLONE = UV_FS_COPYFILE_FICLONE,
FICLONE_FORCE = UV_FS_COPYFILE_FICLONE_FORCE,
_UVW_ENUM = 0
UVW_ENUM = 0
};
enum class uvw_symlink_flags : int {
DIR = UV_FS_SYMLINK_DIR,
JUNCTION = UV_FS_SYMLINK_JUNCTION,
_UVW_ENUM = 0
UVW_ENUM = 0
};
} // namespace details
@ -263,7 +263,7 @@ public:
using fs_request::fs_request;
~file_req() noexcept;
~file_req() noexcept override;
/**
* @brief Async [close](http://linux.die.net/man/2/close).
@ -595,7 +595,7 @@ public:
using fs_request::fs_request;
~fs_req() noexcept;
~fs_req() noexcept override;
/**
* @brief Async [unlink](http://linux.die.net/man/2/unlink).
@ -886,7 +886,7 @@ public:
* @param path New path, as described in the official documentation.
* @param flags Optional additional flags.
*/
void copyfile(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::_UVW_ENUM);
void copyfile(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::UVW_ENUM);
/**
* @brief Copies a file synchronously from a path to a new one.
@ -907,7 +907,7 @@ public:
* @param flags Optional additional flags.
* @return True in case of success, false otherwise.
*/
bool copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::_UVW_ENUM);
bool copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::UVW_ENUM);
/**
* @brief Async [access](http://linux.die.net/man/2/access).
@ -1003,7 +1003,7 @@ public:
* @param path New path, as described in the official documentation.
* @param flags Optional additional flags.
*/
void symlink(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::_UVW_ENUM);
void symlink(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::UVW_ENUM);
/**
* @brief Sync [symlink](http://linux.die.net/man/2/symlink).
@ -1020,7 +1020,7 @@ public:
* @param flags Flags, as described in the official documentation.
* @return True in case of success, false otherwise.
*/
bool symlink_sync(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::_UVW_ENUM);
bool symlink_sync(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::UVW_ENUM);
/**
* @brief Async [readlink](http://linux.die.net/man/2/readlink).
@ -1196,7 +1196,7 @@ public:
std::pair<bool, std::pair<entry_type, const char *>> readdir_sync();
private:
uv_dirent_t dirents[1];
uv_dirent_t dirents;
};
/*! @brief Helper functions. */
@ -1229,7 +1229,7 @@ struct fs_helper {
} // namespace uvw
#ifndef UVW_AS_LIB
# include "fs.cpp"
# include "fs.ipp"
#endif
#endif // UVW_FS_INCLUDE_H

550
src/uvw/fs.ipp Normal file
View File

@ -0,0 +1,550 @@
#include <array>
#include "config.h"
namespace uvw {
UVW_INLINE void file_req::fs_open_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = static_cast<uv_file>(req->result);
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_close_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = BAD_FD;
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_read_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->publish(fs_event{*req, std::move(ptr->current)});
}
}
UVW_INLINE file_req::~file_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void file_req::close() {
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), raw(), file, &fs_close_callback);
}
UVW_INLINE bool file_req::close_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), req, file, nullptr);
if(req->result >= 0) {
file = BAD_FD;
}
return !(req->result < 0);
}
UVW_INLINE void file_req::open(const std::string &path, file_open_flags flags, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), raw(), path.data(), static_cast<int>(flags), mode, &fs_open_callback);
}
UVW_INLINE bool file_req::open_sync(const std::string &path, file_open_flags flags, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), req, path.data(), static_cast<int>(flags), mode, nullptr);
if(req->result >= 0) {
file = static_cast<uv_file>(req->result);
}
return !(req->result < 0);
}
UVW_INLINE void file_req::read(int64_t offset, unsigned int len) {
current = std::make_unique<char[]>(len);
buffer = uv_buf_init(current.get(), len);
std::array bufs{buffer};
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_read_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::unique_ptr<const char[]>, std::size_t>> file_req::read_sync(int64_t offset, unsigned int len) {
current = std::make_unique<char[]>(len);
buffer = uv_buf_init(current.get(), len);
std::array bufs{buffer};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), req, file, bufs.data(), 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(std::move(current), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void file_req::write(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
std::array bufs{uv_buf_init(current.get(), len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_request_callback);
}
UVW_INLINE void file_req::write(char *buf, unsigned int len, int64_t offset) {
std::array bufs{uv_buf_init(buf, len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::write_sync(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
std::array bufs{uv_buf_init(current.get(), len)};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), req, file, bufs.data(), 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::stat() {
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> file_req::stat_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), req, file, nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void file_req::sync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::sync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::datasync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::datasync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::truncate(int64_t offset) {
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), raw(), file, offset, &fs_request_callback);
}
UVW_INLINE bool file_req::truncate_sync(int64_t offset) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), req, file, offset, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::sendfile(file_handle out, int64_t offset, std::size_t length) {
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), raw(), out, file, offset, length, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::sendfile_sync(file_handle out, int64_t offset, std::size_t length) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), req, out, file, offset, length, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::chmod(int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), raw(), file, mode, &fs_request_callback);
}
UVW_INLINE bool file_req::chmod_sync(int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), req, file, mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::futime(fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), raw(), file, atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool file_req::futime_sync(fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), req, file, atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::chown(uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), raw(), file, uid, gid, &fs_request_callback);
}
UVW_INLINE bool file_req::chown_sync(uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), req, file, uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE file_req::operator file_handle() const noexcept {
return file;
}
UVW_INLINE fs_req::~fs_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void fs_req::unlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::unlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdir(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::mkdir_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdtemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::mkdtemp_sync(const std::string &tpl) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), req, tpl.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::mkstemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::string, std::size_t>> fs_req::mkstemp_sync(const std::string &tpl) {
std::pair<bool, std::pair<std::string, std::size_t>> ret{false, {}};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), req, tpl.data(), nullptr);
ret.first = !(req->result < 0);
if(ret.first) {
ret.second.first = req->path;
ret.second.second = static_cast<std::size_t>(req->result);
}
return ret;
}
UVW_INLINE void fs_req::lutime(const std::string &path, time atime, time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::lutime_sync(const std::string &path, time atime, time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::rmdir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rmdir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::scandir(const std::string &path, int flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), raw(), path.data(), flags, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> fs_req::scandir_sync(const std::string &path, int flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), req, path.data(), flags, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::scandir_next() {
std::pair<bool, std::pair<entry_type, const char *>> ret{false, {entry_type::UNKNOWN, nullptr}};
uv_fs_req_cleanup(raw());
auto res = uv_fs_scandir_next(raw(), &dirents);
if(UV_EOF != res) {
ret.second.first = static_cast<entry_type>(dirents.type);
ret.second.second = dirents.name;
ret.first = true;
}
return ret;
}
UVW_INLINE void fs_req::stat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::stat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::lstat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::lstat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::statfs(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, fs_info> fs_req::statfs_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), *static_cast<uv_statfs_t *>(req->ptr));
}
UVW_INLINE void fs_req::rename(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rename_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::copyfile(const std::string &old, const std::string &path, copy_file_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::access(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::access_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::chmod(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::chmod_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::utime(const std::string &path, fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::utime_sync(const std::string &path, fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::link(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::link_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::symlink(const std::string &old, const std::string &path, symlink_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::symlink_sync(const std::string &old, const std::string &path, symlink_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), req, old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<const char *, std::size_t>> fs_req::readlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), req, path.data(), nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(static_cast<char *>(req->ptr), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void fs_req::realpath(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::realpath_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::chown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::chown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::lchown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::lchown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::opendir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::opendir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::closedir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE bool fs_req::closedir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readdir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = &dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::readdir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = &dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, nullptr);
return {req->result != 0, {static_cast<entry_type>(dirents.type), dirents.name}};
}
UVW_INLINE os_file_descriptor fs_helper::handle(file_handle file) noexcept {
return uv_get_osfhandle(file);
}
UVW_INLINE file_handle fs_helper::open(os_file_descriptor descriptor) noexcept {
return uv_open_osfhandle(descriptor);
}
} // namespace uvw

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB
# include "fs_event.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE fs_event_event::fs_event_event(const char *pathname, details::uvw_fs_event events)
: filename{pathname}, flags{std::move(events)} {}
UVW_INLINE void fs_event_handle::start_callback(uv_fs_event_t *hndl, const char *filename, int events, int status) {
if(fs_event_handle &fsEvent = *(static_cast<fs_event_handle *>(hndl->data)); status) {
fsEvent.publish(error_event{status});
} else {
fsEvent.publish(fs_event_event{filename, details::uvw_fs_event(events)});
}
}
UVW_INLINE int fs_event_handle::init() {
return leak_if(uv_fs_event_init(parent().raw(), raw()));
}
UVW_INLINE int fs_event_handle::start(const std::string &path, event_flags flags) {
return uv_fs_event_start(raw(), &start_callback, path.data(), static_cast<uv_fs_event_flags>(flags));
}
UVW_INLINE int fs_event_handle::stop() {
return uv_fs_event_stop(raw());
}
UVW_INLINE std::string fs_event_handle::path() noexcept {
return details::try_read(&uv_fs_event_getpath, raw());
}
} // namespace uvw
#include "fs_event.h"
#include "fs_event.ipp"

View File

@ -18,7 +18,7 @@ enum class uvw_fs_event_flags : std::underlying_type_t<uv_fs_event_flags> {
WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY,
STAT = UV_FS_EVENT_STAT,
RECURSIVE = UV_FS_EVENT_RECURSIVE,
_UVW_ENUM = 0
UVW_ENUM = 0
};
enum class uvw_fs_event : std::underlying_type_t<uv_fs_event> {
@ -96,7 +96,7 @@ public:
* @param flags Additional flags to control the behavior.
* @return Underlying return value.
*/
int start(const std::string &path, event_flags flags = event_flags::_UVW_ENUM);
int start(const std::string &path, event_flags flags = event_flags::UVW_ENUM);
/**
* @brief Stops polling the file descriptor.
@ -114,7 +114,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "fs_event.cpp"
# include "fs_event.ipp"
#endif
#endif // UVW_FS_EVENT_INCLUDE_H

33
src/uvw/fs_event.ipp Normal file
View File

@ -0,0 +1,33 @@
#include "config.h"
namespace uvw {
UVW_INLINE fs_event_event::fs_event_event(const char *pathname, details::uvw_fs_event events)
: filename{pathname}, flags{events} {}
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
UVW_INLINE void fs_event_handle::start_callback(uv_fs_event_t *hndl, const char *filename, int events, int status) {
if(fs_event_handle &fsEvent = *(static_cast<fs_event_handle *>(hndl->data)); status) {
fsEvent.publish(error_event{status});
} else {
fsEvent.publish(fs_event_event{filename, details::uvw_fs_event(events)});
}
}
UVW_INLINE int fs_event_handle::init() {
return leak_if(uv_fs_event_init(parent().raw(), raw()));
}
UVW_INLINE int fs_event_handle::start(const std::string &path, event_flags flags) {
return uv_fs_event_start(raw(), &start_callback, path.data(), static_cast<uv_fs_event_flags>(flags));
}
UVW_INLINE int fs_event_handle::stop() {
return uv_fs_event_stop(raw());
}
UVW_INLINE std::string fs_event_handle::path() noexcept {
return details::try_read(&uv_fs_event_getpath, raw());
}
} // namespace uvw

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB
# include "fs_poll.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE fs_poll_event::fs_poll_event(file_info previous, file_info current) noexcept
: prev{std::move(previous)}, curr{std::move(current)} {}
UVW_INLINE void fs_poll_handle::start_callback(uv_fs_poll_t *hndl, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
if(fs_poll_handle &fsPoll = *(static_cast<fs_poll_handle *>(hndl->data)); status) {
fsPoll.publish(error_event{status});
} else {
fsPoll.publish(fs_poll_event{*prev, *curr});
}
}
UVW_INLINE int fs_poll_handle::init() {
return leak_if(uv_fs_poll_init(parent().raw(), raw()));
}
UVW_INLINE int fs_poll_handle::start(const std::string &file, fs_poll_handle::time interval) {
return uv_fs_poll_start(raw(), &start_callback, file.data(), interval.count());
}
UVW_INLINE int fs_poll_handle::stop() {
return uv_fs_poll_stop(raw());
}
UVW_INLINE std::string fs_poll_handle::path() noexcept {
return details::try_read(&uv_fs_poll_getpath, raw());
}
} // namespace uvw
#include "fs_poll.h"
#include "fs_poll.ipp"

View File

@ -70,7 +70,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "fs_poll.cpp"
# include "fs_poll.ipp"
#endif
#endif // UVW_FS_POLL_INCLUDE_H

32
src/uvw/fs_poll.ipp Normal file
View File

@ -0,0 +1,32 @@
#include "config.h"
namespace uvw {
UVW_INLINE fs_poll_event::fs_poll_event(file_info previous, file_info current) noexcept
: prev{previous}, curr{current} {}
UVW_INLINE void fs_poll_handle::start_callback(uv_fs_poll_t *hndl, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
if(fs_poll_handle &fsPoll = *(static_cast<fs_poll_handle *>(hndl->data)); status) {
fsPoll.publish(error_event{status});
} else {
fsPoll.publish(fs_poll_event{*prev, *curr});
}
}
UVW_INLINE int fs_poll_handle::init() {
return leak_if(uv_fs_poll_init(parent().raw(), raw()));
}
UVW_INLINE int fs_poll_handle::start(const std::string &file, fs_poll_handle::time interval) {
return uv_fs_poll_start(raw(), &start_callback, file.data(), interval.count());
}
UVW_INLINE int fs_poll_handle::stop() {
return uv_fs_poll_stop(raw());
}
UVW_INLINE std::string fs_poll_handle::path() noexcept {
return details::try_read(&uv_fs_poll_getpath, raw());
}
} // namespace uvw

View File

@ -29,11 +29,11 @@ protected:
ref.publish(close_event{});
}
uv_handle_t *as_uv_handle() {
[[nodiscard]] uv_handle_t *as_uv_handle() {
return reinterpret_cast<uv_handle_t *>(this->raw());
}
const uv_handle_t *as_uv_handle() const {
[[nodiscard]] const uv_handle_t *as_uv_handle() const {
return reinterpret_cast<const uv_handle_t *>(this->raw());
}
@ -49,7 +49,7 @@ public:
*
* @return The actual category of the handle.
*/
handle_category category() const noexcept {
[[nodiscard]] handle_category category() const noexcept {
return handle_category{as_uv_handle()->type};
}
@ -62,7 +62,7 @@ public:
*
* @return The actual type of the handle.
*/
handle_type type() const noexcept {
[[nodiscard]] handle_type type() const noexcept {
return utilities::guess_handle(category());
}
@ -85,7 +85,7 @@ public:
*
* @return True if the handle is active, false otherwise.
*/
bool active() const noexcept {
[[nodiscard]] bool active() const noexcept {
return !!uv_is_active(as_uv_handle());
}
@ -97,7 +97,7 @@ public:
*
* @return True if the handle is closing or closed, false otherwise.
*/
bool closing() const noexcept {
[[nodiscard]] bool closing() const noexcept {
return !!uv_is_closing(as_uv_handle());
}
@ -139,7 +139,7 @@ public:
* @brief Checks if the given handle referenced.
* @return True if the handle referenced, false otherwise.
*/
bool referenced() const noexcept {
[[nodiscard]] bool referenced() const noexcept {
return !!uv_has_ref(as_uv_handle());
}
@ -147,7 +147,7 @@ public:
* @brief Returns the size of the underlying handle type.
* @return The size of the underlying handle type.
*/
std::size_t size() const noexcept {
[[nodiscard]] std::size_t size() const noexcept {
return uv_handle_size(as_uv_handle()->type);
}
@ -163,7 +163,7 @@ public:
* @return The size of the send buffer, the underlying return value in case
* of errors.
*/
int send_buffer_size() {
[[nodiscard]] int send_buffer_size() {
int value = 0;
auto err = uv_send_buffer_size(as_uv_handle(), &value);
return err ? err : value;
@ -180,7 +180,7 @@ public:
*
* @return Underlying return value.
*/
int send_buffer_size(int value) {
[[nodiscard]] int send_buffer_size(int value) {
return uv_send_buffer_size(as_uv_handle(), &value);
}
@ -196,7 +196,7 @@ public:
* @return The size of the receive buffer, the underlying return value in
* case of errors.
*/
int recv_buffer_size() {
[[nodiscard]] int recv_buffer_size() {
int value = 0;
auto err = uv_recv_buffer_size(as_uv_handle(), &value);
return err ? err : value;
@ -213,7 +213,7 @@ public:
*
* @return Underlying return value.
*/
int recv_buffer_size(int value) {
[[nodiscard]] int recv_buffer_size(int value) {
return uv_recv_buffer_size(as_uv_handle(), &value);
}
@ -238,7 +238,7 @@ public:
* @return The file descriptor attached to the hande or a negative value in
* case of errors.
*/
os_file_descriptor fd() const {
[[nodiscard]] os_file_descriptor fd() const {
uv_os_fd_t fd;
uv_fileno(as_uv_handle(), &fd);
return fd;

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB
# include "idle.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void idle_handle::start_callback(uv_idle_t *hndl) {
idle_handle &idle = *(static_cast<idle_handle *>(hndl->data));
idle.publish(idle_event{});
}
UVW_INLINE int idle_handle::init() {
return leak_if(uv_idle_init(parent().raw(), raw()));
}
UVW_INLINE int idle_handle::start() {
return uv_idle_start(raw(), &start_callback);
}
UVW_INLINE int idle_handle::stop() {
return uv_idle_stop(raw());
}
} // namespace uvw
#include "idle.h"
#include "idle.ipp"

View File

@ -59,7 +59,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "idle.cpp"
# include "idle.ipp"
#endif
#endif // UVW_IDLE_INCLUDE_H

22
src/uvw/idle.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void idle_handle::start_callback(uv_idle_t *hndl) {
idle_handle &idle = *(static_cast<idle_handle *>(hndl->data));
idle.publish(idle_event{});
}
UVW_INLINE int idle_handle::init() {
return leak_if(uv_idle_init(parent().raw(), raw()));
}
UVW_INLINE int idle_handle::start() {
return uv_idle_start(raw(), &start_callback);
}
UVW_INLINE int idle_handle::stop() {
return uv_idle_stop(raw());
}
} // namespace uvw

View File

@ -1,27 +1,2 @@
#ifdef UVW_AS_LIB
# include "lib.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE shared_lib::shared_lib(loop::token token, std::shared_ptr<loop> ref, const std::string &filename) noexcept
: uv_type{token, std::move(ref)} {
opened = (0 == uv_dlopen(filename.data(), raw()));
}
UVW_INLINE shared_lib::~shared_lib() noexcept {
uv_dlclose(raw());
}
UVW_INLINE shared_lib::operator bool() const noexcept {
return opened;
}
UVW_INLINE const char *shared_lib::error() const noexcept {
return uv_dlerror(raw());
}
} // namespace uvw
#include "lib.h"
#include "lib.ipp"

View File

@ -43,7 +43,9 @@ public:
static_assert(std::is_function_v<F>);
F *func;
auto err = uv_dlsym(raw(), name.data(), reinterpret_cast<void **>(&func));
if(err) { func = nullptr; }
if(err) {
func = nullptr;
}
return func;
}
@ -51,7 +53,7 @@ public:
* @brief Returns the last error message, if any.
* @return The last error message, if any.
*/
const char *error() const noexcept;
[[nodiscard]] const char *error() const noexcept;
private:
bool opened;
@ -60,7 +62,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "lib.cpp"
# include "lib.ipp"
#endif
#endif // UVW_LIB_INCLUDE_H

23
src/uvw/lib.ipp Normal file
View File

@ -0,0 +1,23 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE shared_lib::shared_lib(loop::token token, std::shared_ptr<loop> ref, const std::string &filename) noexcept
: uv_type{token, std::move(ref)} {
opened = (0 == uv_dlopen(filename.data(), raw()));
}
UVW_INLINE shared_lib::~shared_lib() noexcept {
uv_dlclose(raw());
}
UVW_INLINE shared_lib::operator bool() const noexcept {
return opened;
}
UVW_INLINE const char *shared_lib::error() const noexcept {
return uv_dlerror(raw());
}
} // namespace uvw

View File

@ -1,120 +1,2 @@
#ifdef UVW_AS_LIB
# include "loop.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE loop::loop(std::unique_ptr<uv_loop_t, deleter> ptr) noexcept
: uv_loop{std::move(ptr)} {}
UVW_INLINE std::shared_ptr<loop> loop::create() {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{new uv_loop_t, [](uv_loop_t *l) { delete l; }};
auto curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
if(uv_loop_init(curr->uv_loop.get())) {
curr = nullptr;
}
return curr;
}
UVW_INLINE std::shared_ptr<loop> loop::create(uv_loop_t *res) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{res, [](uv_loop_t *) {}};
return std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
UVW_INLINE std::shared_ptr<loop> loop::get_default() {
static std::weak_ptr<loop> ref;
std::shared_ptr<loop> curr;
if(ref.expired()) {
auto def = uv_default_loop();
if(def) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>(def, [](uv_loop_t *) {});
curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
ref = curr;
} else {
curr = ref.lock();
}
return curr;
}
UVW_INLINE loop::~loop() noexcept {
if(uv_loop) {
close();
}
}
UVW_INLINE int loop::close() {
int ret = 0;
if(uv_loop) {
ret = uv_loop_close(uv_loop.get());
uv_loop.reset();
}
return ret;
}
UVW_INLINE int loop::run(run_mode mode) noexcept {
return uv_run(uv_loop.get(), static_cast<uv_run_mode>(mode));
}
UVW_INLINE bool loop::alive() const noexcept {
return !!uv_loop_alive(uv_loop.get());
}
UVW_INLINE void loop::stop() noexcept {
uv_stop(uv_loop.get());
}
UVW_INLINE int loop::descriptor() const noexcept {
return uv_backend_fd(uv_loop.get());
}
UVW_INLINE std::pair<bool, loop::time> loop::timeout() const noexcept {
auto to = uv_backend_timeout(uv_loop.get());
return std::make_pair(to == -1, time{to});
}
UVW_INLINE loop::time loop::idle_time() const noexcept {
return time{uv_metrics_idle_time(uv_loop.get())};
}
UVW_INLINE metrics_type loop::metrics() const noexcept {
metrics_type res{};
uv_metrics_info(uv_loop.get(), &res);
return res;
}
UVW_INLINE loop::time loop::now() const noexcept {
return time{uv_now(uv_loop.get())};
}
UVW_INLINE void loop::update() const noexcept {
return uv_update_time(uv_loop.get());
}
UVW_INLINE int loop::fork() noexcept {
return uv_loop_fork(uv_loop.get());
}
UVW_INLINE void loop::data(std::shared_ptr<void> ud) {
user_data = std::move(ud);
}
UVW_INLINE const uv_loop_t *loop::raw() const noexcept {
return uv_loop.get();
}
UVW_INLINE uv_loop_t *loop::raw() noexcept {
return const_cast<uv_loop_t *>(const_cast<const loop *>(this)->raw());
}
} // namespace uvw
#include "loop.h"
#include "loop.ipp"

View File

@ -124,7 +124,7 @@ public:
loop &operator=(const loop &) = delete;
loop &operator=(loop &&other) = delete;
~loop() noexcept;
~loop() noexcept override;
/**
* @brief Sets additional loop options.
@ -433,7 +433,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "loop.cpp"
# include "loop.ipp"
#endif
#endif // UVW_LOOP_INCLUDE_H

116
src/uvw/loop.ipp Normal file
View File

@ -0,0 +1,116 @@
#include "config.h"
namespace uvw {
UVW_INLINE loop::loop(std::unique_ptr<uv_loop_t, deleter> ptr) noexcept
: uv_loop{std::move(ptr)} {}
UVW_INLINE std::shared_ptr<loop> loop::create() {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{new uv_loop_t, [](uv_loop_t *l) { delete l; }};
auto curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
if(uv_loop_init(curr->uv_loop.get())) {
curr = nullptr;
}
return curr;
}
UVW_INLINE std::shared_ptr<loop> loop::create(uv_loop_t *res) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{res, [](uv_loop_t *) {}};
return std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
UVW_INLINE std::shared_ptr<loop> loop::get_default() {
static std::weak_ptr<loop> ref;
std::shared_ptr<loop> curr;
if(ref.expired()) {
auto def = uv_default_loop();
if(def) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>(def, [](uv_loop_t *) {});
curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
ref = curr;
} else {
curr = ref.lock();
}
return curr;
}
UVW_INLINE loop::~loop() noexcept {
if(uv_loop) {
close();
}
}
UVW_INLINE int loop::close() {
int ret = 0;
if(uv_loop) {
ret = uv_loop_close(uv_loop.get());
uv_loop.reset();
}
return ret;
}
UVW_INLINE int loop::run(run_mode mode) noexcept {
return uv_run(uv_loop.get(), static_cast<uv_run_mode>(mode));
}
UVW_INLINE bool loop::alive() const noexcept {
return !!uv_loop_alive(uv_loop.get());
}
UVW_INLINE void loop::stop() noexcept {
uv_stop(uv_loop.get());
}
UVW_INLINE int loop::descriptor() const noexcept {
return uv_backend_fd(uv_loop.get());
}
UVW_INLINE std::pair<bool, loop::time> loop::timeout() const noexcept {
auto to = uv_backend_timeout(uv_loop.get());
return std::make_pair(to == -1, time{to});
}
UVW_INLINE loop::time loop::idle_time() const noexcept {
return time{uv_metrics_idle_time(uv_loop.get())};
}
UVW_INLINE metrics_type loop::metrics() const noexcept {
metrics_type res{};
uv_metrics_info(uv_loop.get(), &res);
return res;
}
UVW_INLINE loop::time loop::now() const noexcept {
return time{uv_now(uv_loop.get())};
}
UVW_INLINE void loop::update() const noexcept {
return uv_update_time(uv_loop.get());
}
UVW_INLINE int loop::fork() noexcept {
return uv_loop_fork(uv_loop.get());
}
UVW_INLINE void loop::data(std::shared_ptr<void> ud) {
user_data = std::move(ud);
}
UVW_INLINE const uv_loop_t *loop::raw() const noexcept {
return uv_loop.get();
}
UVW_INLINE uv_loop_t *loop::raw() noexcept {
return const_cast<uv_loop_t *>(const_cast<const loop *>(this)->raw());
}
} // namespace uvw

View File

@ -1,63 +1,2 @@
#ifdef UVW_AS_LIB
# include "pipe.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE pipe_handle::pipe_handle(loop::token token, std::shared_ptr<loop> ref, bool pass)
: stream_handle{token, std::move(ref)}, ipc{pass} {}
UVW_INLINE int pipe_handle::init() {
return leak_if(uv_pipe_init(parent().raw(), raw(), ipc));
}
UVW_INLINE int pipe_handle::open(file_handle file) {
return uv_pipe_open(raw(), file);
}
UVW_INLINE int pipe_handle::bind(const std::string &name, const bool no_truncate) {
return uv_pipe_bind2(raw(), name.data(), name.size(), no_truncate * UV_PIPE_NO_TRUNCATE);
}
UVW_INLINE int pipe_handle::connect(const std::string &name, const bool no_truncate) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto connect = parent().resource<details::connect_req>();
connect->on<error_event>(listener);
connect->on<connect_event>(listener);
unsigned int flags = no_truncate * UV_PIPE_NO_TRUNCATE;
return connect->connect(&uv_pipe_connect2, raw(), name.data(), name.size(), flags);
}
UVW_INLINE std::string pipe_handle::sock() const noexcept {
return details::try_read(&uv_pipe_getsockname, raw());
}
UVW_INLINE std::string pipe_handle::peer() const noexcept {
return details::try_read(&uv_pipe_getpeername, raw());
}
UVW_INLINE void pipe_handle::pending(int count) noexcept {
uv_pipe_pending_instances(raw(), count);
}
UVW_INLINE int pipe_handle::pending() noexcept {
return uv_pipe_pending_count(raw());
}
UVW_INLINE handle_type pipe_handle::receive() noexcept {
handle_category category = uv_pipe_pending_type(raw());
return utilities::guess_handle(category);
}
UVW_INLINE int pipe_handle::chmod(chmod_flags flags) noexcept {
return uv_pipe_chmod(raw(), static_cast<uv_poll_event>(flags));
}
} // namespace uvw
#include "pipe.h"
#include "pipe.ipp"

View File

@ -19,7 +19,7 @@ namespace details {
enum class uvw_chmod_flags : std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
_UVW_ENUM = 0
UVW_ENUM = 0
};
}
@ -158,7 +158,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "pipe.cpp"
# include "pipe.ipp"
#endif
#endif // UVW_PIPE_INCLUDE_H

59
src/uvw/pipe.ipp Normal file
View File

@ -0,0 +1,59 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE pipe_handle::pipe_handle(loop::token token, std::shared_ptr<loop> ref, bool pass)
: stream_handle{token, std::move(ref)}, ipc{pass} {}
UVW_INLINE int pipe_handle::init() {
return leak_if(uv_pipe_init(parent().raw(), raw(), ipc));
}
UVW_INLINE int pipe_handle::open(file_handle file) {
return uv_pipe_open(raw(), file);
}
UVW_INLINE int pipe_handle::bind(const std::string &name, const bool no_truncate) {
return uv_pipe_bind2(raw(), name.data(), name.size(), no_truncate * UV_PIPE_NO_TRUNCATE);
}
UVW_INLINE int pipe_handle::connect(const std::string &name, const bool no_truncate) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto connect = parent().resource<details::connect_req>();
connect->on<error_event>(listener);
connect->on<connect_event>(listener);
unsigned int flags = no_truncate * UV_PIPE_NO_TRUNCATE;
return connect->connect(&uv_pipe_connect2, raw(), name.data(), name.size(), flags);
}
UVW_INLINE std::string pipe_handle::sock() const noexcept {
return details::try_read(&uv_pipe_getsockname, raw());
}
UVW_INLINE std::string pipe_handle::peer() const noexcept {
return details::try_read(&uv_pipe_getpeername, raw());
}
UVW_INLINE void pipe_handle::pending(int count) noexcept {
uv_pipe_pending_instances(raw(), count);
}
UVW_INLINE int pipe_handle::pending() noexcept {
return uv_pipe_pending_count(raw());
}
UVW_INLINE handle_type pipe_handle::receive() noexcept {
handle_category category = uv_pipe_pending_type(raw());
return utilities::guess_handle(category);
}
UVW_INLINE int pipe_handle::chmod(chmod_flags flags) noexcept {
return uv_pipe_chmod(raw(), static_cast<uv_poll_event>(flags));
}
} // namespace uvw

View File

@ -1,43 +1,2 @@
#ifdef UVW_AS_LIB
# include "poll.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE poll_event::poll_event(details::uvw_poll_event events) noexcept
: flags{std::move(events)} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, int desc)
: handle{token, std::move(ref)}, tag{FD}, file_desc{desc} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, os_socket_handle sock)
: handle{token, std::move(ref)}, tag{SOCKET}, socket{sock} {}
UVW_INLINE void poll_handle::start_callback(uv_poll_t *hndl, int status, int events) {
if(poll_handle &poll = *(static_cast<poll_handle *>(hndl->data)); status) {
poll.publish(error_event{status});
} else {
poll.publish(poll_event{poll_event_flags(events)});
}
}
UVW_INLINE int poll_handle::init() {
if(tag == SOCKET) {
return leak_if(uv_poll_init_socket(parent().raw(), raw(), socket));
} else {
return leak_if(uv_poll_init(parent().raw(), raw(), file_desc));
}
}
UVW_INLINE int poll_handle::start(poll_event_flags flags) {
return uv_poll_start(raw(), static_cast<uv_poll_event>(flags), &start_callback);
}
UVW_INLINE int poll_handle::stop() {
return uv_poll_stop(raw());
}
} // namespace uvw
#include "poll.h"
#include "poll.ipp"

View File

@ -18,7 +18,7 @@ enum class uvw_poll_event : std::underlying_type_t<uv_poll_event> {
WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT,
PRIORITIZED = UV_PRIORITIZED,
_UVW_ENUM = 0
UVW_ENUM = 0
};
}
@ -113,7 +113,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "poll.cpp"
# include "poll.ipp"
#endif
#endif // UVW_POLL_INCLUDE_H

40
src/uvw/poll.ipp Normal file
View File

@ -0,0 +1,40 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE poll_event::poll_event(details::uvw_poll_event events) noexcept
: flags{events} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, int desc)
: handle{token, std::move(ref)}, tag{FD}, file_desc{desc} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, os_socket_handle sock)
: handle{token, std::move(ref)}, tag{SOCKET}, socket{sock} {}
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
UVW_INLINE void poll_handle::start_callback(uv_poll_t *hndl, int status, int events) {
if(poll_handle &poll = *(static_cast<poll_handle *>(hndl->data)); status) {
poll.publish(error_event{status});
} else {
poll.publish(poll_event{poll_event_flags(events)});
}
}
UVW_INLINE int poll_handle::init() {
if(tag == SOCKET) {
return leak_if(uv_poll_init_socket(parent().raw(), raw(), socket));
} else {
return leak_if(uv_poll_init(parent().raw(), raw(), file_desc));
}
}
UVW_INLINE int poll_handle::start(poll_event_flags flags) {
return uv_poll_start(raw(), static_cast<uv_poll_event>(flags), &start_callback);
}
UVW_INLINE int poll_handle::stop() {
return uv_poll_stop(raw());
}
} // namespace uvw

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB
# include "prepare.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void prepare_handle::start_callback(uv_prepare_t *hndl) {
prepare_handle &prepare = *(static_cast<prepare_handle *>(hndl->data));
prepare.publish(prepare_event{});
}
UVW_INLINE int prepare_handle::init() {
return leak_if(uv_prepare_init(parent().raw(), raw()));
}
UVW_INLINE int prepare_handle::start() {
return uv_prepare_start(raw(), &start_callback);
}
UVW_INLINE int prepare_handle::stop() {
return uv_prepare_stop(raw());
}
} // namespace uvw
#include "prepare.h"
#include "prepare.ipp"

View File

@ -52,7 +52,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "prepare.cpp"
# include "prepare.ipp"
#endif
#endif // UVW_PREPARE_INCLUDE_H

22
src/uvw/prepare.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void prepare_handle::start_callback(uv_prepare_t *hndl) {
prepare_handle &prepare = *(static_cast<prepare_handle *>(hndl->data));
prepare.publish(prepare_event{});
}
UVW_INLINE int prepare_handle::init() {
return leak_if(uv_prepare_init(parent().raw(), raw()));
}
UVW_INLINE int prepare_handle::start() {
return uv_prepare_start(raw(), &start_callback);
}
UVW_INLINE int prepare_handle::stop() {
return uv_prepare_stop(raw());
}
} // namespace uvw

View File

@ -1,111 +1,2 @@
#ifdef UVW_AS_LIB
# include "process.h"
#endif
#include <algorithm>
#include "config.h"
namespace uvw {
UVW_INLINE exit_event::exit_event(int64_t code, int sig) noexcept
: status{code}, signal{sig} {}
UVW_INLINE void process_handle::exit_callback(uv_process_t *hndl, int64_t exit_status, int term_signal) {
process_handle &process = *(static_cast<process_handle *>(hndl->data));
process.publish(exit_event{exit_status, term_signal});
}
UVW_INLINE process_handle::process_handle(loop::token token, std::shared_ptr<loop> ref)
: handle{token, std::move(ref)} {}
UVW_INLINE void process_handle::disable_stdio_inheritance() noexcept {
uv_disable_stdio_inheritance();
}
UVW_INLINE bool process_handle::kill(int pid, int signum) noexcept {
return (0 == uv_kill(pid, signum));
}
UVW_INLINE int process_handle::init() {
// deferred initialization: libuv initializes process handles only when
// uv_spawn is invoked and uvw stays true to the underlying library
return 0;
}
UVW_INLINE int process_handle::spawn(const char *file, char **args, char **env) {
uv_process_options_t po;
po.exit_cb = &exit_callback;
po.file = file;
po.args = args;
po.env = env;
po.cwd = po_cwd.empty() ? nullptr : po_cwd.data();
po.flags = static_cast<uv_process_flags>(po_flags);
po.uid = po_uid;
po.gid = po_gid;
std::vector<uv_stdio_container_t> poStdio;
poStdio.reserve(po_fd_stdio.size() + po_stream_stdio.size());
poStdio.insert(poStdio.begin(), po_fd_stdio.cbegin(), po_fd_stdio.cend());
poStdio.insert(poStdio.end(), po_stream_stdio.cbegin(), po_stream_stdio.cend());
po.stdio_count = static_cast<decltype(po.stdio_count)>(poStdio.size());
po.stdio = poStdio.data();
// see init member function for more details
leak_if(0);
return uv_spawn(parent().raw(), raw(), &po);
}
UVW_INLINE int process_handle::kill(int signum) {
return uv_process_kill(raw(), signum);
}
UVW_INLINE int process_handle::pid() noexcept {
return raw()->pid;
}
UVW_INLINE process_handle &process_handle::cwd(const std::string &path) noexcept {
po_cwd = path;
return *this;
}
UVW_INLINE process_handle &process_handle::flags(process_flags flags) noexcept {
po_flags = flags;
return *this;
}
UVW_INLINE process_handle &process_handle::stdio(file_handle fd, stdio_flags flags) {
auto fgs = static_cast<uv_stdio_flags>(flags);
auto actual = uvw::file_handle{fd};
auto it = std::find_if(po_fd_stdio.begin(), po_fd_stdio.end(), [actual](auto &&container) {
return static_cast<const uvw::details::uv_type_wrapper<int>>(container.data.fd) == static_cast<const uvw::details::uv_type_wrapper<int>>(actual);
});
if(it == po_fd_stdio.cend()) {
uv_stdio_container_t container;
container.flags = fgs;
container.data.fd = actual;
po_fd_stdio.push_back(std::move(container));
} else {
it->flags = fgs;
it->data.fd = actual;
}
return *this;
}
UVW_INLINE process_handle &process_handle::uid(uid_type id) {
po_uid = id;
return *this;
}
UVW_INLINE process_handle &process_handle::gid(gid_type id) {
po_gid = id;
return *this;
}
} // namespace uvw
#include "process.h"
#include "process.ipp"

View File

@ -26,7 +26,7 @@ enum class uvw_process_flags : std::underlying_type_t<uv_process_flags> {
WINDOWS_HIDE_CONSOLE = UV_PROCESS_WINDOWS_HIDE_CONSOLE,
WINDOWS_HIDE_GUI = UV_PROCESS_WINDOWS_HIDE_GUI,
WINDOWS_FILE_PATH_EXACT_NAME = UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME,
_UVW_ENUM = 0
UVW_ENUM = 0
};
enum class uvw_stdio_flags : std::underlying_type_t<uv_stdio_flags> {
@ -37,7 +37,7 @@ enum class uvw_stdio_flags : std::underlying_type_t<uv_stdio_flags> {
READABLE_PIPE = UV_READABLE_PIPE,
WRITABLE_PIPE = UV_WRITABLE_PIPE,
OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE,
_UVW_ENUM = 0
UVW_ENUM = 0
};
} // namespace details
@ -181,7 +181,7 @@ public:
uv_stdio_container_t container;
container.flags = static_cast<uv_stdio_flags>(flags);
container.data.stream = reinterpret_cast<uv_stream_t *>(stream.raw());
po_stream_stdio.push_back(std::move(container));
po_stream_stdio.push_back(container);
return *this;
}
@ -239,7 +239,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "process.cpp"
# include "process.ipp"
#endif
#endif // UVW_PROCESS_INCLUDE_H

107
src/uvw/process.ipp Normal file
View File

@ -0,0 +1,107 @@
#include <algorithm>
#include "config.h"
namespace uvw {
UVW_INLINE exit_event::exit_event(int64_t code, int sig) noexcept
: status{code}, signal{sig} {}
UVW_INLINE void process_handle::exit_callback(uv_process_t *hndl, int64_t exit_status, int term_signal) {
process_handle &process = *(static_cast<process_handle *>(hndl->data));
process.publish(exit_event{exit_status, term_signal});
}
UVW_INLINE process_handle::process_handle(loop::token token, std::shared_ptr<loop> ref)
: handle{token, std::move(ref)} {}
UVW_INLINE void process_handle::disable_stdio_inheritance() noexcept {
uv_disable_stdio_inheritance();
}
UVW_INLINE bool process_handle::kill(int pid, int signum) noexcept {
return (0 == uv_kill(pid, signum));
}
UVW_INLINE int process_handle::init() {
// deferred initialization: libuv initializes process handles only when
// uv_spawn is invoked and uvw stays true to the underlying library
return 0;
}
UVW_INLINE int process_handle::spawn(const char *file, char **args, char **env) {
uv_process_options_t po;
po.exit_cb = &exit_callback;
po.file = file;
po.args = args;
po.env = env;
po.cwd = po_cwd.empty() ? nullptr : po_cwd.data();
po.flags = static_cast<uv_process_flags>(po_flags);
po.uid = po_uid;
po.gid = po_gid;
std::vector<uv_stdio_container_t> poStdio;
poStdio.reserve(po_fd_stdio.size() + po_stream_stdio.size());
poStdio.insert(poStdio.begin(), po_fd_stdio.cbegin(), po_fd_stdio.cend());
poStdio.insert(poStdio.end(), po_stream_stdio.cbegin(), po_stream_stdio.cend());
po.stdio_count = static_cast<decltype(po.stdio_count)>(poStdio.size());
po.stdio = poStdio.data();
// see init member function for more details
static_cast<void>(leak_if(0));
return uv_spawn(parent().raw(), raw(), &po);
}
UVW_INLINE int process_handle::kill(int signum) {
return uv_process_kill(raw(), signum);
}
UVW_INLINE int process_handle::pid() noexcept {
return raw()->pid;
}
UVW_INLINE process_handle &process_handle::cwd(const std::string &path) noexcept {
po_cwd = path;
return *this;
}
UVW_INLINE process_handle &process_handle::flags(process_flags flags) noexcept {
po_flags = flags;
return *this;
}
UVW_INLINE process_handle &process_handle::stdio(file_handle fd, stdio_flags flags) {
auto fgs = static_cast<uv_stdio_flags>(flags);
auto actual = uvw::file_handle{fd};
auto it = std::find_if(po_fd_stdio.begin(), po_fd_stdio.end(), [actual](auto &&container) {
return static_cast<const uvw::details::uv_type_wrapper<int>>(container.data.fd) == static_cast<const uvw::details::uv_type_wrapper<int>>(actual);
});
if(it == po_fd_stdio.cend()) {
uv_stdio_container_t container;
container.flags = fgs;
container.data.fd = actual;
po_fd_stdio.push_back(container);
} else {
it->flags = fgs;
it->data.fd = actual;
}
return *this;
}
UVW_INLINE process_handle &process_handle::uid(uid_type id) {
po_uid = id;
return *this;
}
UVW_INLINE process_handle &process_handle::gid(gid_type id) {
po_gid = id;
return *this;
}
} // namespace uvw

View File

@ -18,7 +18,7 @@ namespace uvw {
template<typename T, typename U, typename... E>
class request: public resource<T, U, E...> {
protected:
static auto reserve(U *req) {
[[nodiscard]] static auto reserve(U *req) {
auto ptr = static_cast<T *>(req->data)->shared_from_this();
ptr->self_reset();
return ptr;
@ -47,7 +47,7 @@ public:
* @brief Returns the size of the underlying request type.
* @return The size of the underlying request type.
*/
std::size_t size() const noexcept {
[[nodiscard]] std::size_t size() const noexcept {
return uv_req_size(reinterpret_cast<const uv_req_t *>(this->raw())->type);
}
};

View File

@ -17,7 +17,7 @@ namespace uvw {
template<typename T, typename U, typename... E>
class resource: public uv_type<U>, public emitter<T, E...>, public std::enable_shared_from_this<T> {
protected:
int leak_if(int err) noexcept {
[[nodiscard]] int leak_if(int err) noexcept {
if(err == 0) {
self_ptr = this->shared_from_this();
}
@ -29,7 +29,7 @@ protected:
self_ptr.reset();
}
bool has_self() const noexcept {
[[nodiscard]] bool has_self() const noexcept {
return static_cast<bool>(self_ptr);
}
@ -44,7 +44,7 @@ public:
* @return User-defined data if any, an invalid pointer otherwise.
*/
template<typename R = void>
std::shared_ptr<R> data() const {
[[nodiscard]] std::shared_ptr<R> data() const {
return std::static_pointer_cast<R>(user_data);
}

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB
# include "signal.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE signal_event::signal_event(int sig) noexcept
: signum{sig} {}
UVW_INLINE void signal_handle::start_callback(uv_signal_t *hndl, int signum) {
signal_handle &signal = *(static_cast<signal_handle *>(hndl->data));
signal.publish(signal_event{signum});
}
UVW_INLINE int signal_handle::init() {
return leak_if(uv_signal_init(parent().raw(), raw()));
}
UVW_INLINE int signal_handle::start(int signum) {
return uv_signal_start(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::one_shot(int signum) {
return uv_signal_start_oneshot(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::stop() {
return uv_signal_stop(raw());
}
UVW_INLINE int signal_handle::signal() const noexcept {
return raw()->signum;
}
} // namespace uvw
#include "signal.h"
#include "signal.ipp"

View File

@ -77,7 +77,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "signal.cpp"
# include "signal.ipp"
#endif
#endif // UVW_SIGNAL_INCLUDE_H

33
src/uvw/signal.ipp Normal file
View File

@ -0,0 +1,33 @@
#include "config.h"
namespace uvw {
UVW_INLINE signal_event::signal_event(int sig) noexcept
: signum{sig} {}
UVW_INLINE void signal_handle::start_callback(uv_signal_t *hndl, int signum) {
signal_handle &signal = *(static_cast<signal_handle *>(hndl->data));
signal.publish(signal_event{signum});
}
UVW_INLINE int signal_handle::init() {
return leak_if(uv_signal_init(parent().raw(), raw()));
}
UVW_INLINE int signal_handle::start(int signum) {
return uv_signal_start(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::one_shot(int signum) {
return uv_signal_start_oneshot(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::stop() {
return uv_signal_stop(raw());
}
UVW_INLINE int signal_handle::signal() const noexcept {
return raw()->signum;
}
} // namespace uvw

View File

@ -1,33 +1,2 @@
#ifdef UVW_AS_LIB
# include "stream.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE data_event::data_event(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)},
length{len} {}
UVW_INLINE void details::connect_req::connect_callback(uv_connect_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(connect_event{});
}
}
UVW_INLINE void details::shutdown_req::shoutdown_callback(uv_shutdown_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(shutdown_event{});
}
}
UVW_INLINE int details::shutdown_req::shutdown(uv_stream_t *hndl) {
return this->leak_if(uv_shutdown(raw(), hndl, &shoutdown_callback));
}
} // namespace uvw
#include "stream.h"
#include "stream.ipp"

View File

@ -2,6 +2,7 @@
#define UVW_STREAM_INCLUDE_H
#include <algorithm>
#include <array>
#include <cstddef>
#include <iterator>
#include <memory>
@ -142,11 +143,11 @@ class stream_handle: public handle<T, U, listen_event, end_event, connect_event,
}
}
uv_stream_t *as_uv_stream() {
[[nodiscard]] uv_stream_t *as_uv_stream() {
return reinterpret_cast<uv_stream_t *>(this->raw());
}
const uv_stream_t *as_uv_stream() const {
[[nodiscard]] const uv_stream_t *as_uv_stream() const {
return reinterpret_cast<const uv_stream_t *>(this->raw());
}
@ -377,8 +378,8 @@ public:
* @return Underlying return value.
*/
int try_write(std::unique_ptr<char[]> data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)};
return uv_try_write(as_uv_stream(), bufs, 1);
std::array bufs{uv_buf_init(data.get(), len)};
return uv_try_write(as_uv_stream(), bufs.data(), 1);
}
/**
@ -393,8 +394,8 @@ public:
*/
template<typename V, typename W>
int try_write(std::unique_ptr<char[]> data, unsigned int len, stream_handle<V, W> &send) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)};
return uv_try_write2(as_uv_stream(), bufs, 1, send.raw());
std::array bufs{uv_buf_init(data.get(), len)};
return uv_try_write2(as_uv_stream(), bufs.data(), 1, send.raw());
}
/**
@ -408,8 +409,8 @@ public:
* @return Underlying return value.
*/
int try_write(char *data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data, len)};
return uv_try_write(as_uv_stream(), bufs, 1);
std::array bufs{uv_buf_init(data, len)};
return uv_try_write(as_uv_stream(), bufs.data(), 1);
}
/**
@ -424,15 +425,15 @@ public:
*/
template<typename V, typename W>
int try_write(char *data, unsigned int len, stream_handle<V, W> &send) {
uv_buf_t bufs[] = {uv_buf_init(data, len)};
return uv_try_write2(as_uv_stream(), bufs, 1, send.raw());
std::array bufs{uv_buf_init(data, len)};
return uv_try_write2(as_uv_stream(), bufs.data(), 1, send.raw());
}
/**
* @brief Checks if the stream is readable.
* @return True if the stream is readable, false otherwise.
*/
bool readable() const noexcept {
[[nodiscard]] bool readable() const noexcept {
return (uv_is_readable(as_uv_stream()) == 1);
}
@ -440,7 +441,7 @@ public:
* @brief Checks if the stream is writable.
* @return True if the stream is writable, false otherwise.
*/
bool writable() const noexcept {
[[nodiscard]] bool writable() const noexcept {
return (uv_is_writable(as_uv_stream()) == 1);
}
@ -467,7 +468,7 @@ public:
* @brief Gets the amount of queued bytes waiting to be sent.
* @return Amount of queued bytes waiting to be sent.
*/
size_t write_queue_size() const noexcept {
[[nodiscard]] size_t write_queue_size() const noexcept {
return uv_stream_get_write_queue_size(as_uv_stream());
}
};
@ -475,7 +476,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "stream.cpp"
# include "stream.ipp"
#endif
#endif // UVW_STREAM_INCLUDE_H

29
src/uvw/stream.ipp Normal file
View File

@ -0,0 +1,29 @@
#include "config.h"
namespace uvw {
UVW_INLINE data_event::data_event(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)},
length{len} {}
UVW_INLINE void details::connect_req::connect_callback(uv_connect_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(connect_event{});
}
}
UVW_INLINE void details::shutdown_req::shoutdown_callback(uv_shutdown_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(shutdown_event{});
}
}
UVW_INLINE int details::shutdown_req::shutdown(uv_stream_t *hndl) {
return this->leak_if(uv_shutdown(raw(), hndl, &shoutdown_callback));
}
} // namespace uvw

View File

@ -1,86 +1,2 @@
#ifdef UVW_AS_LIB
# include "tcp.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE tcp_handle::tcp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: stream_handle{token, std::move(ref)}, tag{f ? FLAGS : DEFAULT}, flags{f} {}
UVW_INLINE int tcp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_tcp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_tcp_init(parent().raw(), raw()));
}
}
UVW_INLINE int tcp_handle::open(os_socket_handle socket) {
return uv_tcp_open(raw(), socket);
}
UVW_INLINE bool tcp_handle::no_delay(bool value) {
return (0 == uv_tcp_nodelay(raw(), value));
}
UVW_INLINE bool tcp_handle::keep_alive(bool enable, tcp_handle::time val) {
return (0 == uv_tcp_keepalive(raw(), enable, val.count()));
}
UVW_INLINE bool tcp_handle::simultaneous_accepts(bool enable) {
return (0 == uv_tcp_simultaneous_accepts(raw(), enable));
}
UVW_INLINE int tcp_handle::bind(const sockaddr &addr, tcp_flags opts) {
return uv_tcp_bind(raw(), &addr, static_cast<uv_tcp_flags>(opts));
}
UVW_INLINE int tcp_handle::bind(const std::string &ip, unsigned int port, tcp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int tcp_handle::bind(socket_address addr, tcp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address tcp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE socket_address tcp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int tcp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int tcp_handle::connect(socket_address addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int tcp_handle::connect(const sockaddr &addr) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto req = parent().resource<details::connect_req>();
req->on<error_event>(listener);
req->on<connect_event>(listener);
return req->connect(&uv_tcp_connect, raw(), &addr);
}
UVW_INLINE int tcp_handle::close_reset() {
return uv_tcp_close_reset(raw(), &this->close_callback);
}
} // namespace uvw
#include "tcp.h"
#include "tcp.ipp"

View File

@ -19,7 +19,7 @@ namespace details {
enum class uvw_tcp_flags : std::underlying_type_t<uv_tcp_flags> {
IPV6ONLY = UV_TCP_IPV6ONLY,
_UVW_ENUM = 0
UVW_ENUM = 0
};
}
@ -115,7 +115,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(const sockaddr &addr, tcp_flags opts = tcp_flags::_UVW_ENUM);
int bind(const sockaddr &addr, tcp_flags opts = tcp_flags::UVW_ENUM);
/**
* @brief Binds the handle to an address and port.
@ -133,7 +133,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(const std::string &ip, unsigned int port, tcp_flags opts = tcp_flags::_UVW_ENUM);
int bind(const std::string &ip, unsigned int port, tcp_flags opts = tcp_flags::UVW_ENUM);
/**
* @brief Binds the handle to an address and port.
@ -150,7 +150,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(socket_address addr, tcp_flags opts = tcp_flags::_UVW_ENUM);
int bind(const socket_address &addr, tcp_flags opts = tcp_flags::UVW_ENUM);
/**
* @brief Gets the current address to which the handle is bound.
@ -199,7 +199,7 @@ public:
* @param addr A valid instance of socket_address.
* @return Underlying return value.
*/
int connect(socket_address addr);
int connect(const socket_address &addr);
/**
* @brief Resets a TCP connection by sending a RST packet.
@ -227,7 +227,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "tcp.cpp"
# include "tcp.ipp"
#endif
#endif // UVW_TCP_INCLUDE_H

82
src/uvw/tcp.ipp Normal file
View File

@ -0,0 +1,82 @@
#include "config.h"
namespace uvw {
UVW_INLINE tcp_handle::tcp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: stream_handle{token, std::move(ref)}, tag{f ? FLAGS : DEFAULT}, flags{f} {}
UVW_INLINE int tcp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_tcp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_tcp_init(parent().raw(), raw()));
}
}
UVW_INLINE int tcp_handle::open(os_socket_handle socket) {
return uv_tcp_open(raw(), socket);
}
UVW_INLINE bool tcp_handle::no_delay(bool value) {
return (0 == uv_tcp_nodelay(raw(), value));
}
UVW_INLINE bool tcp_handle::keep_alive(bool enable, tcp_handle::time val) {
return (0 == uv_tcp_keepalive(raw(), enable, val.count()));
}
UVW_INLINE bool tcp_handle::simultaneous_accepts(bool enable) {
return (0 == uv_tcp_simultaneous_accepts(raw(), enable));
}
UVW_INLINE int tcp_handle::bind(const sockaddr &addr, tcp_flags opts) {
return uv_tcp_bind(raw(), &addr, static_cast<uv_tcp_flags>(opts));
}
UVW_INLINE int tcp_handle::bind(const std::string &ip, unsigned int port, tcp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int tcp_handle::bind(const socket_address &addr, tcp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address tcp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE socket_address tcp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int tcp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int tcp_handle::connect(const socket_address &addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int tcp_handle::connect(const sockaddr &addr) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto req = parent().resource<details::connect_req>();
req->on<error_event>(listener);
req->on<connect_event>(listener);
return req->connect(&uv_tcp_connect, raw(), &addr);
}
UVW_INLINE int tcp_handle::close_reset() {
return uv_tcp_close_reset(raw(), &this->close_callback);
}
} // namespace uvw

View File

@ -1,179 +1,2 @@
#ifdef UVW_AS_LIB
# include "thread.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE thread::thread(loop::token token, std::shared_ptr<loop> ref, task t, std::shared_ptr<void> d) noexcept
: uv_type{token, std::move(ref)},
data{std::move(d)},
func{std::move(t)} {}
UVW_INLINE void thread::create_callback(void *arg) {
thread &curr = *(static_cast<thread *>(arg));
curr.func(curr.data);
}
UVW_INLINE thread::type thread::self() noexcept {
return uv_thread_self();
}
UVW_INLINE int thread::getcpu() noexcept {
return uv_thread_getcpu();
}
UVW_INLINE bool thread::equal(const thread &tl, const thread &tr) noexcept {
return !(0 == uv_thread_equal(tl.raw(), tr.raw()));
}
UVW_INLINE thread::~thread() noexcept {
join();
}
UVW_INLINE bool thread::run() noexcept {
return (0 == uv_thread_create(raw(), &create_callback, this));
}
UVW_INLINE bool thread::run(create_flags opts, std::size_t stack) noexcept {
uv_thread_options_t params{static_cast<unsigned int>(opts), stack};
return (0 == uv_thread_create_ex(raw(), &params, &create_callback, this));
}
UVW_INLINE bool thread::join() noexcept {
return (0 == uv_thread_join(raw()));
}
UVW_INLINE thread_local_storage::thread_local_storage(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_key_create(uv_type::raw());
}
UVW_INLINE thread_local_storage::~thread_local_storage() noexcept {
uv_key_delete(uv_type::raw());
}
UVW_INLINE uv_once_t *once::guard() noexcept {
static uv_once_t once = UV_ONCE_INIT;
return &once;
}
UVW_INLINE mutex::mutex(loop::token token, std::shared_ptr<loop> ref, bool recursive) noexcept
: uv_type{token, std::move(ref)} {
if(recursive) {
uv_mutex_init_recursive(raw());
} else {
uv_mutex_init(raw());
}
}
UVW_INLINE mutex::~mutex() noexcept {
uv_mutex_destroy(raw());
}
UVW_INLINE void mutex::lock() noexcept {
uv_mutex_lock(raw());
}
UVW_INLINE bool mutex::try_lock() noexcept {
return (0 == uv_mutex_trylock(raw()));
}
UVW_INLINE void mutex::unlock() noexcept {
uv_mutex_unlock(raw());
}
UVW_INLINE rwlock::rwlock(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_rwlock_init(raw());
}
UVW_INLINE rwlock::~rwlock() noexcept {
uv_rwlock_destroy(raw());
}
UVW_INLINE void rwlock::rdlock() noexcept {
uv_rwlock_rdlock(raw());
}
UVW_INLINE bool rwlock::try_rdlock() noexcept {
return (0 == uv_rwlock_tryrdlock(raw()));
}
UVW_INLINE void rwlock::rdunlock() noexcept {
uv_rwlock_rdunlock(raw());
}
UVW_INLINE void rwlock::wrlock() noexcept {
uv_rwlock_wrlock(raw());
}
UVW_INLINE bool rwlock::try_wrlock() noexcept {
return (0 == uv_rwlock_trywrlock(raw()));
}
UVW_INLINE void rwlock::wrunlock() noexcept {
uv_rwlock_wrunlock(raw());
}
UVW_INLINE semaphore::semaphore(loop::token token, std::shared_ptr<loop> ref, unsigned int value) noexcept
: uv_type{token, std::move(ref)} {
uv_sem_init(raw(), value);
}
UVW_INLINE semaphore::~semaphore() noexcept {
uv_sem_destroy(raw());
}
UVW_INLINE void semaphore::post() noexcept {
uv_sem_post(raw());
}
UVW_INLINE void semaphore::wait() noexcept {
uv_sem_wait(raw());
}
UVW_INLINE bool semaphore::try_wait() noexcept {
return (0 == uv_sem_trywait(raw()));
}
UVW_INLINE condition::condition(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_cond_init(raw());
}
UVW_INLINE condition::~condition() noexcept {
uv_cond_destroy(raw());
}
UVW_INLINE void condition::signal() noexcept {
uv_cond_signal(raw());
}
UVW_INLINE void condition::broadcast() noexcept {
uv_cond_broadcast(raw());
}
UVW_INLINE void condition::wait(mutex &mtx) noexcept {
uv_cond_wait(raw(), mtx.raw());
}
UVW_INLINE bool condition::timed_wait(mutex &mtx, uint64_t timeout) noexcept {
return (0 == uv_cond_timedwait(raw(), mtx.raw(), timeout));
}
UVW_INLINE barrier::barrier(loop::token token, std::shared_ptr<loop> ref, unsigned int count) noexcept
: uv_type{token, std::move(ref)} {
uv_barrier_init(raw(), count);
}
UVW_INLINE barrier::~barrier() noexcept {
uv_barrier_destroy(raw());
}
UVW_INLINE bool barrier::wait() noexcept {
return (0 == uv_barrier_wait(raw()));
}
} // namespace uvw
#include "thread.h"
#include "thread.ipp"

View File

@ -22,7 +22,15 @@ enum class uvw_thread_create_flags : std::underlying_type_t<uv_thread_create_fla
THREAD_HAS_STACK_SIZE = UV_THREAD_HAS_STACK_SIZE
};
}
enum class uvw_thread_priority : int {
THREAD_PRIO_HIGHEST = UV_THREAD_PRIORITY_HIGHEST,
THREAD_PRIO_ABOVE_NORMAL = UV_THREAD_PRIORITY_ABOVE_NORMAL,
THREAD_PRIO_NORMAL = UV_THREAD_PRIORITY_NORMAL,
THREAD_PRIO_BELOW_NORMAL = UV_THREAD_PRIORITY_BELOW_NORMAL,
THREAD_PRIO_LOWEST = UV_THREAD_PRIORITY_LOWEST
};
} // namespace details
class thread;
class thread_local_storage;
@ -49,6 +57,7 @@ class thread final: public uv_type<uv_thread_t> {
public:
using create_flags = details::uvw_thread_create_flags;
using thread_priority = details::uvw_thread_priority;
using task = internal_task;
using type = uv_thread_t;
@ -74,6 +83,23 @@ public:
*/
static bool equal(const thread &tl, const thread &tr) noexcept;
/**
* @brief Sets the scheduling priority of a given thread.
* @param tl A valid instance of a thread.
* @param val Thread priority to set.
* @return True in case of success, false otherwise.
*/
static bool priority(const thread &tl, thread_priority val) noexcept;
/**
* @brief Retrieves the scheduling priority of a given thread.
* @param tl A valid instance of a thread.
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * The scheduled priority for the given thread.
*/
static std::pair<bool, thread_priority> priority(const thread &tl) noexcept;
~thread() noexcept;
/**
@ -157,7 +183,7 @@ public:
/**
* @brief Runs a function once and only once.
*
* The callback must be such that it's convertible to `void(*)(void)`. Free
* The callback must be such that it's convertible to `void(*)()`. Free
* functions and non-capturing lambdas are both viable solutions.
*
* @tparam F Type of the callback.
@ -165,7 +191,7 @@ public:
*/
template<typename F>
static void run(F &&f) noexcept {
using callback_type = void (*)(void);
using callback_type = void (*)();
static_assert(std::is_convertible_v<F, callback_type>);
callback_type cb = f;
uv_once(guard(), cb);
@ -355,7 +381,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "thread.cpp"
# include "thread.ipp"
#endif
#endif // UVW_THREAD_INCLUDE_H

185
src/uvw/thread.ipp Normal file
View File

@ -0,0 +1,185 @@
#include "config.h"
namespace uvw {
UVW_INLINE thread::thread(loop::token token, std::shared_ptr<loop> ref, task t, std::shared_ptr<void> d) noexcept
: uv_type{token, std::move(ref)},
data{std::move(d)},
func{std::move(t)} {}
UVW_INLINE void thread::create_callback(void *arg) {
thread &curr = *(static_cast<thread *>(arg));
curr.func(curr.data);
}
UVW_INLINE thread::type thread::self() noexcept {
return uv_thread_self();
}
UVW_INLINE int thread::getcpu() noexcept {
return uv_thread_getcpu();
}
UVW_INLINE bool thread::equal(const thread &tl, const thread &tr) noexcept {
return !(0 == uv_thread_equal(tl.raw(), tr.raw()));
}
UVW_INLINE bool thread::priority(const thread &tl, thread_priority val) noexcept {
return (uv_thread_setpriority(*tl.raw(), static_cast<std::underlying_type_t<thread_priority>>(val)) == 0);
}
UVW_INLINE std::pair<bool, thread::thread_priority> thread::priority(const thread &tl) noexcept {
int prio{};
const bool res = (uv_thread_getpriority(*tl.raw(), &prio) == 0);
return {res, thread_priority{static_cast<std::underlying_type_t<thread_priority>>(prio)}};
}
UVW_INLINE thread::~thread() noexcept {
join();
}
UVW_INLINE bool thread::run() noexcept {
return (0 == uv_thread_create(raw(), &create_callback, this));
}
UVW_INLINE bool thread::run(create_flags opts, std::size_t stack) noexcept {
uv_thread_options_t params{static_cast<unsigned int>(opts), stack};
return (0 == uv_thread_create_ex(raw(), &params, &create_callback, this));
}
UVW_INLINE bool thread::join() noexcept {
return (0 == uv_thread_join(raw()));
}
UVW_INLINE thread_local_storage::thread_local_storage(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_key_create(uv_type::raw());
}
UVW_INLINE thread_local_storage::~thread_local_storage() noexcept {
uv_key_delete(uv_type::raw());
}
UVW_INLINE uv_once_t *once::guard() noexcept {
static uv_once_t once = UV_ONCE_INIT;
return &once;
}
UVW_INLINE mutex::mutex(loop::token token, std::shared_ptr<loop> ref, bool recursive) noexcept
: uv_type{token, std::move(ref)} {
if(recursive) {
uv_mutex_init_recursive(raw());
} else {
uv_mutex_init(raw());
}
}
UVW_INLINE mutex::~mutex() noexcept {
uv_mutex_destroy(raw());
}
UVW_INLINE void mutex::lock() noexcept {
uv_mutex_lock(raw());
}
UVW_INLINE bool mutex::try_lock() noexcept {
return (0 == uv_mutex_trylock(raw()));
}
UVW_INLINE void mutex::unlock() noexcept {
uv_mutex_unlock(raw());
}
UVW_INLINE rwlock::rwlock(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_rwlock_init(raw());
}
UVW_INLINE rwlock::~rwlock() noexcept {
uv_rwlock_destroy(raw());
}
UVW_INLINE void rwlock::rdlock() noexcept {
uv_rwlock_rdlock(raw());
}
UVW_INLINE bool rwlock::try_rdlock() noexcept {
return (0 == uv_rwlock_tryrdlock(raw()));
}
UVW_INLINE void rwlock::rdunlock() noexcept {
uv_rwlock_rdunlock(raw());
}
UVW_INLINE void rwlock::wrlock() noexcept {
uv_rwlock_wrlock(raw());
}
UVW_INLINE bool rwlock::try_wrlock() noexcept {
return (0 == uv_rwlock_trywrlock(raw()));
}
UVW_INLINE void rwlock::wrunlock() noexcept {
uv_rwlock_wrunlock(raw());
}
UVW_INLINE semaphore::semaphore(loop::token token, std::shared_ptr<loop> ref, unsigned int value) noexcept
: uv_type{token, std::move(ref)} {
uv_sem_init(raw(), value);
}
UVW_INLINE semaphore::~semaphore() noexcept {
uv_sem_destroy(raw());
}
UVW_INLINE void semaphore::post() noexcept {
uv_sem_post(raw());
}
UVW_INLINE void semaphore::wait() noexcept {
uv_sem_wait(raw());
}
UVW_INLINE bool semaphore::try_wait() noexcept {
return (0 == uv_sem_trywait(raw()));
}
UVW_INLINE condition::condition(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_cond_init(raw());
}
UVW_INLINE condition::~condition() noexcept {
uv_cond_destroy(raw());
}
UVW_INLINE void condition::signal() noexcept {
uv_cond_signal(raw());
}
UVW_INLINE void condition::broadcast() noexcept {
uv_cond_broadcast(raw());
}
UVW_INLINE void condition::wait(mutex &mtx) noexcept {
uv_cond_wait(raw(), mtx.raw());
}
UVW_INLINE bool condition::timed_wait(mutex &mtx, uint64_t timeout) noexcept {
return (0 == uv_cond_timedwait(raw(), mtx.raw(), timeout));
}
UVW_INLINE barrier::barrier(loop::token token, std::shared_ptr<loop> ref, unsigned int count) noexcept
: uv_type{token, std::move(ref)} {
uv_barrier_init(raw(), count);
}
UVW_INLINE barrier::~barrier() noexcept {
uv_barrier_destroy(raw());
}
UVW_INLINE bool barrier::wait() noexcept {
return (0 == uv_barrier_wait(raw()));
}
} // namespace uvw

View File

@ -1,42 +1,2 @@
#ifdef UVW_AS_LIB
# include "timer.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void timer_handle::start_callback(uv_timer_t *hndl) {
timer_handle &timer = *(static_cast<timer_handle *>(hndl->data));
timer.publish(timer_event{});
}
UVW_INLINE int timer_handle::init() {
return leak_if(uv_timer_init(parent().raw(), raw()));
}
UVW_INLINE int timer_handle::start(timer_handle::time timeout, timer_handle::time repeat) {
return uv_timer_start(raw(), &start_callback, timeout.count(), repeat.count());
}
UVW_INLINE int timer_handle::stop() {
return uv_timer_stop(raw());
}
UVW_INLINE int timer_handle::again() {
return uv_timer_again(raw());
}
UVW_INLINE void timer_handle::repeat(timer_handle::time repeat) {
uv_timer_set_repeat(raw(), repeat.count());
}
UVW_INLINE timer_handle::time timer_handle::repeat() {
return time{uv_timer_get_repeat(raw())};
}
UVW_INLINE timer_handle::time timer_handle::due_in() {
return time{uv_timer_get_due_in(raw())};
}
} // namespace uvw
#include "timer.h"
#include "timer.ipp"

View File

@ -1,8 +1,8 @@
#ifndef UVW_TIMER_INCLUDE_H
#define UVW_TIMER_INCLUDE_H
#include <cstdint>
#include <chrono>
#include <cstdint>
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
@ -105,7 +105,7 @@ public:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "timer.cpp"
# include "timer.ipp"
#endif
#endif // UVW_TIMER_INCLUDE_H

38
src/uvw/timer.ipp Normal file
View File

@ -0,0 +1,38 @@
#include "config.h"
namespace uvw {
UVW_INLINE void timer_handle::start_callback(uv_timer_t *hndl) {
timer_handle &timer = *(static_cast<timer_handle *>(hndl->data));
timer.publish(timer_event{});
}
UVW_INLINE int timer_handle::init() {
return leak_if(uv_timer_init(parent().raw(), raw()));
}
UVW_INLINE int timer_handle::start(timer_handle::time timeout, timer_handle::time repeat) {
return uv_timer_start(raw(), &start_callback, timeout.count(), repeat.count());
}
UVW_INLINE int timer_handle::stop() {
return uv_timer_stop(raw());
}
UVW_INLINE int timer_handle::again() {
return uv_timer_again(raw());
}
UVW_INLINE void timer_handle::repeat(timer_handle::time repeat) {
uv_timer_set_repeat(raw(), repeat.count());
}
UVW_INLINE timer_handle::time timer_handle::repeat() {
return time{uv_timer_get_repeat(raw())};
}
UVW_INLINE timer_handle::time timer_handle::due_in() {
return time{uv_timer_get_due_in(raw())};
}
} // namespace uvw

View File

@ -1,67 +1,2 @@
#ifdef UVW_AS_LIB
# include "tty.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE details::reset_mode_memo::~reset_mode_memo() {
uv_tty_reset_mode();
}
UVW_INLINE tty_handle::tty_handle(loop::token token, std::shared_ptr<loop> ref, file_handle desc, bool readable)
: stream_handle{token, std::move(ref)},
memo{mode_memo_handler()},
fd{desc},
rw{readable} {}
UVW_INLINE std::shared_ptr<details::reset_mode_memo> tty_handle::mode_memo_handler() {
static std::weak_ptr<details::reset_mode_memo> weak;
auto shared = weak.lock();
if(!shared) { weak = shared = std::make_shared<details::reset_mode_memo>(); }
return shared;
}
UVW_INLINE int tty_handle::init() {
return leak_if(uv_tty_init(parent().raw(), raw(), fd, rw));
}
UVW_INLINE bool tty_handle::mode(tty_handle::tty_mode m) {
return (0 == uv_tty_set_mode(raw(), static_cast<uv_tty_mode_t>(m)));
}
UVW_INLINE bool tty_handle::reset_mode() noexcept {
return (0 == uv_tty_reset_mode());
}
UVW_INLINE win_size tty_handle::get_win_size() {
win_size size;
if(0 != uv_tty_get_winsize(raw(), &size.width, &size.height)) {
size.width = -1;
size.height = -1;
}
return size;
}
UVW_INLINE void tty_handle::vterm_state(tty_handle::tty_vtermstate s) const noexcept {
switch(s) {
case tty_vtermstate::SUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_SUPPORTED);
break;
case tty_vtermstate::UNSUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_UNSUPPORTED);
break;
}
}
UVW_INLINE tty_handle::tty_vtermstate tty_handle::vterm_state() const noexcept {
uv_tty_vtermstate_t state;
uv_tty_get_vterm_state(&state);
return tty_vtermstate{state};
}
} // namespace uvw
#include "tty.h"
#include "tty.ipp"

View File

@ -140,7 +140,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "tty.cpp"
# include "tty.ipp"
#endif
#endif // UVW_TTY_INCLUDE_H

65
src/uvw/tty.ipp Normal file
View File

@ -0,0 +1,65 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE details::reset_mode_memo::~reset_mode_memo() {
uv_tty_reset_mode();
}
UVW_INLINE tty_handle::tty_handle(loop::token token, std::shared_ptr<loop> ref, file_handle desc, bool readable)
: stream_handle{token, std::move(ref)},
memo{mode_memo_handler()},
fd{desc},
rw{readable} {}
UVW_INLINE std::shared_ptr<details::reset_mode_memo> tty_handle::mode_memo_handler() {
static std::weak_ptr<details::reset_mode_memo> weak;
auto shared = weak.lock();
if(!shared) {
weak = shared = std::make_shared<details::reset_mode_memo>();
}
return shared;
}
UVW_INLINE int tty_handle::init() {
return leak_if(uv_tty_init(parent().raw(), raw(), fd, rw));
}
UVW_INLINE bool tty_handle::mode(tty_handle::tty_mode m) {
return (0 == uv_tty_set_mode(raw(), static_cast<uv_tty_mode_t>(m)));
}
UVW_INLINE bool tty_handle::reset_mode() noexcept {
return (0 == uv_tty_reset_mode());
}
UVW_INLINE win_size tty_handle::get_win_size() {
win_size size;
if(0 != uv_tty_get_winsize(raw(), &size.width, &size.height)) {
size.width = -1;
size.height = -1;
}
return size;
}
UVW_INLINE void tty_handle::vterm_state(tty_handle::tty_vtermstate s) const noexcept {
switch(s) {
case tty_vtermstate::SUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_SUPPORTED);
break;
case tty_vtermstate::UNSUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_UNSUPPORTED);
break;
}
}
UVW_INLINE tty_handle::tty_vtermstate tty_handle::vterm_state() const noexcept {
uv_tty_vtermstate_t state;
uv_tty_get_vterm_state(&state);
return tty_vtermstate{state};
}
} // namespace uvw

View File

@ -2,6 +2,7 @@
#define UVW_TYPE_INFO_INCLUDE_HPP
#include <cstdint>
#include <string_view>
#include "config.h"
namespace uvw {
@ -14,14 +15,13 @@ namespace uvw {
namespace internal {
// Fowler-Noll-Vo hash function v. 1a - the good
[[nodiscard]] static constexpr std::uint32_t fnv1a(const char *curr) noexcept {
[[nodiscard]] static constexpr std::uint32_t fnv1a(const std::string_view view) noexcept {
constexpr std::uint32_t offset = 2166136261;
constexpr std::uint32_t prime = 16777619;
auto value = offset;
while(*curr != 0) {
auto curr_val_int = static_cast<std::uint32_t>(*(curr++));
value = (value ^ curr_val_int) * prime;
for(auto &&curr: view) {
value = (value ^ static_cast<std::uint32_t>(static_cast<unsigned char>(curr))) * prime;
}
return value;

View File

@ -1,216 +1,2 @@
#ifdef UVW_AS_LIB
# include "udp.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE udp_data_event::udp_data_event(socket_address sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept
: data{std::move(buf)},
length{len},
sender{std::move(sndr)},
partial{part} {}
UVW_INLINE void details::send_req::udp_send_callback(uv_udp_send_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(send_event{});
}
}
UVW_INLINE details::send_req::send_req(loop::token token, std::shared_ptr<loop> parent, std::unique_ptr<char[], deleter> dt, unsigned int len)
: request{token, std::move(parent)},
data{std::move(dt)},
buf{uv_buf_init(data.get(), len)} {}
UVW_INLINE int details::send_req::send(uv_udp_t *hndl, const struct sockaddr *addr) {
return this->leak_if(uv_udp_send(raw(), hndl, &buf, 1, addr, &udp_send_callback));
}
UVW_INLINE void udp_handle::recv_callback(uv_udp_t *hndl, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
udp_handle &udp = *(static_cast<udp_handle *>(hndl->data));
// data will be destroyed no matter of what the value of nread is
std::unique_ptr<char[]> data{buf->base};
if(nread > 0) {
// data available (can be truncated)
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
} else if(nread == 0 && addr == nullptr) {
// no more data to be read, doing nothing is fine
} else if(nread == 0 && addr != nullptr) {
// empty udp packet
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), false});
} else {
// transmission error
udp.publish(error_event(nread));
}
}
UVW_INLINE udp_handle::udp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: handle{token, std::move(ref)}, tag{FLAGS}, flags{f} {}
UVW_INLINE int udp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_udp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_udp_init(parent().raw(), raw()));
}
}
UVW_INLINE int udp_handle::open(os_socket_handle socket) {
return uv_udp_open(raw(), socket);
}
UVW_INLINE int udp_handle::connect(const sockaddr &addr) {
return uv_udp_connect(raw(), &addr);
}
UVW_INLINE int udp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int udp_handle::connect(socket_address addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int udp_handle::disconnect() {
return uv_udp_connect(raw(), nullptr);
}
UVW_INLINE socket_address udp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int udp_handle::bind(const sockaddr &addr, udp_handle::udp_flags opts) {
return uv_udp_bind(raw(), &addr, static_cast<uv_udp_flags>(opts));
}
UVW_INLINE int udp_handle::bind(const std::string &ip, unsigned int port, udp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int udp_handle::bind(socket_address addr, udp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address udp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE bool udp_handle::multicast_membership(const std::string &multicast, const std::string &iface, membership ms) {
return (0 == uv_udp_set_membership(raw(), multicast.data(), iface.data(), static_cast<uv_membership>(ms)));
}
UVW_INLINE bool udp_handle::multicast_loop(bool enable) {
return (0 == uv_udp_set_multicast_loop(raw(), enable));
}
UVW_INLINE bool udp_handle::multicast_ttl(int val) {
return (0 == uv_udp_set_multicast_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE bool udp_handle::multicast_interface(const std::string &iface) {
return (0 == uv_udp_set_multicast_interface(raw(), iface.data()));
}
UVW_INLINE bool udp_handle::broadcast(bool enable) {
return (0 == uv_udp_set_broadcast(raw(), enable));
}
UVW_INLINE bool udp_handle::ttl(int val) {
return (0 == uv_udp_set_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data.release(), [](char *ptr) { delete[] ptr; }}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len) {
return send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, char *data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data, [](char *) {}}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::send(socket_address addr, char *data, unsigned int len) {
return send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)};
return uv_udp_try_send(raw(), bufs, 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, char *data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data, len)};
return uv_udp_try_send(raw(), bufs, 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::try_send(socket_address addr, char *data, unsigned int len) {
return try_send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::recv() {
return uv_udp_recv_start(raw(), &details::common_alloc_callback, &recv_callback);
}
UVW_INLINE int udp_handle::stop() {
return uv_udp_recv_stop(raw());
}
UVW_INLINE size_t udp_handle::send_queue_size() const noexcept {
return uv_udp_get_send_queue_size(raw());
}
UVW_INLINE size_t udp_handle::send_queue_count() const noexcept {
return uv_udp_get_send_queue_count(raw());
}
} // namespace uvw
#include "udp.h"
#include "udp.ipp"

View File

@ -38,7 +38,7 @@ enum class uvw_udp_flags : std::underlying_type_t<uv_udp_flags> {
UDP_MMSG_FREE = UV_UDP_MMSG_FREE,
UDP_LINUX_RECVERR = UV_UDP_LINUX_RECVERR,
UDP_RECVMMSG = UV_UDP_RECVMMSG,
_UVW_ENUM = 0
UVW_ENUM = 0
};
enum class uvw_membership : std::underlying_type_t<uv_membership> {
@ -154,7 +154,7 @@ public:
* @param addr A valid instance of socket_address.
* @return Underlying return value.
*/
int connect(socket_address addr);
int connect(const socket_address &addr);
/**
* @brief Disconnects the handle.
@ -193,7 +193,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(const sockaddr &addr, udp_flags opts = udp_flags::_UVW_ENUM);
int bind(const sockaddr &addr, udp_flags opts = udp_flags::UVW_ENUM);
/**
* @brief Binds the UDP handle to an IP address and port.
@ -217,7 +217,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(const std::string &ip, unsigned int port, udp_flags opts = udp_flags::_UVW_ENUM);
int bind(const std::string &ip, unsigned int port, udp_flags opts = udp_flags::UVW_ENUM);
/**
* @brief Binds the UDP handle to an IP address and port.
@ -240,7 +240,7 @@ public:
* @param opts Optional additional flags.
* @return Underlying return value.
*/
int bind(socket_address addr, udp_flags opts = udp_flags::_UVW_ENUM);
int bind(const socket_address &addr, udp_flags opts = udp_flags::UVW_ENUM);
/**
* @brief Get the local IP and port of the UDP handle.
@ -358,7 +358,7 @@ public:
* @param len The lenght of the submitted data.
* @return Underlying return value.
*/
int send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len);
int send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len);
/**
* @brief Sends data over the UDP socket.
@ -416,7 +416,7 @@ public:
* @param len The lenght of the submitted data.
* @return Underlying return value.
*/
int send(socket_address addr, char *data, unsigned int len);
int send(const socket_address &addr, char *data, unsigned int len);
/**
* @brief Sends data over the UDP socket.
@ -456,7 +456,7 @@ public:
* @param len The lenght of the submitted data.
* @return Underlying return value.
*/
int try_send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len);
int try_send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len);
/**
* @brief Sends data over the UDP socket.
@ -496,7 +496,7 @@ public:
* @param len The lenght of the submitted data.
* @return Underlying return value.
*/
int try_send(socket_address addr, char *data, unsigned int len);
int try_send(const socket_address &addr, char *data, unsigned int len);
/**
* @brief Prepares for receiving data.
@ -556,7 +556,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "udp.cpp"
# include "udp.ipp"
#endif
#endif // UVW_UDP_INCLUDE_H

213
src/uvw/udp.ipp Normal file
View File

@ -0,0 +1,213 @@
#include <array>
#include "config.h"
namespace uvw {
UVW_INLINE udp_data_event::udp_data_event(socket_address sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept
: data{std::move(buf)},
length{len},
sender{std::move(sndr)},
partial{part} {}
UVW_INLINE void details::send_req::udp_send_callback(uv_udp_send_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(send_event{});
}
}
UVW_INLINE details::send_req::send_req(loop::token token, std::shared_ptr<loop> parent, std::unique_ptr<char[], deleter> dt, unsigned int len)
: request{token, std::move(parent)},
data{std::move(dt)},
buf{uv_buf_init(data.get(), len)} {}
UVW_INLINE int details::send_req::send(uv_udp_t *hndl, const struct sockaddr *addr) {
return this->leak_if(uv_udp_send(raw(), hndl, &buf, 1, addr, &udp_send_callback));
}
UVW_INLINE void udp_handle::recv_callback(uv_udp_t *hndl, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
udp_handle &udp = *(static_cast<udp_handle *>(hndl->data));
// data will be destroyed no matter of what the value of nread is
std::unique_ptr<char[]> data{buf->base};
if(nread > 0) {
// data available (can be truncated)
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
} else if(nread == 0 && addr == nullptr) {
// no more data to be read, doing nothing is fine
} else if(nread == 0 && addr != nullptr) {
// empty udp packet
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), false});
} else {
// transmission error
udp.publish(error_event(nread));
}
}
UVW_INLINE udp_handle::udp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: handle{token, std::move(ref)}, tag{FLAGS}, flags{f} {}
UVW_INLINE int udp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_udp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_udp_init(parent().raw(), raw()));
}
}
UVW_INLINE int udp_handle::open(os_socket_handle socket) {
return uv_udp_open(raw(), socket);
}
UVW_INLINE int udp_handle::connect(const sockaddr &addr) {
return uv_udp_connect(raw(), &addr);
}
UVW_INLINE int udp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int udp_handle::connect(const socket_address &addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int udp_handle::disconnect() {
return uv_udp_connect(raw(), nullptr);
}
UVW_INLINE socket_address udp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int udp_handle::bind(const sockaddr &addr, udp_handle::udp_flags opts) {
return uv_udp_bind(raw(), &addr, static_cast<uv_udp_flags>(opts));
}
UVW_INLINE int udp_handle::bind(const std::string &ip, unsigned int port, udp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int udp_handle::bind(const socket_address &addr, udp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address udp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE bool udp_handle::multicast_membership(const std::string &multicast, const std::string &iface, membership ms) {
return (0 == uv_udp_set_membership(raw(), multicast.data(), iface.data(), static_cast<uv_membership>(ms)));
}
UVW_INLINE bool udp_handle::multicast_loop(bool enable) {
return (0 == uv_udp_set_multicast_loop(raw(), enable));
}
UVW_INLINE bool udp_handle::multicast_ttl(int val) {
return (0 == uv_udp_set_multicast_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE bool udp_handle::multicast_interface(const std::string &iface) {
return (0 == uv_udp_set_multicast_interface(raw(), iface.data()));
}
UVW_INLINE bool udp_handle::broadcast(bool enable) {
return (0 == uv_udp_set_broadcast(raw(), enable));
}
UVW_INLINE bool udp_handle::ttl(int val) {
return (0 == uv_udp_set_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data.release(), [](char *ptr) { delete[] ptr; }}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len) {
return send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, char *data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data, [](char *) {}}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::send(const socket_address &addr, char *data, unsigned int len) {
return send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
std::array bufs{uv_buf_init(data.get(), len)};
return uv_udp_try_send(raw(), bufs.data(), 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, char *data, unsigned int len) {
std::array bufs{uv_buf_init(data, len)};
return uv_udp_try_send(raw(), bufs.data(), 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::try_send(const socket_address &addr, char *data, unsigned int len) {
return try_send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::recv() {
return uv_udp_recv_start(raw(), &details::common_alloc_callback, &recv_callback);
}
UVW_INLINE int udp_handle::stop() {
return uv_udp_recv_stop(raw());
}
UVW_INLINE size_t udp_handle::send_queue_size() const noexcept {
return uv_udp_get_send_queue_size(raw());
}
UVW_INLINE size_t udp_handle::send_queue_count() const noexcept {
return uv_udp_get_send_queue_count(raw());
}
} // namespace uvw

View File

@ -1,368 +1,2 @@
#ifdef UVW_AS_LIB
# include "util.h"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE passwd_info::passwd_info(std::shared_ptr<uv_passwd_t> pwd)
: value{pwd} {}
UVW_INLINE std::string passwd_info::username() const noexcept {
return ((value && value->username) ? value->username : "");
}
UVW_INLINE decltype(uv_passwd_t::uid) passwd_info::uid() const noexcept {
return (value ? value->uid : decltype(uv_passwd_t::uid){});
}
UVW_INLINE decltype(uv_passwd_t::gid) passwd_info::gid() const noexcept {
return (value ? value->gid : decltype(uv_passwd_t::gid){});
}
UVW_INLINE std::string passwd_info::shell() const noexcept {
return ((value && value->shell) ? value->shell : "");
}
UVW_INLINE std::string passwd_info::homedir() const noexcept {
return ((value && value->homedir) ? value->homedir : "");
}
UVW_INLINE passwd_info::operator bool() const noexcept {
return static_cast<bool>(value);
}
UVW_INLINE uts_name::uts_name(std::shared_ptr<uv_utsname_t> init)
: uname{init} {}
UVW_INLINE std::string uts_name::sysname() const noexcept {
return uname ? uname->sysname : "";
}
UVW_INLINE std::string uts_name::release() const noexcept {
return uname ? uname->release : "";
}
UVW_INLINE std::string uts_name::version() const noexcept {
return uname ? uname->version : "";
}
UVW_INLINE std::string uts_name::machine() const noexcept {
return uname ? uname->machine : "";
}
namespace details {
UVW_INLINE void common_alloc_callback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
auto size = static_cast<unsigned int>(suggested);
*buf = uv_buf_init(new char[size], size);
}
UVW_INLINE sockaddr ip_addr(const char *addr, unsigned int port) {
// explicitly cast to avoid `-Wsign-conversion` warnings
// libuv internally just casts to an `unsigned short` anyway
auto signed_port = static_cast<int>(port);
if(sockaddr_in addr_in; uv_ip4_addr(addr, signed_port, &addr_in) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in);
} else if(sockaddr_in6 addr_in6; uv_ip6_addr(addr, signed_port, &addr_in6) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in6);
}
return {};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in &addr) {
if(char name[details::DEFAULT_SIZE]; uv_ip4_name(&addr, name, details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name}, ntohs(addr.sin_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in6 &addr) {
if(char name[details::DEFAULT_SIZE]; uv_ip6_name(&addr, name, details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name}, ntohs(addr.sin6_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr &addr) {
if(addr.sa_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(addr));
} else if(addr.sa_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(addr));
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_storage &storage) {
if(storage.ss_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(storage));
} else if(storage.ss_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(storage));
}
return socket_address{};
}
} // namespace details
UVW_INLINE pid_type utilities::os::pid() noexcept {
return uv_os_getpid();
}
UVW_INLINE pid_type utilities::os::ppid() noexcept {
return uv_os_getppid();
}
UVW_INLINE std::string utilities::os::homedir() noexcept {
return details::try_read(&uv_os_homedir);
}
UVW_INLINE std::string utilities::os::tmpdir() noexcept {
return details::try_read(&uv_os_tmpdir);
}
UVW_INLINE std::string utilities::os::env(const std::string &name) noexcept {
return details::try_read(&uv_os_getenv, name.c_str());
}
UVW_INLINE bool utilities::os::env(const std::string &name, const std::string &value) noexcept {
return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
}
UVW_INLINE std::string utilities::os::hostname() noexcept {
return details::try_read(&uv_os_gethostname);
}
UVW_INLINE uts_name utilities::os::uname() noexcept {
auto ptr = std::make_shared<uv_utsname_t>();
uv_os_uname(ptr.get());
return ptr;
}
UVW_INLINE passwd_info utilities::os::passwd() noexcept {
auto deleter = [](uv_passwd_t *passwd) {
uv_os_free_passwd(passwd);
delete passwd;
};
std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
uv_os_get_passwd(ptr.get());
return ptr;
}
UVW_INLINE int utilities::os::priority(pid_type pid) {
int prio = 0;
if(uv_os_getpriority(pid, &prio)) {
prio = UV_PRIORITY_LOW + 1;
}
return prio;
}
UVW_INLINE bool utilities::os::priority(pid_type pid, int prio) {
return 0 == uv_os_setpriority(pid, prio);
}
UVW_INLINE handle_type utilities::guess_handle(handle_category category) noexcept {
switch(category) {
case UV_ASYNC:
return handle_type::ASYNC;
case UV_CHECK:
return handle_type::CHECK;
case UV_FS_EVENT:
return handle_type::FS_EVENT;
case UV_FS_POLL:
return handle_type::FS_POLL;
case UV_HANDLE:
return handle_type::HANDLE;
case UV_IDLE:
return handle_type::IDLE;
case UV_NAMED_PIPE:
return handle_type::PIPE;
case UV_POLL:
return handle_type::POLL;
case UV_PREPARE:
return handle_type::PREPARE;
case UV_PROCESS:
return handle_type::PROCESS;
case UV_STREAM:
return handle_type::STREAM;
case UV_TCP:
return handle_type::TCP;
case UV_TIMER:
return handle_type::TIMER;
case UV_TTY:
return handle_type::TTY;
case UV_UDP:
return handle_type::UDP;
case UV_SIGNAL:
return handle_type::SIGNAL;
case UV_FILE:
return handle_type::FILE;
default:
return handle_type::UNKNOWN;
}
}
UVW_INLINE handle_type utilities::guess_handle(file_handle file) noexcept {
handle_category category = uv_guess_handle(file);
return guess_handle(category);
}
UVW_INLINE std::vector<cpu_info> utilities::cpu() noexcept {
std::vector<cpu_info> cpuinfos;
uv_cpu_info_t *infos;
int count;
if(0 == uv_cpu_info(&infos, &count)) {
for(int next = 0; next < count; ++next) {
cpuinfos.push_back({infos[next].model, infos[next].speed, infos[next].cpu_times});
}
uv_free_cpu_info(infos, count);
}
return cpuinfos;
}
UVW_INLINE std::vector<interface_address> utilities::interface_addresses() noexcept {
std::vector<interface_address> interfaces;
uv_interface_address_t *ifaces{nullptr};
int count{0};
if(0 == uv_interface_addresses(&ifaces, &count)) {
for(int next = 0; next < count; ++next) {
interface_address iface_addr;
iface_addr.name = ifaces[next].name;
std::copy(ifaces[next].phys_addr, (ifaces[next].phys_addr + 6), iface_addr.physical);
iface_addr.internal = ifaces[next].is_internal == 0 ? false : true;
if(ifaces[next].address.address4.sin_family == AF_INET) {
iface_addr.address = details::sock_addr(ifaces[next].address.address4);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask4);
} else if(ifaces[next].address.address4.sin_family == AF_INET6) {
iface_addr.address = details::sock_addr(ifaces[next].address.address6);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask6);
}
interfaces.push_back(std::move(iface_addr));
}
uv_free_interface_addresses(ifaces, count);
}
return interfaces;
}
UVW_INLINE std::string utilities::index_to_name(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoname, index);
}
UVW_INLINE std::string utilities::index_to_iid(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoiid, index);
}
UVW_INLINE bool utilities::replace_allocator(malloc_func_type malloc_func, realloc_func_type realloc_func, calloc_func_type calloc_func, free_func_type free_func) noexcept {
return (0 == uv_replace_allocator(malloc_func, realloc_func, calloc_func, free_func));
}
UVW_INLINE std::array<double, 3> utilities::load_average() noexcept {
std::array<double, 3> avg;
uv_loadavg(avg.data());
return avg;
}
UVW_INLINE char **utilities::setup_args(int argc, char **argv) {
return uv_setup_args(argc, argv);
}
UVW_INLINE std::string utilities::process_title() {
std::size_t size = details::DEFAULT_SIZE;
char buf[details::DEFAULT_SIZE];
std::string str{};
if(0 == uv_get_process_title(buf, size)) {
str.assign(buf, size);
}
return str;
}
UVW_INLINE bool utilities::process_title(const std::string &title) {
return (0 == uv_set_process_title(title.c_str()));
}
UVW_INLINE uint64_t utilities::total_memory() noexcept {
return uv_get_total_memory();
}
UVW_INLINE uint64_t utilities::constrained_memory() noexcept {
return uv_get_constrained_memory();
}
UVW_INLINE uint64_t utilities::available_memory() noexcept {
return uv_get_available_memory();
}
UVW_INLINE double utilities::uptime() noexcept {
double ret;
if(0 != uv_uptime(&ret)) {
ret = 0;
}
return ret;
}
UVW_INLINE resource_usage utilities::rusage() noexcept {
resource_usage ru;
auto err = uv_getrusage(&ru);
return err ? resource_usage{} : ru;
}
UVW_INLINE timespec64 utilities::gettime(clock_id source) noexcept {
timespec64 ts;
auto err = uv_clock_gettime(static_cast<uv_clock_id>(source), &ts);
return err ? timespec64{} : ts;
}
UVW_INLINE uint64_t utilities::hrtime() noexcept {
return uv_hrtime();
}
UVW_INLINE std::string utilities::path() noexcept {
return details::try_read(&uv_exepath);
}
UVW_INLINE std::string utilities::cwd() noexcept {
return details::try_read(&uv_cwd);
}
UVW_INLINE bool utilities::chdir(const std::string &dir) noexcept {
return (0 == uv_chdir(dir.data()));
}
UVW_INLINE timeval64 utilities::time_of_day() noexcept {
uv_timeval64_t ret;
uv_gettimeofday(&ret);
return ret;
}
UVW_INLINE void utilities::sleep(unsigned int msec) noexcept {
uv_sleep(msec);
}
UVW_INLINE unsigned int utilities::available_parallelism() noexcept {
return uv_available_parallelism();
}
} // namespace uvw
#include "util.h"
#include "util.ipp"

View File

@ -118,31 +118,31 @@ struct passwd_info {
* @brief Gets the username.
* @return The username of the current effective uid (not the real uid).
*/
std::string username() const noexcept;
[[nodiscard]] std::string username() const noexcept;
/**
* @brief Gets the uid.
* @return The current effective uid (not the real uid).
*/
decltype(uv_passwd_t::uid) uid() const noexcept;
[[nodiscard]] decltype(uv_passwd_t::uid) uid() const noexcept;
/**
* @brief Gets the gid.
* @return The gid of the current effective uid (not the real uid).
*/
decltype(uv_passwd_t::gid) gid() const noexcept;
[[nodiscard]] decltype(uv_passwd_t::gid) gid() const noexcept;
/**
* @brief Gets the shell.
* @return The shell of the current effective uid (not the real uid).
*/
std::string shell() const noexcept;
[[nodiscard]] std::string shell() const noexcept;
/**
* @brief Gets the homedir.
* @return The homedir of the current effective uid (not the real uid).
*/
std::string homedir() const noexcept;
[[nodiscard]] std::string homedir() const noexcept;
/**
* @brief Checks if the instance contains valid data.
@ -170,25 +170,25 @@ struct uts_name {
* @brief Gets the operating system name (like "Linux").
* @return The operating system name.
*/
std::string sysname() const noexcept;
[[nodiscard]] std::string sysname() const noexcept;
/**
* @brief Gets the operating system release (like "2.6.28").
* @return The operating system release.
*/
std::string release() const noexcept;
[[nodiscard]] std::string release() const noexcept;
/**
* @brief Gets the operating system version.
* @return The operating system version
*/
std::string version() const noexcept;
[[nodiscard]] std::string version() const noexcept;
/**
* @brief Gets the hardware identifier.
* @return The hardware identifier.
*/
std::string machine() const noexcept;
[[nodiscard]] std::string machine() const noexcept;
private:
std::shared_ptr<uv_utsname_t> uname;
@ -238,11 +238,11 @@ struct cpu_info {
* \brief Interface address.
*/
struct interface_address {
std::string name; /*!< The name of the interface (as an example _eth0_). */
char physical[6]; /*!< The physical address. */
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
socket_address address; /*!< The address of the given interface. */
socket_address netmask; /*!< The netmask of the given interface. */
std::string name; /*!< The name of the interface (as an example _eth0_). */
std::array<char, 6u> physical; /*!< The physical address. */
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
socket_address address; /*!< The address of the given interface. */
socket_address netmask; /*!< The netmask of the given interface. */
};
namespace details {
@ -250,21 +250,21 @@ namespace details {
static constexpr std::size_t DEFAULT_SIZE = 128;
template<typename F, typename... Args>
std::string try_read(F &&f, Args &&...args) noexcept {
[[nodiscard]] std::string try_read(F &&f, Args &&...args) {
std::size_t size = DEFAULT_SIZE;
char buf[DEFAULT_SIZE];
std::array<char, DEFAULT_SIZE> buf{};
std::string str{};
auto err = std::forward<F>(f)(args..., buf, &size);
auto err = std::forward<F>(f)(args..., buf.data(), &size);
if(UV_ENOBUFS == err) {
std::unique_ptr<char[]> data{new char[size]};
auto data = std::make_unique<char[]>(size);
err = std::forward<F>(f)(args..., data.get(), &size);
if(0 == err) {
str = data.get();
}
} else if(0 == err) {
str.assign(buf, size);
str.assign(buf.data(), size);
}
return str;
@ -310,7 +310,7 @@ struct utilities {
*
* @return The current process id.
*/
static pid_type pid() noexcept;
[[nodiscard]] static pid_type pid() noexcept;
/**
* @brief Returns the parent process id.
@ -321,7 +321,7 @@ struct utilities {
*
* @return The parent process id.
*/
static pid_type ppid() noexcept;
[[nodiscard]] static pid_type ppid() noexcept;
/**
* @brief Gets the current user's home directory.
@ -333,7 +333,7 @@ struct utilities {
* @return The current user's home directory, an empty string in case of
* errors.
*/
static std::string homedir() noexcept;
[[nodiscard]] static std::string homedir() noexcept;
/**
* @brief Gets the temp directory.
@ -344,7 +344,7 @@ struct utilities {
*
* @return The temp directory, an empty string in case of errors.
*/
static std::string tmpdir() noexcept;
[[nodiscard]] static std::string tmpdir() noexcept;
/**
* @brief Retrieves an environment variable.
@ -352,7 +352,7 @@ struct utilities {
* @return The value of the environment variable, an empty string in
* case of errors.
*/
static std::string env(const std::string &name) noexcept;
[[nodiscard]] static std::string env(const std::string &name) noexcept;
/**
* @brief Creates, updates or deletes an environment variable.
@ -377,7 +377,7 @@ struct utilities {
* @return True in case of success, false otherwise.
*/
template<typename Func>
static std::enable_if_t<std::is_invocable_v<Func, std::string_view, std::string_view>, bool>
[[nodiscard]] static std::enable_if_t<std::is_invocable_v<Func, std::string_view, std::string_view>, bool>
env(Func func) noexcept {
uv_env_item_t *items = nullptr;
int count{};
@ -399,7 +399,7 @@ struct utilities {
* @brief Returns the hostname.
* @return The hostname, an empty string in case of errors.
*/
static std::string hostname() noexcept;
[[nodiscard]] static std::string hostname() noexcept;
/**
* @brief Gets name and information about the current kernel.
@ -410,7 +410,7 @@ struct utilities {
*
* @return Name and information about the current kernel.
*/
static uts_name uname() noexcept;
[[nodiscard]] static uts_name uname() noexcept;
/**
* @brief Gets a subset of the password file entry.
@ -424,7 +424,7 @@ struct utilities {
*
* @return The accessible subset of the password file entry.
*/
static passwd_info passwd() noexcept;
[[nodiscard]] static passwd_info passwd();
/**
* @brief Retrieves the scheduling priority of a process.
@ -464,7 +464,7 @@ struct utilities {
* @param category A properly initialized handle category.
* @return The actual type of the handle as defined by handle_type
*/
static handle_type guess_handle(handle_category category) noexcept;
[[nodiscard]] static handle_type guess_handle(handle_category category) noexcept;
/**
* @brief Gets the type of the stream to be used with the given descriptor.
@ -484,7 +484,7 @@ struct utilities {
* * `handle_type::UDP`
* * `handle_type::FILE`
*/
static handle_type guess_handle(file_handle file) noexcept;
[[nodiscard]] static handle_type guess_handle(file_handle file) noexcept;
/** @brief Gets information about the CPUs on the system.
*
@ -493,7 +493,7 @@ struct utilities {
*
* @return A set of descriptors of all the available CPUs.
*/
static std::vector<cpu_info> cpu() noexcept;
[[nodiscard]] static std::vector<cpu_info> cpu() noexcept;
/**
* @brief Gets a set of descriptors of all the available interfaces.
@ -503,7 +503,7 @@ struct utilities {
*
* @return A set of descriptors of all the available interfaces.
*/
static std::vector<interface_address> interface_addresses() noexcept;
[[nodiscard]] static std::vector<interface_address> interface_addresses() noexcept;
/**
* @brief IPv6-capable implementation of
@ -518,7 +518,7 @@ struct utilities {
* @param index Network interface index.
* @return Network interface name.
*/
static std::string index_to_name(unsigned int index) noexcept;
[[nodiscard]] static std::string index_to_name(unsigned int index) noexcept;
/**
* @brief Retrieves a network interface identifier.
@ -530,7 +530,7 @@ struct utilities {
* @param index Network interface index.
* @return Network interface identifier.
*/
static std::string index_to_iid(unsigned int index) noexcept;
[[nodiscard]] static std::string index_to_iid(unsigned int index) noexcept;
/**
* @brief Override the use of some standard librarys functions.
@ -561,7 +561,7 @@ struct utilities {
* @brief Gets the load average.
* @return `[0,0,0]` on Windows (not available), the load average otherwise.
*/
static std::array<double, 3> load_average() noexcept;
[[nodiscard]] static std::array<double, 3> load_average() noexcept;
/**
* @brief Store the program arguments.
@ -576,7 +576,7 @@ struct utilities {
* @brief Gets the title of the current process.
* @return The process title.
*/
static std::string process_title();
[[nodiscard]] static std::string process_title();
/**
* @brief Sets the current process title.
@ -589,7 +589,7 @@ struct utilities {
* @brief Gets memory information (in bytes).
* @return Memory information.
*/
static uint64_t total_memory() noexcept;
[[nodiscard]] static uint64_t total_memory() noexcept;
/**
* @brief Gets the amount of memory available to the process (in bytes).
@ -602,32 +602,39 @@ struct utilities {
*
* @return Amount of memory available to the process.
*/
static uint64_t constrained_memory() noexcept;
[[nodiscard]] static uint64_t constrained_memory() noexcept;
/**
* @brief Gets the amount of free memory still available to the process.
* @return Amount of free memory still available to the process (in bytes).
*/
static uint64_t available_memory() noexcept;
[[nodiscard]] static uint64_t available_memory() noexcept;
/**
* @brief Gets the resident set size (RSS) for the current process.
* @return The resident set size (RSS) for the current process or a negative
* value in case of errors.
*/
[[nodiscard]] static int64_t resident_set_memory() noexcept;
/**
* @brief Gets the current system uptime.
* @return The current system uptime or 0 in case of errors.
*/
static double uptime() noexcept;
[[nodiscard]] static double uptime() noexcept;
/**
* @brief Gets the resource usage measures for the current process.
* @return Resource usage measures, zeroes-filled object in case of errors.
*/
static resource_usage rusage() noexcept;
[[nodiscard]] static resource_usage rusage() noexcept;
/**
* @brief Gets the current system time from a high-resolution clock source.
* @param source Clock source, either real-time or monotonic.
* @return Current system time from the given high-resolution clock source.
*/
static timespec64 gettime(clock_id source) noexcept;
[[nodiscard]] static timespec64 gettime(clock_id source) noexcept;
/**
* @brief Gets the current high-resolution real time.
@ -639,7 +646,7 @@ struct utilities {
*
* @return The current high-resolution real time.
*/
static uint64_t hrtime() noexcept;
[[nodiscard]] static uint64_t hrtime() noexcept;
/**
* @brief Gets the executable path.
@ -651,7 +658,7 @@ struct utilities {
* @brief Gets the current working directory.
* @return The current working directory, an empty string in case of errors.
*/
static std::string cwd() noexcept;
[[nodiscard]] static std::string cwd() noexcept;
/**
* @brief Changes the current working directory.
@ -665,7 +672,7 @@ struct utilities {
* [`gettimeofday`](https://linux.die.net/man/2/gettimeofday)
* @return The current time.
*/
static timeval64 time_of_day() noexcept;
[[nodiscard]] static timeval64 time_of_day() noexcept;
/**
* @brief Causes the calling thread to sleep for a while.
@ -678,7 +685,7 @@ struct utilities {
* use (always a non-zero value).
* @return Estimate of the amount of parallelism a program should use.
*/
static unsigned int available_parallelism() noexcept;
[[nodiscard]] static unsigned int available_parallelism() noexcept;
};
/**
@ -700,7 +707,7 @@ overloaded(Func...) -> overloaded<Func...>;
} // namespace uvw
#ifndef UVW_AS_LIB
# include "util.cpp"
# include "util.ipp"
#endif
#endif // UVW_UTIL_INCLUDE_H

369
src/uvw/util.ipp Normal file
View File

@ -0,0 +1,369 @@
#include "config.h"
namespace uvw {
UVW_INLINE passwd_info::passwd_info(std::shared_ptr<uv_passwd_t> pwd)
: value{std::move(pwd)} {}
UVW_INLINE std::string passwd_info::username() const noexcept {
return ((value && value->username) ? value->username : "");
}
UVW_INLINE decltype(uv_passwd_t::uid) passwd_info::uid() const noexcept {
return (value ? value->uid : decltype(uv_passwd_t::uid){});
}
UVW_INLINE decltype(uv_passwd_t::gid) passwd_info::gid() const noexcept {
return (value ? value->gid : decltype(uv_passwd_t::gid){});
}
UVW_INLINE std::string passwd_info::shell() const noexcept {
return ((value && value->shell) ? value->shell : "");
}
UVW_INLINE std::string passwd_info::homedir() const noexcept {
return ((value && value->homedir) ? value->homedir : "");
}
UVW_INLINE passwd_info::operator bool() const noexcept {
return static_cast<bool>(value);
}
UVW_INLINE uts_name::uts_name(std::shared_ptr<uv_utsname_t> init)
: uname{std::move(init)} {}
UVW_INLINE std::string uts_name::sysname() const noexcept {
return uname ? uname->sysname : "";
}
UVW_INLINE std::string uts_name::release() const noexcept {
return uname ? uname->release : "";
}
UVW_INLINE std::string uts_name::version() const noexcept {
return uname ? uname->version : "";
}
UVW_INLINE std::string uts_name::machine() const noexcept {
return uname ? uname->machine : "";
}
namespace details {
UVW_INLINE void common_alloc_callback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
auto size = static_cast<unsigned int>(suggested);
*buf = uv_buf_init(new char[size], size);
}
UVW_INLINE sockaddr ip_addr(const char *addr, unsigned int port) {
// explicitly cast to avoid `-Wsign-conversion` warnings
// libuv internally just casts to an `unsigned short` anyway
auto signed_port = static_cast<int>(port);
if(sockaddr_in addr_in; uv_ip4_addr(addr, signed_port, &addr_in) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in);
} else if(sockaddr_in6 addr_in6; uv_ip6_addr(addr, signed_port, &addr_in6) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in6);
}
return {};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in &addr) {
if(std::array<char, details::DEFAULT_SIZE> name{}; uv_ip4_name(&addr, name.data(), details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name.data()}, ntohs(addr.sin_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in6 &addr) {
if(std::array<char, details::DEFAULT_SIZE> name{}; uv_ip6_name(&addr, name.data(), details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name.data()}, ntohs(addr.sin6_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr &addr) {
if(addr.sa_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(addr));
} else if(addr.sa_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(addr));
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_storage &storage) {
if(storage.ss_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(storage));
} else if(storage.ss_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(storage));
}
return socket_address{};
}
} // namespace details
UVW_INLINE pid_type utilities::os::pid() noexcept {
return uv_os_getpid();
}
UVW_INLINE pid_type utilities::os::ppid() noexcept {
return uv_os_getppid();
}
UVW_INLINE std::string utilities::os::homedir() noexcept {
return details::try_read(&uv_os_homedir);
}
UVW_INLINE std::string utilities::os::tmpdir() noexcept {
return details::try_read(&uv_os_tmpdir);
}
UVW_INLINE std::string utilities::os::env(const std::string &name) noexcept {
return details::try_read(&uv_os_getenv, name.c_str());
}
UVW_INLINE bool utilities::os::env(const std::string &name, const std::string &value) noexcept {
return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
}
UVW_INLINE std::string utilities::os::hostname() noexcept {
return details::try_read(&uv_os_gethostname);
}
UVW_INLINE uts_name utilities::os::uname() noexcept {
auto ptr = std::make_shared<uv_utsname_t>();
uv_os_uname(ptr.get());
return ptr;
}
UVW_INLINE passwd_info utilities::os::passwd() {
auto deleter = [](uv_passwd_t *passwd) {
uv_os_free_passwd(passwd);
delete passwd;
};
std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
uv_os_get_passwd(ptr.get());
return ptr;
}
UVW_INLINE int utilities::os::priority(pid_type pid) {
int prio = 0;
if(uv_os_getpriority(pid, &prio)) {
prio = UV_PRIORITY_LOW + 1;
}
return prio;
}
UVW_INLINE bool utilities::os::priority(pid_type pid, int prio) {
return 0 == uv_os_setpriority(pid, prio);
}
UVW_INLINE handle_type utilities::guess_handle(handle_category category) noexcept {
switch(category) {
case UV_ASYNC:
return handle_type::ASYNC;
case UV_CHECK:
return handle_type::CHECK;
case UV_FS_EVENT:
return handle_type::FS_EVENT;
case UV_FS_POLL:
return handle_type::FS_POLL;
case UV_HANDLE:
return handle_type::HANDLE;
case UV_IDLE:
return handle_type::IDLE;
case UV_NAMED_PIPE:
return handle_type::PIPE;
case UV_POLL:
return handle_type::POLL;
case UV_PREPARE:
return handle_type::PREPARE;
case UV_PROCESS:
return handle_type::PROCESS;
case UV_STREAM:
return handle_type::STREAM;
case UV_TCP:
return handle_type::TCP;
case UV_TIMER:
return handle_type::TIMER;
case UV_TTY:
return handle_type::TTY;
case UV_UDP:
return handle_type::UDP;
case UV_SIGNAL:
return handle_type::SIGNAL;
case UV_FILE:
return handle_type::FILE;
default:
return handle_type::UNKNOWN;
}
}
UVW_INLINE handle_type utilities::guess_handle(file_handle file) noexcept {
handle_category category = uv_guess_handle(file);
return guess_handle(category);
}
UVW_INLINE std::vector<cpu_info> utilities::cpu() noexcept {
std::vector<cpu_info> cpuinfos;
uv_cpu_info_t *infos;
int count;
if(0 == uv_cpu_info(&infos, &count)) {
for(int next = 0; next < count; ++next) {
cpuinfos.push_back({infos[next].model, infos[next].speed, infos[next].cpu_times});
}
uv_free_cpu_info(infos, count);
}
return cpuinfos;
}
UVW_INLINE std::vector<interface_address> utilities::interface_addresses() noexcept {
std::vector<interface_address> interfaces;
uv_interface_address_t *ifaces{nullptr};
int count{0};
if(0 == uv_interface_addresses(&ifaces, &count)) {
for(int next = 0; next < count; ++next) {
interface_address iface_addr;
iface_addr.name = ifaces[next].name;
std::copy(ifaces[next].phys_addr, (ifaces[next].phys_addr + 6), iface_addr.physical.data());
iface_addr.internal = ifaces[next].is_internal == 0 ? false : true;
if(ifaces[next].address.address4.sin_family == AF_INET) {
iface_addr.address = details::sock_addr(ifaces[next].address.address4);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask4);
} else if(ifaces[next].address.address4.sin_family == AF_INET6) {
iface_addr.address = details::sock_addr(ifaces[next].address.address6);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask6);
}
interfaces.push_back(std::move(iface_addr));
}
uv_free_interface_addresses(ifaces, count);
}
return interfaces;
}
UVW_INLINE std::string utilities::index_to_name(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoname, index);
}
UVW_INLINE std::string utilities::index_to_iid(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoiid, index);
}
UVW_INLINE bool utilities::replace_allocator(malloc_func_type malloc_func, realloc_func_type realloc_func, calloc_func_type calloc_func, free_func_type free_func) noexcept {
return (0 == uv_replace_allocator(malloc_func, realloc_func, calloc_func, free_func));
}
UVW_INLINE std::array<double, 3> utilities::load_average() noexcept {
std::array<double, 3> avg;
uv_loadavg(avg.data());
return avg;
}
UVW_INLINE char **utilities::setup_args(int argc, char **argv) {
return uv_setup_args(argc, argv);
}
UVW_INLINE std::string utilities::process_title() {
std::array<char, details::DEFAULT_SIZE> buf{};
std::string str{};
if(0 == uv_get_process_title(buf.data(), details::DEFAULT_SIZE)) {
str.assign(buf.data(), details::DEFAULT_SIZE);
}
return str;
}
UVW_INLINE bool utilities::process_title(const std::string &title) {
return (0 == uv_set_process_title(title.c_str()));
}
UVW_INLINE uint64_t utilities::total_memory() noexcept {
return uv_get_total_memory();
}
UVW_INLINE uint64_t utilities::constrained_memory() noexcept {
return uv_get_constrained_memory();
}
UVW_INLINE uint64_t utilities::available_memory() noexcept {
return uv_get_available_memory();
}
UVW_INLINE int64_t utilities::resident_set_memory() noexcept {
size_t res{};
const auto err = uv_resident_set_memory(&res);
return (err == 0) ? static_cast<int64_t>(res) : static_cast<int64_t>(err);
}
UVW_INLINE double utilities::uptime() noexcept {
double ret;
if(0 != uv_uptime(&ret)) {
ret = 0;
}
return ret;
}
UVW_INLINE resource_usage utilities::rusage() noexcept {
resource_usage ru;
auto err = uv_getrusage(&ru);
return err ? resource_usage{} : ru;
}
UVW_INLINE timespec64 utilities::gettime(clock_id source) noexcept {
timespec64 ts;
auto err = uv_clock_gettime(static_cast<uv_clock_id>(source), &ts);
return err ? timespec64{} : ts;
}
UVW_INLINE uint64_t utilities::hrtime() noexcept {
return uv_hrtime();
}
UVW_INLINE std::string utilities::path() noexcept {
return details::try_read(&uv_exepath);
}
UVW_INLINE std::string utilities::cwd() noexcept {
return details::try_read(&uv_cwd);
}
UVW_INLINE bool utilities::chdir(const std::string &dir) noexcept {
return (0 == uv_chdir(dir.data()));
}
UVW_INLINE timeval64 utilities::time_of_day() noexcept {
uv_timeval64_t ret;
uv_gettimeofday(&ret);
return ret;
}
UVW_INLINE void utilities::sleep(unsigned int msec) noexcept {
uv_sleep(msec);
}
UVW_INLINE unsigned int utilities::available_parallelism() noexcept {
return uv_available_parallelism();
}
} // namespace uvw

View File

@ -17,7 +17,7 @@ namespace uvw {
template<typename U>
struct uv_type {
explicit uv_type(loop::token, std::shared_ptr<loop> ref) noexcept
: owner{std::move(ref)}, resource{} {}
: owner{std::move(ref)} {}
uv_type(const uv_type &) = delete;
uv_type(uv_type &&) = delete;
@ -29,7 +29,7 @@ struct uv_type {
* @brief Gets the loop from which the resource was originated.
* @return A reference to a loop instance.
*/
loop &parent() const noexcept {
[[nodiscard]] loop &parent() const noexcept {
return *owner;
}
@ -48,7 +48,7 @@ struct uv_type {
*
* @return The underlying raw data structure.
*/
const U *raw() const noexcept {
[[nodiscard]] const U *raw() const noexcept {
return &resource;
}
@ -67,7 +67,7 @@ struct uv_type {
*
* @return The underlying raw data structure.
*/
U *raw() noexcept {
[[nodiscard]] U *raw() noexcept {
return &resource;
}
@ -76,7 +76,7 @@ protected:
private:
std::shared_ptr<loop> owner;
U resource;
U resource{};
};
} // namespace uvw

View File

@ -1,30 +1,2 @@
#ifdef UVW_AS_LIB
# include "work.h"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE work_req::work_req(loop::token token, std::shared_ptr<loop> ref, task t)
: request{token, std::move(ref)}, func{t} {}
UVW_INLINE void work_req::work_callback(uv_work_t *req) {
static_cast<work_req *>(req->data)->func();
}
UVW_INLINE void work_req::after_work_callback(uv_work_t* req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(work_event{});
}
}
UVW_INLINE int work_req::queue() {
return this->leak_if(uv_queue_work(parent().raw(), raw(), &work_callback, &after_work_callback));
}
} // namespace uvw
#include "work.h"
#include "work.ipp"

View File

@ -20,7 +20,7 @@ struct work_event {};
*
* To create a `work_req` through a `loop`, arguments follow:
*
* * A valid instance of a `Task`, that is of type `std::function<void(void)>`.
* * A valid instance of a `Task`, that is of type `std::function<void()>`.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/threadpool.html)
@ -31,7 +31,7 @@ class work_req final: public request<work_req, uv_work_t, work_event> {
static void after_work_callback(uv_work_t *req, int status);
public:
using task = std::function<void(void)>;
using task = std::function<void()>;
explicit work_req(loop::token token, std::shared_ptr<loop> ref, task t);
@ -53,7 +53,7 @@ private:
} // namespace uvw
#ifndef UVW_AS_LIB
# include "work.cpp"
# include "work.ipp"
#endif
#endif // UVW_WORK_INCLUDE_H

25
src/uvw/work.ipp Normal file
View File

@ -0,0 +1,25 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE work_req::work_req(loop::token token, std::shared_ptr<loop> ref, task t)
: request{token, std::move(ref)}, func{std::move(t)} {}
UVW_INLINE void work_req::work_callback(uv_work_t *req) {
static_cast<work_req *>(req->data)->func();
}
UVW_INLINE void work_req::after_work_callback(uv_work_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(work_event{});
}
}
UVW_INLINE int work_req::queue() {
return this->leak_if(uv_queue_work(parent().raw(), raw(), &work_callback, &after_work_callback));
}
} // namespace uvw

View File

@ -1,13 +1,13 @@
[wrap-file]
directory = libuv-v1.46.0
source_url = https://dist.libuv.org/dist/v1.46.0/libuv-v1.46.0.tar.gz
source_filename = libuv-v1.46.0.tar.gz
source_hash = 111f83958b9fdc65f1489195d25f342b9f7a3e683140c60e62c00fbaccddddce
patch_filename = libuv_1.46.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.46.0-1/get_patch
patch_hash = 41b1834129f13efcb4a94a137335eb85fe0662509010c157617954d2feb20ac8
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.46.0-1/libuv-v1.46.0.tar.gz
wrapdb_version = 1.46.0-1
directory = libuv-v1.48.0
source_url = https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
source_filename = libuv-v1.48.0.tar.gz
source_hash = 7f1db8ac368d89d1baf163bac1ea5fe5120697a73910c8ae6b2fffb3551d59fb
patch_filename = libuv_1.48.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.48.0-1/get_patch
patch_hash = 27b18917c914a5d6dfb459073710e9bfb6b2962d69d4e0bad5bc7b1173482be7
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.48.0-1/libuv-v1.48.0.tar.gz
wrapdb_version = 1.48.0-1
[provide]
libuv = libuv_dep

View File

@ -7,7 +7,7 @@ include(FetchContent)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(FIND_GTEST_PACKAGE)
if(UVW_FIND_GTEST_PACKAGE)
find_package(GTest REQUIRED)
else()
FetchContent_Declare(
@ -19,18 +19,22 @@ else()
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_library(GTest::Main ALIAS gtest_main)
target_compile_features(gtest PUBLIC cxx_std_17)
set_target_properties(gtest PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gtest_main PUBLIC cxx_std_17)
set_target_properties(gtest_main PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gmock PUBLIC cxx_std_17)
set_target_properties(gmock PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gmock_main PUBLIC cxx_std_17)
set_target_properties(gmock_main PROPERTIES CXX_CLANG_TIDY "")
if(CMAKE_SYSTEM_NAME MATCHES OpenBSD)
target_compile_options(gtest PRIVATE -Wno-error)
@ -41,7 +45,7 @@ if(WIN32)
set(WINSOCK2 ws2_32)
endif()
function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
function(UVW_ADD_TEST TEST_NAME TEST_SOURCE)
add_executable(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(
@ -69,16 +73,16 @@ function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
add_test(NAME uvw_${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}>)
endfunction()
function(ADD_UVW_DIR_TEST TEST_NAME TEST_SOURCE)
ADD_UVW_TEST(${TEST_NAME} ${TEST_SOURCE})
function(UVW_ADD_DIR_TEST TEST_NAME TEST_SOURCE)
UVW_ADD_TEST(${TEST_NAME} ${TEST_SOURCE})
string(TOUPPER "${TEST_NAME}" TEST_NAME_UPPER)
set(TEST_DIR_VAR "TARGET_${TEST_NAME_UPPER}_DIR")
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}_data)
target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_DIR_VAR}="${TEST_NAME}_data")
endfunction()
function(ADD_UVW_LIB_TEST TEST_NAME TEST_SOURCE)
ADD_UVW_TEST(${TEST_NAME} ${TEST_SOURCE})
function(UVW_ADD_LIB_TEST TEST_NAME TEST_SOURCE)
UVW_ADD_TEST(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(${TEST_NAME} PRIVATE ${CMAKE_DL_LIBS})
target_compile_definitions(${TEST_NAME} PRIVATE TARGET_LIB_SO="$<TARGET_FILE:fake>")
endfunction()
@ -87,39 +91,39 @@ add_library(fake SHARED fake.cpp)
# List of available targets
option(BUILD_DNS_TEST "Build DNS test." OFF)
option(UVW_BUILD_DNS_TEST "Build DNS test." OFF)
ADD_UVW_TEST(main main.cpp)
ADD_UVW_TEST(async uvw/async.cpp)
ADD_UVW_TEST(check uvw/check.cpp)
ADD_UVW_TEST(emitter uvw/emitter.cpp)
ADD_UVW_DIR_TEST(file_req uvw/file_req.cpp)
ADD_UVW_DIR_TEST(fs_event uvw/fs_event.cpp)
ADD_UVW_DIR_TEST(fs_req uvw/fs_req.cpp)
ADD_UVW_TEST(handle uvw/handle.cpp)
ADD_UVW_TEST(idle uvw/idle.cpp)
ADD_UVW_LIB_TEST(lib uvw/lib.cpp)
ADD_UVW_TEST(loop uvw/loop.cpp)
ADD_UVW_DIR_TEST(pipe uvw/pipe.cpp)
ADD_UVW_TEST(prepare uvw/prepare.cpp)
ADD_UVW_TEST(process uvw/process.cpp)
ADD_UVW_TEST(request uvw/request.cpp)
ADD_UVW_TEST(resource uvw/resource.cpp)
ADD_UVW_TEST(signal uvw/signal.cpp)
ADD_UVW_TEST(stream uvw/stream.cpp)
ADD_UVW_TEST(tcp uvw/tcp.cpp)
ADD_UVW_TEST(thread uvw/thread.cpp)
ADD_UVW_TEST(timer uvw/timer.cpp)
ADD_UVW_TEST(tty uvw/tty.cpp)
ADD_UVW_TEST(udp uvw/udp.cpp)
ADD_UVW_TEST(uv_type uvw/uv_type.cpp)
ADD_UVW_TEST(util uvw/util.cpp)
ADD_UVW_TEST(work uvw/work.cpp)
UVW_ADD_TEST(main main.cpp)
UVW_ADD_TEST(async uvw/async.cpp)
UVW_ADD_TEST(check uvw/check.cpp)
UVW_ADD_TEST(emitter uvw/emitter.cpp)
UVW_ADD_DIR_TEST(file_req uvw/file_req.cpp)
UVW_ADD_DIR_TEST(fs_event uvw/fs_event.cpp)
UVW_ADD_DIR_TEST(fs_req uvw/fs_req.cpp)
UVW_ADD_TEST(handle uvw/handle.cpp)
UVW_ADD_TEST(idle uvw/idle.cpp)
UVW_ADD_LIB_TEST(lib uvw/lib.cpp)
UVW_ADD_TEST(loop uvw/loop.cpp)
UVW_ADD_DIR_TEST(pipe uvw/pipe.cpp)
UVW_ADD_TEST(prepare uvw/prepare.cpp)
UVW_ADD_TEST(process uvw/process.cpp)
UVW_ADD_TEST(request uvw/request.cpp)
UVW_ADD_TEST(resource uvw/resource.cpp)
UVW_ADD_TEST(signal uvw/signal.cpp)
UVW_ADD_TEST(stream uvw/stream.cpp)
UVW_ADD_TEST(tcp uvw/tcp.cpp)
UVW_ADD_TEST(thread uvw/thread.cpp)
UVW_ADD_TEST(timer uvw/timer.cpp)
UVW_ADD_TEST(tty uvw/tty.cpp)
UVW_ADD_TEST(udp uvw/udp.cpp)
UVW_ADD_TEST(uv_type uvw/uv_type.cpp)
UVW_ADD_TEST(util uvw/util.cpp)
UVW_ADD_TEST(work uvw/work.cpp)
if(NOT CMAKE_SYSTEM_NAME MATCHES OpenBSD)
ADD_UVW_DIR_TEST(file_req_sendfile uvw/file_req_sendfile.cpp)
UVW_ADD_DIR_TEST(file_req_sendfile uvw/file_req_sendfile.cpp)
endif()
if(BUILD_DNS_TEST)
ADD_UVW_TEST(dns uvw/dns.cpp)
if(UVW_BUILD_DNS_TEST)
UVW_ADD_TEST(dns uvw/dns.cpp)
endif()

View File

@ -1,5 +1,3 @@
#include <stdio.h>
extern "C" int fake_func(double *);
int fake_func(double *d) {

View File

@ -1,7 +1,7 @@
#include <cassert>
#include <chrono>
#include <iostream>
#include <memory>
#include <utility>
#include <uvw.hpp>
void listen(uvw::loop &loop) {

View File

@ -1,4 +1,3 @@
#include <chrono>
#include <gtest/gtest.h>
#include <uvw/fs.h>

View File

@ -43,7 +43,7 @@ TEST(Handle, Functionalities) {
ASSERT_LT(handle->recv_buffer_size(), 0);
ASSERT_NE(0, handle->recv_buffer_size(0));
ASSERT_NO_THROW(handle->fd());
ASSERT_NO_THROW([[maybe_unused]] const auto fd = handle->fd());
}
TEST(Handle, InitializationFailure) {

View File

@ -1,5 +1,4 @@
#include <gtest/gtest.h>
#include <uvw/check.h>
#include <uvw/signal.h>
TEST(Signal, Start) {

View File

@ -4,7 +4,7 @@
TEST(Thread, Run) {
auto loop = uvw::loop::get_default();
auto has_run = std::make_shared<bool>();
auto cb = [](std::shared_ptr<void> data) {
auto cb = [](const std::shared_ptr<void> &data) {
if(auto has_run_ptr = std::static_pointer_cast<bool>(data); has_run_ptr) {
*has_run_ptr = true;
}

View File

@ -27,8 +27,8 @@ TEST(Util, Utilities) {
ASSERT_TRUE(static_cast<bool>(passwd));
ASSERT_FALSE(passwd.username().empty());
ASSERT_FALSE(passwd.homedir().empty());
ASSERT_NO_THROW(passwd.uid());
ASSERT_NO_THROW(passwd.gid());
ASSERT_NO_THROW([[maybe_unused]] const auto uid = passwd.uid());
ASSERT_NO_THROW([[maybe_unused]] const auto gid = passwd.gid());
#ifndef _MSC_VER
// libuv returns a null string for the shell on Windows
@ -72,21 +72,22 @@ TEST(Util, Utilities) {
ASSERT_FALSE(interfaceAddresses[0].address.ip.empty());
ASSERT_FALSE(interfaceAddresses[0].netmask.ip.empty());
ASSERT_NO_THROW(uvw::utilities::index_to_name(0));
ASSERT_NO_THROW(uvw::utilities::index_to_iid(0));
ASSERT_NO_THROW([[maybe_unused]] const auto name = uvw::utilities::index_to_name(0));
ASSERT_NO_THROW([[maybe_unused]] const auto iid = uvw::utilities::index_to_iid(0));
ASSERT_TRUE(uvw::utilities::replace_allocator(
[](size_t size) { return malloc(size); },
[](void *ptr, size_t size) { return realloc(ptr, size); },
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
[](size_t num, size_t size) { return calloc(num, size); },
[](void *ptr) { return free(ptr); }));
ASSERT_NO_THROW(uvw::utilities::load_average());
ASSERT_NO_THROW([[maybe_unused]] const auto load_average = uvw::utilities::load_average());
ASSERT_NE(uvw::utilities::total_memory(), decltype(uvw::utilities::total_memory()){0});
ASSERT_NE(uvw::utilities::available_memory(), decltype(uvw::utilities::available_memory()){0});
ASSERT_NE(uvw::utilities::uptime(), decltype(uvw::utilities::uptime()){0});
ASSERT_NO_THROW(uvw::utilities::rusage());
ASSERT_NO_THROW(uvw::utilities::gettime(uvw::clock_id::MONOTONIC));
ASSERT_NO_THROW([[maybe_unused]] const auto rusage = uvw::utilities::rusage());
ASSERT_NO_THROW([[maybe_unused]] const auto time = uvw::utilities::gettime(uvw::clock_id::MONOTONIC));
ASSERT_NE(uvw::utilities::hrtime(), decltype(uvw::utilities::hrtime()){0});
ASSERT_FALSE(uvw::utilities::path().empty());
ASSERT_FALSE(uvw::utilities::cwd().empty());

Some files were not shown because too many files have changed in this diff Show More