Open technoyes opened 1 year ago
Not super happy about the get_as_raw_ptr() returning size through an output argument, but I can't think of a cleaner way.
Maybe std::span? Or std::string_view? There was some discussion about this here. https://github.com/vector-of-bool/cmrc/issues/24 Preferably without doing a deep copy of any kind. An std::string will create a deep copy of the entire file's data so maybe a string_view is preferred.
I will send an updated PR adding std::string_view
support, but make it optional since it requires C++17. I don't think std::span
offers any additional value, and it also requires C++20. I think I will keep the raw_ptr interface for people stuck with C++11 compilers.
I added a std::string_view accessor, updated the docs (did a drive-by fix on an indentation problem), added a standalone example and added more tests (drive-by fix of a potential undefined return value).
Separated this into five separate commits to make it easier to review.
Let me know what you think when you have time @vector-of-bool.
Fixed a problem with reference assignment (noticed it with MSVC with C++20 standard mode).
Sorry that I missed this. It got buried in notifications and I just saw it after your comment yesterday. This project has unfortunately languished a bit while I've been busy with other things.
I think, IIUC, what this PR and #24 are looking for is an easy contiguous_range
interface. The file
class gets really close, but is just missing the data()
accessor. Simply adding data()
to satisfy std::ranges::contiguous_range
will get it a long way in terms of compatibility with contiguous-range algorithms.
As for the convenience interfaces of span/string(_view)/vector/etc.
, In another library, I have a buffer class with a constrained conversion operator template which allows one to explicit-convert it to string_view/span/vector-like types. I think such a conversion template may be useful for file
. It is entirely possible (although a bit uglier) to write such a conversion template without C++20 concepts. Basically:
// BEWARE: Untested code!
template <
typename To,
typename ConstPointer = typename To::const_pointer,
typename = std::enable_if_t<
// Can construct with a size-pointer pair
std::is_constructible_v<To, ConstPointer, std::size_t>
// Make sure the elements are byte-sized
and sizeof(std::remove_pointer_t<ConstPointer>) == 1
>>
explicit operator T() const noexcept {
return To(reinterpret_cast<ConstPointer>(data()), size());
}
with this, any class which satisfies the constraints can be used in an explicit conversion:
cmrc::file get_some_file();
// ...
auto sv = std::string_view(get_some_file());
std::span
, std::vector
, std::string_view
, QString
, etc. all in one interface.
How does that sound?
No worries at all - mailboxes get flooded and life is busy for us all. Thank you for creating the little gem that CMRC is. Really helps creating self-contained portable apps smoothly!
That said, that is some strong C++ Kung Fu you have there! Learned a lot just looking up what those template constructs do.
From a library users perspective your solution looks clean and efficient.
Does this mean that as a consumer of the resources one could do this:
// No copy of data, direct access to read-only (const) data
const char* raw = std::string_view(fs.open("file.txt")).data();
If so, I'd happily take your solution over this MR.
Gently bumping this one a little bit @vector-of-bool :-)
This change adds support for directly fetching resource data as std::string as well as raw "const char*" combined with std::size_t. This allows cleaner code in use cases where the existing file interface is overkill.
Complete with docs and tests. Also added small doc about the NULL byte that is appended to all resources.
Not super happy about the get_as_raw_ptr() returning size through an output argument, but I can't think of a cleaner way.
Thoughts?