Skip to content

Commit 79be3d0

Browse files
Merge pull request #4 from connectivecpp/develop
Merge develop to main
2 parents 87e30c4 + 9d20c02 commit 79be3d0

File tree

5 files changed

+352
-231
lines changed

5 files changed

+352
-231
lines changed

.github/workflows/build_run_unit_test_cmake.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ jobs:
1212
build_matrix:
1313
strategy:
1414
matrix:
15-
# os: [ubuntu-latest, windows-latest, macos-14]
16-
os: [ubuntu-latest]
15+
os: [ubuntu-latest, windows-latest, macos-14]
16+
# os: [ubuntu-latest, windows-latest]
1717
runs-on: ${{ matrix.os }}
1818
defaults:
1919
run:

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
![GH Tag](https://img.shields.io/github/v/tag/connectivecpp/shared-buffer?label=GH%20tag)
1212

13+
![License](https://img.shields.io/badge/License-Boost%201.0-blue)
14+
1315
## Overview
1416

1517
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.
@@ -40,7 +42,7 @@ The unit test code uses [Catch2](https://github.com/catchorg/Catch2). If the `SH
4042

4143
The unit test uses utilities from Connective C++'s [utility-rack](https://github.com/connectivecpp/utility-rack).
4244

43-
Specific version (or branch) specs for the dependenies are in `test/CMakeLists.txt`.
45+
Specific version (or branch) specs for the dependencies are in the [test/CMakeLists.txt](test/CMakeLists.txt) file, look for the `CPMAddPackage` commands.
4446

4547
## Build and Run Unit Tests
4648

include/buffer/shared_buffer.hpp

+123-53
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@
8181
#include <span>
8282

8383
#include <utility> // std::move, std::swap
84-
#include <cstring> // std::memcpy
84+
#include <algorithm> // std::copy
8585

86-
// TODO - add conecepts and / or requires
86+
// TODO - add concepts and / or requires
8787
//
8888
// modify the templated constructor that takes a buffer of any valid
89-
// byte type, add constraints; this makes the "reinterpret_cast" safe
89+
// byte type, add constraints which makes the casting safer
9090

9191
namespace chops {
9292

@@ -147,6 +147,34 @@ class mutable_shared_buffer {
147147
mutable_shared_buffer() noexcept :
148148
m_data{std::make_shared<byte_vec>(size_type(0))} { }
149149

150+
/**
151+
* @brief Construct by copying from a @c std::span of @c std::byte.
152+
*
153+
* @param sp @c std::byte span pointing to buffer of data. The data is
154+
* copied into the internal buffer of the @c mutable_shared_buffer.
155+
*
156+
*/
157+
template <std::size_t Ext>
158+
explicit mutable_shared_buffer(std::span<const std::byte, Ext> sp) :
159+
m_data{std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())} { }
160+
161+
/**
162+
* @brief Construct by copying from a @c std::byte array.
163+
*
164+
* A @c std::span is first created, then the constructor taking
165+
* a @c std::span is called.
166+
*
167+
* @pre Size cannot be greater than the source buffer.
168+
*
169+
* @param buf Non-null pointer to a @c std::byte buffer of data. The
170+
* data is copied into the internal buffer of the @c mutable_shared_buffer.
171+
*
172+
* @param sz Size of buffer.
173+
*
174+
*/
175+
mutable_shared_buffer(const std::byte* buf, std::size_t sz) :
176+
mutable_shared_buffer(std::as_bytes(std::span<const std::byte>{buf, sz})) { }
177+
150178
/**
151179
* @brief Move construct from a @c std::vector of @c std::bytes.
152180
*
@@ -161,45 +189,34 @@ class mutable_shared_buffer {
161189
m_data{std::make_shared<byte_vec>(size_type(0))} {
162190
*m_data = std::move(bv);
163191
}
192+
164193
/**
165194
* @brief Construct a @c mutable_shared_buffer with an initial size, contents
166-
* set to zero.
195+
* of each byte set to zero.
167196
*
168197
* Allocate zero initialized space which can be overwritten with data as needed.
169198
* The @c data method is called to get access to the underlying @c std::byte
170199
* buffer.
171200
*
172201
* @param sz Size for internal @c std::byte buffer.
173202
*/
174-
explicit mutable_shared_buffer(size_type sz) noexcept :
203+
explicit mutable_shared_buffer(size_type sz) :
175204
m_data{std::make_shared<byte_vec>(sz)} { }
176205

177-
/**
178-
* @brief Construct by copying from a @c std::span of @c std::byte.
179-
*
180-
* @param sp @c std::byte span pointing to buffer of data. The data is
181-
* copied into the internal buffer of the @c mutable_shared_buffer.
182-
*
183-
*/
184-
mutable_shared_buffer(std::span<const std::byte> sp) noexcept :
185-
m_data{std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())} { }
186206

187207
/**
188-
* @brief Construct by copying from a @c std::byte array.
189-
*
190-
* A @c std::span is first created, then the constructor taking
191-
* a @c std::span is called.
208+
* @brief Construct by copying bytes from a @c std::span.
192209
*
193-
* @pre Size cannot be greater than the source buffer.
194-
*
195-
* @param buf @c std::byte array containing buffer of data. The data is
196-
* copied into the internal buffer of the @c mutable_shared_buffer.
210+
* The type of the span must be convertible to or be layout compatible with
211+
* @c std::byte.
197212
*
198-
* @param sz Size of buffer.
213+
* @param sp @c std::span pointing to buffer of data. The @c std::span
214+
* pointer is cast into a @c std::byte pointer and bytes are then copied.
199215
*
200216
*/
201-
mutable_shared_buffer(const std::byte* buf, size_type sz) noexcept :
202-
mutable_shared_buffer(std::span<const std::byte>(buf, sz)) { }
217+
template <typename T, std::size_t Ext>
218+
mutable_shared_buffer(std::span<const T, Ext> sp) :
219+
mutable_shared_buffer(std::as_bytes(sp)) { }
203220

204221
/**
205222
* @brief Construct by copying bytes from an arbitrary pointer.
@@ -210,14 +227,13 @@ class mutable_shared_buffer {
210227
*
211228
* @pre Size cannot be greater than the source buffer.
212229
*
213-
* @param buf Pointer to a buffer of data. The pointer must be convertible
214-
* to a @c void pointer and then to a @c std::byte pointer.
230+
* @param buf Non-null pointer to a buffer of data.
215231
*
216232
* @param sz Size of buffer, in bytes.
217233
*/
218234
template <typename T>
219235
mutable_shared_buffer(const T* buf, size_type sz) :
220-
mutable_shared_buffer(reinterpret_cast<const std::byte *>(buf), sz) { }
236+
mutable_shared_buffer(std::as_bytes(std::span<const T>{buf, sz})) { }
221237

222238
/**
223239
* @brief Construct from input iterators.
@@ -256,23 +272,23 @@ class mutable_shared_buffer {
256272
const std::byte* data() const noexcept { return m_data->data(); }
257273

258274
/**
259-
* @brief Return access to underlying @c std::vector.
260-
*
261-
* This can be used to instantiate a dynamic_buffer as defined in the Networking TS.
262-
* Changing the @c std::vector from outside this class works because no state
263-
* data is stored within this object that needs to be consistent with the @c std::vector
264-
* contents.
275+
* @brief Return size (number of bytes) of buffer.
265276
*
266-
* @return Reference to @c std::vector<std::byte>.
277+
* @return Size of buffer, which may be zero.
267278
*/
268-
byte_vec& get_byte_vec() noexcept { return *m_data; }
279+
size_type size() const noexcept { return m_data->size(); }
269280

270281
/**
271-
* @brief Return size (number of bytes) of buffer.
282+
* @brief Return access to underlying @c std::vector.
272283
*
273-
* @return Size of buffer, which may be zero.
284+
* This can be used to instantiate a @c dynamic_buffer as defined in the Networking TS
285+
* or Asio API. Changing the @c std::vector from outside this class works because no
286+
* state data is stored within this object that needs to be consistent with the
287+
* @c std::vector contents.
288+
*
289+
* @return Reference to @c std::vector<std::byte>.
274290
*/
275-
size_type size() const noexcept { return m_data->size(); }
291+
byte_vec& get_byte_vec() noexcept { return *m_data; }
276292

277293
/**
278294
* @brief Query to see if size is zero.
@@ -315,34 +331,63 @@ class mutable_shared_buffer {
315331
/**
316332
* @brief Append a @c std::byte buffer to the end of the internal buffer.
317333
*
318-
* @param buf @c std::byte array containing buffer of data.
334+
* @param buf Non-null pointer to @c std::byte buffer of data.
319335
*
320336
* @param sz Size of buffer.
321337
*
322338
* @return Reference to @c this (to allow method chaining).
323339
*/
324-
mutable_shared_buffer& append(const std::byte* buf, size_type sz) {
340+
mutable_shared_buffer& append(const std::byte* buf, std::size_t sz) {
325341
size_type old_sz = size();
326342
resize(old_sz + sz); // set up buffer space
327-
std::memcpy(data() + old_sz, buf, sz);
343+
std::copy(buf, buf+sz, data()+old_sz);
328344
return *this;
329345
}
330346

347+
/**
348+
* @brief Append a @c std::span to the end of the internal buffer.
349+
*
350+
* @param sp @c std::span of @c std::byte data.
351+
*
352+
* @return Reference to @c this (to allow method chaining).
353+
*/
354+
template <std::size_t Ext>
355+
mutable_shared_buffer& append(std::span<const std::byte, Ext> sp) {
356+
return append(sp.data(), sp.size());
357+
}
358+
331359
/**
332360
* @brief Append by copying bytes from an arbitrary pointer.
333361
*
334362
* The pointer passed into this method is cast into a @c std::byte pointer and bytes
335363
* are then copied. In particular, this method can be used for @c char pointers,
336364
* @c void pointers, @ unsigned @c char pointers, etc.
337365
*
338-
* @param buf Pointer to a buffer of data. The pointer must be convertible
339-
* to a @c void pointer and then to a @c std::byte pointer.
366+
* @param buf Non-null pointer to a buffer of data.
340367
*
341368
* @param sz Size of buffer, in bytes.
342369
*/
343370
template <typename T>
344-
mutable_shared_buffer& append(const T* buf, size_type sz) {
345-
return append(reinterpret_cast<const std::byte *>(buf), sz);
371+
mutable_shared_buffer& append(const T* buf, std::size_t sz) {
372+
return append(std::as_bytes(std::span<const T>{buf, sz}));
373+
}
374+
375+
/**
376+
* @brief Append a @c std::span that is a non @c std::byte buffer.
377+
*
378+
* The @c std::span passed into this method is performs a cast on the
379+
* data. In particular, this method can be used for @c char pointers,
380+
* @c void pointers, @ unsigned @c char pointers, etc.
381+
*
382+
* The type of the span must be convertible to or be layout compatible with
383+
* @c std::byte.
384+
*
385+
* @param sp @c std::span of arbitrary bytes.
386+
*
387+
*/
388+
template <typename T, std::size_t Ext>
389+
mutable_shared_buffer& append(std::span<const T, Ext> sp) {
390+
return append(std::as_bytes(sp));
346391
}
347392

348393
/**
@@ -463,36 +508,61 @@ class const_shared_buffer {
463508
const_shared_buffer& operator=(const const_shared_buffer&) = delete;
464509
const_shared_buffer& operator=(const_shared_buffer&&) = delete;
465510

511+
/**
512+
* @brief Construct by copying from a @c std::span of @c std::byte.
513+
*
514+
* @param sp @c std::byte span pointing to buffer of data. The data is
515+
* copied into the internal buffer of the @c const_shared_buffer.
516+
*
517+
*/
518+
template <std::size_t Ext>
519+
explicit const_shared_buffer(std::span<const std::byte, Ext> sp) :
520+
m_data(std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())) { }
466521
/**
467522
* @brief Construct by copying from a @c std::byte array.
468523
*
469524
* @pre Size cannot be greater than the source buffer.
470525
*
471-
* @param buf @c std::byte array containing buffer of data. The data is
526+
* @param buf Non-null pointer to @c std::byte buffer of data. The data is
472527
* copied into the internal buffer of the @c const_shared_buffer.
473528
*
474529
* @param sz Size of buffer.
475530
*/
476-
const_shared_buffer(const std::byte* buf, size_type sz) :
477-
m_data(std::make_shared<byte_vec>(buf, buf+sz)) { }
531+
const_shared_buffer(const std::byte* buf, std::size_t sz) :
532+
const_shared_buffer(std::as_bytes(std::span<const std::byte>{buf, sz})) { }
478533

534+
/**
535+
* @brief Construct by copying from a @c std::span.
536+
*
537+
* The type of the span must be convertible to or be layout compatible with
538+
* @c std::byte.
539+
*
540+
* @param sp @c std::span pointing to buffer of data. The @c std::span
541+
* pointer is cast into a @c std::byte pointer and bytes are then copied.
542+
*
543+
*/
544+
template <typename T, std::size_t Ext>
545+
const_shared_buffer(std::span<const T, Ext> sp) :
546+
const_shared_buffer(std::as_bytes(sp)) { }
479547
/**
480548
* @brief Construct by copying bytes from an arbitrary pointer.
481549
*
482550
* The pointer passed into this constructor is cast into a @c std::byte pointer and bytes
483551
* are then copied. In particular, this method can be used for @c char pointers,
484552
* @c void pointers, @c unsigned @c char pointers, etc.
485553
*
554+
* The type of the span must be convertible to or be layout compatible with
555+
* @c std::byte.
556+
*
486557
* @pre Size cannot be greater than the source buffer.
487558
*
488-
* @param buf Pointer to a buffer of data. The pointer must be convertible
489-
* to a @c void pointer and then to a @c std::byte pointer.
559+
* @param buf Non-null pointer to a buffer of data.
490560
*
491561
* @param sz Size of buffer, in bytes.
492562
*/
493563
template <typename T>
494-
const_shared_buffer(const T* buf, size_type sz) :
495-
const_shared_buffer(reinterpret_cast<const std::byte *>(buf), sz) { }
564+
const_shared_buffer(const T* buf, std::size_t sz) :
565+
const_shared_buffer(std::as_bytes(std::span<const T>{buf, sz})) { }
496566

497567
/**
498568
* @brief Construct by copying from a @c mutable_shared_buffer object.

test/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ target_compile_features ( shared_buffer_test PRIVATE cxx_std_20 )
1515
# add dependencies
1616
include ( ../cmake/download_cpm.cmake )
1717

18-
CPMAddPackage ( "gh:catchorg/Catch2@3.6.0" )
19-
CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.0" )
18+
CPMAddPackage ( "gh:catchorg/Catch2@3.7.0" )
19+
CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.3" )
2020

2121
# link dependencies
2222
target_link_libraries ( shared_buffer_test PRIVATE shared_buffer utility_rack Catch2::Catch2WithMain )

0 commit comments

Comments
 (0)