From bc47ff64bdac7f2f9297b1fa7ba474923dc7874a Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Thu, 3 Oct 2024 19:24:26 -0600 Subject: [PATCH 1/6] Showing GDG group --- test/shared_buffer_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/shared_buffer_test.cpp b/test/shared_buffer_test.cpp index 4776df7..8b01c62 100644 --- a/test/shared_buffer_test.cpp +++ b/test/shared_buffer_test.cpp @@ -260,6 +260,8 @@ TEST_CASE ( "Mutable shared buffer append", REQUIRE (sb == ta); } + + SECTION ( "Append mutable shared buffer" ) { sb.append(ta); REQUIRE (sb == ta); From 09906da10f1269aa7aab520db692f8f2172c0371 Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Wed, 8 Jan 2025 12:59:34 -0700 Subject: [PATCH 2/6] Updating to latest Catch2 and macos-15 on GH action runner --- .github/workflows/build_run_unit_test_cmake.yml | 2 +- test/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_run_unit_test_cmake.yml b/.github/workflows/build_run_unit_test_cmake.yml index 311762a..2186356 100644 --- a/.github/workflows/build_run_unit_test_cmake.yml +++ b/.github/workflows/build_run_unit_test_cmake.yml @@ -12,7 +12,7 @@ jobs: build_matrix: strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-14] + os: [ubuntu-latest, windows-latest, macos-15] # os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} defaults: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5a72e14..c6300bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,8 +15,8 @@ target_compile_features ( shared_buffer_test PRIVATE cxx_std_20 ) # add dependencies include ( ../cmake/download_cpm.cmake ) -CPMAddPackage ( "gh:catchorg/Catch2@3.7.0" ) -CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.3" ) +CPMAddPackage ( "gh:catchorg/Catch2@3.8.0" ) +CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.4" ) # link dependencies target_link_libraries ( shared_buffer_test PRIVATE shared_buffer utility_rack Catch2::Catch2WithMain ) From b711eb7d28b87b260bc3b480b0652b172016e0b1 Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Fri, 4 Apr 2025 18:49:21 -0600 Subject: [PATCH 3/6] Updating dependent libraries, docs, utility usage --- .github/workflows/gen_docs.yml | 2 +- CMakeLists.txt | 2 +- README.md | 2 +- cmake/download_cpm.cmake | 2 +- example/CMakeLists.txt | 6 ++-- example/shared_buffer_example.cpp | 49 +++++++++++++++++++------------ include/buffer/shared_buffer.hpp | 12 ++++---- test/CMakeLists.txt | 4 +-- test/shared_buffer_test.cpp | 13 ++++---- 9 files changed, 52 insertions(+), 40 deletions(-) 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(); From 42ddf33b634e6eaf40d9eee225c909ac15d7d935 Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Thu, 10 Apr 2025 08:31:28 -0600 Subject: [PATCH 4/6] Minor tweaks to README --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ceb17dc..3804c38 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ While internally all data is kept in `std::byte` buffers, convenience methods ar The generated Doxygen documentation for `shared_buffer` is [here](https://connectivecpp.github.io/shared-buffer/). -## Dependencies +## Library Dependencies -The `shared_buffer` header file does not have any third-party dependencies. It uses C++ standard library headers only. The unit test code does have dependencies as noted below. +The `shared_buffer` header file does not have any third-party dependencies. It uses C++ standard library headers only. The unit test and example code do have dependencies as noted below. ## C++ Standard @@ -44,6 +44,10 @@ The unit test uses utilities from Connective C++'s [utility-rack](https://github Specific version (or branch) specs for the dependencies are in the [test/CMakeLists.txt](test/CMakeLists.txt) file, look for the `CPMAddPackage` commands. +## Example Dependencies + +The example applications use the Connective C++ `utility_rack` reference counted buffer classes. Specific version (or branch) specs for the dependency are in the [example/CMakeLists.txt](example/CMakeLists.txt) file, look for the `CPMAddPackage` command. + ## Build and Run Unit Tests To build and run the unit test program: From b219c2fae8345f47db404b2e120a792fef6f2840 Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Sat, 19 Apr 2025 11:46:40 -0600 Subject: [PATCH 5/6] README doc tweaks --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3804c38..4135cc6 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Specific version (or branch) specs for the dependencies are in the [test/CMakeLi ## Example Dependencies -The example applications use the Connective C++ `utility_rack` reference counted buffer classes. Specific version (or branch) specs for the dependency are in the [example/CMakeLists.txt](example/CMakeLists.txt) file, look for the `CPMAddPackage` command. +The example applications use the Connective C++ `utility_rack` reference counted buffer classes and `binary_serialize` functions. Specific version (or branch) specs for the dependencies are in the [example/CMakeLists.txt](example/CMakeLists.txt) file, look for the `CPMAddPackage` commands. ## Build and Run Unit Tests From 3ebb369eb88f0b22e2f796d278b132f7ae71d28b Mon Sep 17 00:00:00 2001 From: cliffg-softwarelibre Date: Tue, 22 Apr 2025 18:30:32 -0600 Subject: [PATCH 6/6] Added void pointer construction and append --- include/buffer/shared_buffer.hpp | 102 +++++++++++++++++++++++-------- test/shared_buffer_test.cpp | 31 +++++++--- 2 files changed, 100 insertions(+), 33 deletions(-) diff --git a/include/buffer/shared_buffer.hpp b/include/buffer/shared_buffer.hpp index 8112e9f..8b8493c 100644 --- a/include/buffer/shared_buffer.hpp +++ b/include/buffer/shared_buffer.hpp @@ -32,7 +32,8 @@ * 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) can be utilized in use cases other than networking. + * buffer copies and (obviously) can be utilized in use cases other than networking + * (for example reading and writing disk files). * * ### Additional Details * @@ -53,10 +54,6 @@ * @c mutable_shared_buffer class as well as adding convenience methods to the * @c const_shared_buffer class. * - * It is likely that this shared buffer design and code will change as the C++ - * Networking TS buffer features are expanded, changed, or better understood. Currently - * there are no direct ties to Networking TS buffer features. - * * @note Everything is declared @c noexcept except for the methods that allocate * memory and might throw a memory exception. This is tighter than the @c noexcept * declarations on the underlying @c std::vector methods, since @c std::byte @@ -79,6 +76,7 @@ #include // std::shared_ptr #include // spaceship operator #include +#include // std::bit_cast #include // std::move, std::swap #include // std::copy @@ -99,7 +97,7 @@ class const_shared_buffer; * This class provides ownership, copying, and lifetime management for byte oriented * buffers. In particular, it is designed to be used in conjunction with the * @c const_shared_buffer class for efficient transfer and correct lifetime management - * of buffers in asynchronous libraries (such as the C++ Networking TS). In particular, + * of buffers in asynchronous libraries (such as Asio). In particular, * a reference counted buffer can be passed among multiple layers of software without * any one layer "owning" the buffer. * @@ -223,17 +221,37 @@ class mutable_shared_buffer { * * The pointer passed into this constructor is cast into a @c std::byte pointer and bytes * are then copied. In particular, this method can be used for @c char pointers, - * @c void pointers, @c unsigned @c char pointers, etc. + * @c unsigned @c char pointers, @c std::uint8_t pointers, etc. Non character types that + * are trivially copyable are also allowed, although the usual care must be taken + * (padding bytes, alignment, etc). * * @pre Size cannot be greater than the source buffer. * - * @param buf Non-null pointer to a buffer of data. + * @param buf Non-null pointer to a contiguous array of data. * - * @param sz Size of buffer, in bytes. + * @param num Number of elements in the array. + * + * @note For @c void pointers, see specific constructor taking a @c void pointer. */ template - mutable_shared_buffer(const T* buf, size_type sz) : - mutable_shared_buffer(std::as_bytes(std::span{buf, sz})) { } + mutable_shared_buffer(const T* buf, size_type num) : + mutable_shared_buffer(std::as_bytes(std::span{buf, num})) { } + +/** + * @brief Construct by copying bytes from a void pointer. + * + * The pointer passed into this constructor is cast into a @c std::byte pointer and bytes + * are then copied. + * + * @pre Size cannot be greater than the source buffer. + * + * @param buf Non-null @c void pointer to a buffer of data. + * + * @param sz Size of buffer, in bytes. + */ + mutable_shared_buffer(const void* buf, size_type sz) : + mutable_shared_buffer(std::as_bytes( + std::span{std::bit_cast(buf), sz})) { } /** * @brief Construct from input iterators. @@ -345,7 +363,7 @@ class mutable_shared_buffer { } /** - * @brief Append a @c std::span to the end of the internal buffer. + * @brief Append a @c std::span of @c std::bytes to the end of the internal buffer. * * @param sp @c std::span of @c std::byte data. * @@ -361,15 +379,33 @@ class mutable_shared_buffer { * * The pointer passed into this method is cast into a @c std::byte pointer and bytes * are then copied. In particular, this method can be used for @c char pointers, - * @c void pointers, @ unsigned @c char pointers, etc. + * @c void pointers, @c unsigned @c char pointers, @c std::uint8_t pointers, etc. + * Non character types that are layout compatible with @c std::byte are allowed. * - * @param buf Non-null pointer to a buffer of data. + * @param buf Non-null pointer to an array of data. * - * @param sz Size of buffer, in bytes. + * @param num Number of elements in the array. */ template - mutable_shared_buffer& append(const T* buf, std::size_t sz) { - return append(std::as_bytes(std::span{buf, sz})); + mutable_shared_buffer& append(const T* buf, std::size_t num) { + return append(std::as_bytes(std::span{buf, num})); + } + +/** + * @brief Append by copying bytes from a void pointer. + * + * The pointer passed into this constructor is cast into a @c std::byte pointer and bytes + * are then appended. + * + * @pre Size cannot be greater than the source buffer. + * + * @param buf Non-null @c void pointer to a buffer of data. + * + * @param sz Size of buffer, in bytes. + */ + mutable_shared_buffer& append(const void* buf, size_type sz) { + return append(std::as_bytes( + std::span{std::bit_cast(buf), sz})); } /** @@ -549,20 +585,38 @@ class const_shared_buffer { * * The pointer passed into this constructor is cast into a @c std::byte pointer and bytes * are then copied. In particular, this method can be used for @c char pointers, - * @c void pointers, @c unsigned @c char pointers, etc. + * @c unsigned @c char pointers, @c std::uint8_t pointers, etc. Non character types that + * are trivially copyable are also allowed, although the usual care must be taken + * (padding bytes, alignment, etc). * * The type of the span must be convertible to or be layout compatible with * @c std::byte. * * @pre Size cannot be greater than the source buffer. * - * @param buf Non-null pointer to a buffer of data. + * @param buf Non-null pointer to an array of data. * - * @param sz Size of buffer, in bytes. + * @param num Number of elements in the array. */ template - const_shared_buffer(const T* buf, std::size_t sz) : - const_shared_buffer(std::as_bytes(std::span{buf, sz})) { } + const_shared_buffer(const T* buf, std::size_t num) : + const_shared_buffer(std::as_bytes(std::span{buf, num})) { } + +/** + * @brief Construct by copying bytes from a void pointer. + * + * The pointer passed into this constructor is cast into a @c std::byte pointer and bytes + * are then copied. + * + * @pre Size cannot be greater than the source buffer. + * + * @param buf Non-null @c void pointer to a buffer of data. + * + * @param sz Size of buffer, in bytes. + */ + const_shared_buffer(const void* buf, size_type sz) : + const_shared_buffer(std::as_bytes( + std::span{std::bit_cast(buf), sz})) { } /** * @brief Construct by copying from a @c mutable_shared_buffer object. @@ -581,8 +635,8 @@ class const_shared_buffer { * * This constructor will move from a @c mutable_shared_buffer into a @c const_shared_buffer. * This allows efficient API boundaries, where application code can construct and fill in a - * @c mutable_shared_buffer, then @c std::move it into a @c const_shared_buffer for use - * with asynchronous functions. + * @c mutable_shared_buffer, then use this constructor which will @c std::move it into a + * @c const_shared_buffer for use with asynchronous functions. * * @param rhs @c mutable_shared_buffer to be moved from; after moving the * @c mutable_shared_buffer will be empty. diff --git a/test/shared_buffer_test.cpp b/test/shared_buffer_test.cpp index 3230ec3..fe2131a 100644 --- a/test/shared_buffer_test.cpp +++ b/test/shared_buffer_test.cpp @@ -44,8 +44,7 @@ bool check_sb_against_test_data(SB sb) { } template -SB generic_pointer_construction_test() { - auto ptr { std::bit_cast(test_data.data()) }; +SB generic_pointer_construction_test(const PT * ptr) { SB sb(ptr, test_data_size); REQUIRE_FALSE (sb.empty()); REQUIRE (check_sb_against_test_data(sb)); @@ -53,8 +52,8 @@ SB generic_pointer_construction_test() { } template -void generic_pointer_append_test() { - auto sb { generic_pointer_construction_test() }; +void generic_pointer_append_test(const PT * ptr) { + auto sb { generic_pointer_construction_test(ptr) }; auto sav_sz { sb.size() }; const PT arr[] { 5, 6, 7 }; const PT* ptr_arr { arr }; @@ -149,10 +148,17 @@ void byte_vector_move_test() { TEMPLATE_TEST_CASE ( "Generic pointer construction", "[common]", char, unsigned char, signed char, std::uint8_t ) { - generic_pointer_construction_test(); - generic_pointer_construction_test(); + const TestType* ptr { std::bit_cast(test_data.data()) }; + generic_pointer_construction_test(ptr); + generic_pointer_construction_test(ptr); } +TEST_CASE ( "Void pointer construction", + "[common]" ) { + auto ptr { static_cast(test_data.data()) }; + generic_pointer_construction_test(ptr); + generic_pointer_construction_test(ptr); +} TEMPLATE_TEST_CASE ( "Shared buffer common ctor methods", "[const_shared_buffer] [mutable_shared_buffer] [common]", @@ -261,8 +267,6 @@ TEST_CASE ( "Mutable shared buffer append", REQUIRE (sb == ta); } - - SECTION ( "Append mutable shared buffer" ) { sb.append(ta); REQUIRE (sb == ta); @@ -287,12 +291,21 @@ TEST_CASE ( "Mutable shared buffer append", sb.append(sv.data(), sv.size()); REQUIRE (sb == cb); } + + SECTION ( "Append with void pointer" ) { + std::string_view sv("Haha, Bro!"); + const void* ptr { static_cast(sv.data()) }; + chops::mutable_shared_buffer cb(sv.data(), sv.size()); + sb.append(ptr, sv.size()); + REQUIRE (sb == cb); + } } TEMPLATE_TEST_CASE ( "Generic pointer append", "[mutable_shared_buffer] [pointer] [append]", char, unsigned char, signed char, std::uint8_t ) { - generic_pointer_append_test(); + const TestType* ptr { std::bit_cast(test_data.data()) }; + generic_pointer_append_test(ptr); } TEST_CASE ( "Compare a mutable shared_buffer with a const shared buffer",