简体   繁体   English

将字符串数据附加到std :: vector <std::byte> &gt;

[英]Append string data to std::vector<std::byte>>

I'm implementing a HTTP server and the API I follow define the raw response data as a std::vector<std::byte>> . 我正在实现一个HTTP服务器,并且遵循的API将原始响应数据定义为std::vector<std::byte>>

I store http responses headers as std::string in my code and at some point I have to write them to to raw response data before sending it back. 我在代码中将http响应标头存储为std::string ,在某些时候我必须将它们写到原始响应数据中,然后再发送回去。

The thing is, I cannot find a clean way to write/append data from a std::string to my std::vector<std::byte>> (by clean way I mean not looping on the string and appending each char). 问题是,我找不到一种干净的方法将数据从std::string写入/追加到我的std::vector<std::byte>> (通过干净的方式,我的意思是不循环字符串并附加每个字符) 。

What is the best way to do that ? 最好的方法是什么?

Side question: What is the best way to read a string from a std::vector<std::byte>> ? 附带问题:从std::vector<std::byte>>读取字符串的最佳方法是什么?

The char do cannot be converted to std::byte . char不能转换为std::byte Its defined as scoped enum: 其定义为范围枚举:

enum class byte : unsigned char {} ;

cppreference.com std::byte cppreference.com std :: byte

A numeric value n can be converted to a byte value using std::byte{n} , due to C++17 relaxed enum class initialization rules. 由于C ++ 17宽松的枚举类初始化规则,因此可以使用std::byte{n}将数值n转换为字节值。

What you can do is use a helper function or lambda: 您可以做的是使用辅助函数或lambda:

std::string headers;
std::vector<std::byte> response;

response.reserve(response.size() + headers.size());  // Optional
std::transform(headers.begin(), headers.end(), std::back_inserter(response),
    [](unsigned char c) { return std::byte{c}; }              // or `encode(c)`
);  

You can also resize the response and skip the back_inserter : 您还可以调整response大小并跳过back_inserter

const auto response_size = response.size();
response.resize(response_size + headers.size());
std::transform(headers.begin(), headers.end(), std::next(response.begin(), response_size),
    [](unsigned char c) { return std::byte{c}; }
);  

Actually the whole will be optimized by the compiler to something similar to std::copy . 实际上,整个编译器会将其优化为类似于std::copy

Or just replace std::byte with a char and use std::vector::insert() or std::copy() . 或者只是将std::byte替换为char并使用std::vector::insert()std::copy()

Just use the ranged- insert overload ( #4 ): 只需使用远程insert重载( #4 ):

void extend(std::vector<std::byte>& v, std::string const& s) {
    auto bytes = reinterpret_cast<std::byte const*>(s.data());
    v.insert(v.end(), bytes, bytes + s.size());
}

You can read char as byte , it's a permitted alias. 您可以将char读取为byte ,这是允许的别名。

First start with a gsl::span or similar. 首先从gsl::span或类似的名称开始。

template<class T>
struct span {
  T* b =0, *e = 0;
  T* begin() const { return b; }
  T* end() const { return e; }
  std::size_t size() const { return end()-begin(); }
  bool empty() const { return end()==begin(); }
  span( T* s, T* f ):b(s),e(f) {}
  span( T* s, std::size_t len ):span(s, s+len) {}

  template<class Uptr>
  using is_compatible = std::is_convertible< Uptr*, T* >;

  template<class R,
    std::enable_if_t<!std::is_same<std::decay_t<R>, span>{}, bool> = true,
    std::enable_if_t<is_compatible<decltype(std::declval<R&>().data())>{}, bool> = true
  >
  span( R&& r ):
    span(r.data(), r.size())
  {}
  template<class U, std::size_t N,
    std::enable_if_t<is_compatible<U*>{}, bool> = true
  >
  span( U(&arr)[N] ):span(arr, N) {}
};

now we have an abstraction for "possibly mutable view into contiguous T s". 现在我们有了“可能可变的连续T s视图”的抽象。

std::vector<std::byte> concat_string( std::vector<std::byte> lhs, span<char const> rhs ) {
  lhs.reserve(lhs.size()+rhs.size());
  lhs.insert( lhs.end(), (std::byte const*)rhs.begin(), (std::byte const*)rhs.end() );
  return rhs;
}

this assumes you don't want to embed the '\\0' . 假设您不想嵌入'\\0'

you'll want something like the following. 您会想要以下内容。 I realize this still uses copy but there is only the one memory allocation which is the expensive part. 我意识到这仍然使用复制,但是只有一个内存分配是昂贵的部分。

std::vector<std::byte> data;
std::string input;
...
data.reserve(data.size() + input.size());
std::copy(input.begin(), input.end(), std::back_inserter(data));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM