aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--include/winapi/buffer.hpp69
-rw-r--r--include/winapi/handle.hpp5
-rw-r--r--src/handle.cpp10
3 files changed, 76 insertions, 8 deletions
diff --git a/include/winapi/buffer.hpp b/include/winapi/buffer.hpp
new file mode 100644
index 0000000..246822e
--- /dev/null
+++ b/include/winapi/buffer.hpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "winapi-common" project.
+// For details, see https://github.com/egor-tensin/winapi-common.
+// Distributed under the MIT License.
+
+#pragma once
+
+#include <cstddef>
+#include <cstring>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace winapi {
+
+class Buffer : public std::vector<unsigned char> {
+public:
+ typedef std::vector<unsigned char> Parent;
+
+ Buffer() = default;
+
+ explicit Buffer(Parent&& src) : Parent(std::move(src)) {}
+
+ template <typename CharT>
+ explicit Buffer(const std::basic_string<CharT>& src) {
+ set(src);
+ }
+
+ explicit Buffer(const void* src, std::size_t nb) { set(src, nb); }
+
+ template <typename CharT>
+ void set(const std::basic_string<CharT>& src) {
+ set(src.c_str(), src.length() * sizeof(std::basic_string<CharT>::char_type));
+ }
+
+ void set(const void* src, std::size_t nb) {
+ resize(nb);
+ std::memcpy(data(), src, nb);
+ }
+
+ std::string as_utf8() const {
+ const auto c_str = reinterpret_cast<const char*>(data());
+ const auto nb = size();
+ const auto nch = nb;
+ return {c_str, nch};
+ }
+
+ std::wstring as_utf16() const {
+ const auto c_str = reinterpret_cast<const wchar_t*>(data());
+ const auto nb = size();
+ if (nb % 2 != 0) {
+ std::ostringstream oss;
+ oss << "Buffer size invalid at " << nb << " bytes";
+ throw std::runtime_error{oss.str()};
+ }
+ const auto nch = nb / 2;
+ return {c_str, nch};
+ }
+
+ void add(const Buffer& src) {
+ const auto nb = size();
+ resize(size() + src.size());
+ std::memcpy(data() + nb, src.data(), src.size());
+ }
+};
+
+} // namespace winapi
diff --git a/include/winapi/handle.hpp b/include/winapi/handle.hpp
index af37424..5f813bc 100644
--- a/include/winapi/handle.hpp
+++ b/include/winapi/handle.hpp
@@ -5,6 +5,8 @@
#pragma once
+#include "buffer.hpp"
+
#include <boost/config.hpp>
#include <windows.h>
@@ -12,7 +14,6 @@
#include <cstddef>
#include <memory>
#include <utility>
-#include <vector>
namespace winapi {
@@ -37,8 +38,6 @@ public:
static Handle std_out();
static Handle std_err();
- typedef std::vector<unsigned char> Buffer;
-
Buffer read() const;
BOOST_STATIC_CONSTEXPR std::size_t max_chunk_size = 16 * 1024;
diff --git a/src/handle.cpp b/src/handle.cpp
index a6ab3a5..1147cf6 100644
--- a/src/handle.cpp
+++ b/src/handle.cpp
@@ -3,6 +3,7 @@
// For details, see https://github.com/egor-tensin/winapi-common.
// Distributed under the MIT License.
+#include <winapi/buffer.hpp>
#include <winapi/error.hpp>
#include <winapi/handle.hpp>
#include <winapi/workarounds.hpp>
@@ -15,6 +16,7 @@
#include <cstddef>
#include <sstream>
#include <stdexcept>
+#include <utility>
namespace winapi {
namespace {
@@ -100,15 +102,13 @@ bool Handle::read_chunk(Buffer& buffer) const {
}
}
-Handle::Buffer Handle::read() const {
+Buffer Handle::read() const {
Buffer buffer;
- Buffer chunk;
while (true) {
+ Buffer chunk;
const auto next = read_chunk(chunk);
-
- buffer.reserve(buffer.size() + chunk.size());
- buffer.insert(buffer.cend(), chunk.cbegin(), chunk.cend());
+ buffer.add(chunk);
if (!next) {
break;