diff --git a/.github/workflows/gen_docs.yml b/.github/workflows/gen_docs.yml index f3368b4..bab0fc8 100644 --- a/.github/workflows/gen_docs.yml +++ b/.github/workflows/gen_docs.yml @@ -18,7 +18,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - name: run-doxygen - uses: mattnotmitt/doxygen-action@v1.9.8 + uses: mattnotmitt/doxygen-action@v1.12.0 with: working-directory: doc - name: deploy-pages diff --git a/CMakeLists.txt b/CMakeLists.txt index 37012af..9316c1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2024 by Cliff Green +# Copyright (c) 2024-2025 by Cliff Green # # https://github.com/connectivecpp/shared-buffer # diff --git a/README.md b/README.md index 9a1bbad..ceb17dc 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The `shared_buffer` classes are reference counted `std::byte` buffer classes useful for asynchronous networking. In particular, the Asio asynchronous networking library requires a buffer to be kept alive and valid until the outstanding IO operation (e.g. a network write) is completed. A straightforward and idiomatic way to achieve this is by using reference counted buffers. -There are two classes - `const_shared_buffer` for outgoing buffers (which should not be modified), and `mutable_shared_buffer` for incoming buffers (mutable and expandable as data arrives). There are efficient (move) operations for creating a `const_shared_buffer` from a `mutable_shared_buffer`, which allows the use case of creating a message and serializing its contents, then sending it out over the network. +There are two classes - `const_shared_buffer` for outgoing buffers (which should not be modified), and `mutable_shared_buffer` for incoming buffers (mutable and expandable as data arrives). In addition there are efficient (move) operations for creating a `const_shared_buffer` from a `mutable_shared_buffer`. This allows the following use common networking use case: create a `mutable_shared_buffer`, serialize objects into it, then (efficiently) construct a `const_shared_buffer` and send it out over the network. While internally all data is kept in `std::byte` buffers, convenience methods are provided for converting between traditional buffer types (such as `char *` or `unsigned char*` or similar). diff --git a/cmake/download_cpm.cmake b/cmake/download_cpm.cmake index b4e123b..dd69ebe 100644 --- a/cmake/download_cpm.cmake +++ b/cmake/download_cpm.cmake @@ -4,7 +4,7 @@ file( DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.39.0/CPM.cmake + https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.40.0/CPM.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake ) include(${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3fde893..5843110 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2024 by Cliff Green +# Copyright (c) 2024-2025 by Cliff Green # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE.txt or copy at https://www.boost.org/LICENSE_1_0.txt) @@ -11,8 +11,8 @@ project ( shared_buffer_example LANGUAGES CXX ) # add dependencies include ( ../cmake/download_cpm.cmake ) -CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.0" ) -CPMAddPackage ( "gh:connectivecpp/binary-serialize@1.0.0" ) +CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.5" ) +CPMAddPackage ( "gh:connectivecpp/binary-serialize@1.0.4" ) # add executable add_executable ( shared_buffer_example shared_buffer_example.cpp ) diff --git a/example/shared_buffer_example.cpp b/example/shared_buffer_example.cpp index 75a32c5..30b4d38 100644 --- a/example/shared_buffer_example.cpp +++ b/example/shared_buffer_example.cpp @@ -1,14 +1,15 @@ /** @file * - * @brief Example code demonstrating use of @c chops::shared_buffer and - * @c chops::repeat. See @c threaded_wait_shared_demo.cpp for multithreaded - * example. + * @brief Example code demonstrating use of @c chops::shared_buffer. + * See @c threaded_wait_shared_demo.cpp for multithreaded example. * * @author Thurman Gillespy * * @copyright (c) 2019 by Thurman Gillespy * 3/22/19 * + * Minor changes 4/3/2025 by Cliff Green (change repeat to iota, append now has endian flag). + * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * @@ -25,10 +26,11 @@ #include // std::byte #include // std::uint16_t #include +#include // std::strlen +#include // std::views::iota #include "serialize/extract_append.hpp" #include "buffer/shared_buffer.hpp" -#include "utility/repeat.hpp" // tasty utility lambda function constexpr auto printLn = [] () { std::cout << std::endl; }; @@ -55,17 +57,18 @@ int main() { constexpr char str1[] = "A cat in the hat."; const char* strptr = str1; - // add one char at a time, inside chops::repeat - chops::repeat(sizeof(str1), - [&] () { buf1.append(static_cast (*strptr++)); }); + // add one char at a time + for (int i : std::views::iota(0u, std::strlen(strptr) + 1)) { + buf1.append(static_cast (*strptr++)); + } - // what str1 and chops::repeat replaces + // what str1 and the loop replaces // buf1.append(static_cast('A'); // buf1.append((static_cast(' '); // buf1.append((static_cast('c'); // etc. - std::cout << "buffer1 contains " << buf1.size() << " bytes" << std::endl; + std::cout << "buffer1 contains (including trailing nul char) " << buf1.size() << " bytes" << std::endl; // print the output, one char at a time const char* byte = cast_to_char_ptr (buf1); // data starts here for (unsigned int i = 0; i < buf1.size(); ++i) { @@ -90,20 +93,25 @@ int main() { std::cout << "buffer2 contains " << buf2.size() << " bytes and "; std::cout << (buf2.size()/sizeof(std::uint16_t)) << " short integers\n"; - // input some numbers using chops::repeat + // input some numbers const std::uint16_t* data = cast_to_uint16_ptr (buf2);// data starts here - std::uint16_t* valptr = const_cast(data); // remove const* // create number, convert to 'network' (big endian) byte order, place into buf2 std::uint16_t count = 1; - chops::repeat(NUM_INTS, [count, x = buf2.data()] () mutable {auto sz = - chops::append_val (x, count++ * 5); x += sz; }); + auto x = buf2.data(); + for (int i : std::views::iota(0, NUM_INTS)) { + auto sz = chops::append_val (x, count++ * 5); + x += sz; + } // print them out - valptr = const_cast (data); - // read 2 bytes, convert back to proper endian order, print - auto f = [x = buf2.data()] () mutable { std::cout << chops::extract_val(x) << " "; x+=2;}; - chops::repeat(NUM_INTS, f); + // read 2 bytes, convert back to native endian order, print + x = buf2.data(); + for (int i : std::views::iota(0, NUM_INTS)) { + std::cout << chops::extract_val(x) << " "; + x+=2; + } + printLn(); // swap the buffers, print result @@ -111,8 +119,11 @@ int main() { std::cout << "buffer2 contents after swap" << std::endl; std::cout << cast_to_char_ptr (buf2) << std::endl; std::cout << "buffer1 contents after swap" << std::endl; - valptr = const_cast (data); - chops::repeat(NUM_INTS, f); + x = buf1.data(); + for (int i : std::views::iota(0, NUM_INTS)) { + std::cout << chops::extract_val(x) << " "; + x+=2; + } printLn(); return EXIT_SUCCESS; diff --git a/include/buffer/shared_buffer.hpp b/include/buffer/shared_buffer.hpp index 3a2f095..8112e9f 100644 --- a/include/buffer/shared_buffer.hpp +++ b/include/buffer/shared_buffer.hpp @@ -26,13 +26,13 @@ * convenience methods for appending data. @c const_shared_buffer is a reference counted * non-modifiable buffer class. Once the object is constructed, it cannot be modified. * - * A @c const_shared_buffer can be efficiently constructed (no buffer copies) from a - * @c mutable shared_buffer. This allows the use case of serializing data into a - * @c mutable_shared_buffer then constructing a @c const_shared_buffer for writing to - * the network. + * A @c const_shared_buffer can be efficiently constructed (no buffer copies, only + * pointer assignments through move construction) from a @c mutable shared_buffer. This + * allows the use case of serializing data into a @c mutable_shared_buffer then + * constructing a @c const_shared_buffer for writing to the network. * * Besides the data buffer lifetime management, these utility classes eliminate data - * copies and (obviously) do not have to be used only in networking use cases. + * copies and (obviously) can be utilized in use cases other than networking. * * ### Additional Details * @@ -64,7 +64,7 @@ * * @authors Cliff Green, Chris Kohlhoff * - * @copyright (c) 2017-2024 by Cliff Green + * @copyright (c) 2017-2025 by Cliff Green * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6300bb..2545759 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2024 by Cliff Green +# Copyright (c) 2024-2025 by Cliff Green # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE.txt or copy at https://www.boost.org/LICENSE_1_0.txt) @@ -16,7 +16,7 @@ target_compile_features ( shared_buffer_test PRIVATE cxx_std_20 ) include ( ../cmake/download_cpm.cmake ) CPMAddPackage ( "gh:catchorg/Catch2@3.8.0" ) -CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.4" ) +CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.5" ) # link dependencies target_link_libraries ( shared_buffer_test PRIVATE shared_buffer utility_rack Catch2::Catch2WithMain ) diff --git a/test/shared_buffer_test.cpp b/test/shared_buffer_test.cpp index 8b01c62..3230ec3 100644 --- a/test/shared_buffer_test.cpp +++ b/test/shared_buffer_test.cpp @@ -5,7 +5,7 @@ * * @author Cliff Green * - * @copyright (c) 2017-2024 by Cliff Green + * @copyright (c) 2017-2025 by Cliff Green * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,10 @@ #include #include // std::copy #include // std::bit_cast +#include // std::views::iota #include "buffer/shared_buffer.hpp" -#include "utility/repeat.hpp" #include "utility/byte_array.hpp" constexpr std::size_t test_data_size { 12u }; @@ -203,15 +203,16 @@ TEST_CASE ( "Mutable shared buffer resize and clear", sb.resize(N); REQUIRE (sb.size() == N); - chops::repeat(N, [&sb] (int i) { REQUIRE (std::to_integer(*(sb.data() + i)) == 0 ); } ); - + for (int i : std::views::iota(0, N)) { + REQUIRE (std::to_integer(*(sb.data() + i)) == 0 ); + } SECTION ( "Compare two resized mutable shared buffer with same size" ) { chops::mutable_shared_buffer sb2(N); REQUIRE (sb == sb2); - chops::repeat(N, [&sb, &sb2] (int i) { + for (int i : std::views::iota(0, N)) { REQUIRE (std::to_integer(*(sb.data() + i)) == 0 ); REQUIRE (std::to_integer(*(sb2.data() + i)) == 0 ); - } ); + } } SECTION ( "Clear, check size" ) { sb.clear();