From 0de3a787ff7fcf247600fbd26e7d8fa80bcc7750 Mon Sep 17 00:00:00 2001 From: Homing So Date: Thu, 23 May 2024 16:34:55 +0800 Subject: [PATCH] feat: add concept for WriteStream Signed-off-by: Homing So --- example/struct.cc | 6 ++-- include/bencode/writer.h | 67 +++++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/example/struct.cc b/example/struct.cc index 2e0ef54..0281813 100644 --- a/example/struct.cc +++ b/example/struct.cc @@ -77,7 +77,7 @@ struct TorrentFile { } }; -int main(int argc, char *argv[]) { +int main(const int argc, char *argv[]) { (void)argc; (void)argv; @@ -89,10 +89,10 @@ int main(int argc, char *argv[]) { } // 2. Bind DOM to struct. - auto torrent_file = TorrentFile(doc); + const auto torrent_file = TorrentFile(doc); // 3. Convert struct to Bencode and output - auto value = torrent_file.toBencode(); + const auto value = torrent_file.toBencode(); char writeBuffer[65536]; bencode::FileWriteStream out(stdout, writeBuffer); bencode::Writer writer(out); diff --git a/include/bencode/writer.h b/include/bencode/writer.h index 66ef0e3..2a16058 100644 --- a/include/bencode/writer.h +++ b/include/bencode/writer.h @@ -44,7 +44,35 @@ BENCODE_DIAG_OFF(effc++) namespace bencode { -template class Writer : NonCopyable { +namespace required::write_stream { +namespace details { + +template +concept HasPut = requires(WriteStream os, char ch) { + { os.put(ch) } -> std::same_as; +}; + +template +concept HasPuts = + requires(WriteStream os, const char *str, std::size_t length) { + { os.puts(str, length) } -> std::same_as; + }; + +template +concept HasFlush = requires(WriteStream os) { + { os.flush() } -> std::same_as; +}; + +} // namespace details + +template +concept HasAllRequiredFunctions = + details::HasPut && details::HasPuts && details::HasFlush; + +} // namespace required::write_stream + +template +class Writer : NonCopyable { protected: uint64_t stack_; WriteStream &os_; @@ -54,11 +82,15 @@ template class Writer : NonCopyable { virtual ~Writer() = default; virtual bool Null() { return true; } - virtual bool Integer(int64_t i64) { return EndValue(WriteInteger(i64)); } - virtual bool String(std::string_view str) { + virtual bool Integer(const int64_t i64) { + return EndValue(WriteInteger(i64)); + } + virtual bool String(const std::string_view str) { return EndValue(WriteString(str)); } - virtual bool Key(std::string_view str) { return EndValue(WriteKey(str)); } + virtual bool Key(const std::string_view str) { + return EndValue(WriteKey(str)); + } virtual bool StartList() { ++stack_; return EndValue(WriteStartList()); @@ -88,8 +120,8 @@ template class Writer : NonCopyable { void Flush() { os_.flush(); } }; -template -bool Writer::WriteInteger(int64_t i64) { +template +bool Writer::WriteInteger(const int64_t i64) { char buf[32]{}; auto size = static_cast(internal::i64toa(i64, buf) - buf); os_.put('i'); @@ -98,8 +130,8 @@ bool Writer::WriteInteger(int64_t i64) { return true; } -template -bool Writer::WriteString(std::string_view str) { +template +bool Writer::WriteString(const std::string_view str) { char buf[32]{}; auto size = static_cast(internal::u64toa(str.length(), buf) - buf); @@ -109,33 +141,38 @@ bool Writer::WriteString(std::string_view str) { return true; } -template -bool Writer::WriteKey(std::string_view str) { +template +bool Writer::WriteKey(const std::string_view str) { WriteString(str); return true; } -template bool Writer::WriteStartList() { +template +bool Writer::WriteStartList() { os_.put('l'); return true; } -template bool Writer::WriteEndList() { +template +bool Writer::WriteEndList() { os_.put('e'); return true; } -template bool Writer::WriteStartDict() { +template +bool Writer::WriteStartDict() { os_.put('d'); return true; } -template bool Writer::WriteEndDict() { +template +bool Writer::WriteEndDict() { os_.put('e'); return true; } -template bool Writer::EndValue(bool ret) { +template +bool Writer::EndValue(const bool ret) { // end of bencode text if (stack_ == 0) { Flush();