Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard replacement for QByteArray

I want to port a Qt C++11 function to standard C++11. The function has a QByteArray parameter that accepts any kind of data (text, binary data, etc.) and calculates a hash from the data.

QByteArray seems well suited because it can carry any kind of data and has a lot of functions that allow filling it from streams, devices, strings, etc. It even can wrap data without doing a deep copy using fromRawData().

Is there a standard C++11 solution that provides similar flexibility? Currently I tend to use good old void* plus size.

like image 402
Silicomancer Avatar asked Feb 06 '23 15:02

Silicomancer


2 Answers

Is there a standard C++11 solution that provides similar flexibility? Currently I tend to use good old void* plus size.

There's no standard C++11 solution that provides a container that can both manage its own memory or wrap memory managed by someone else.

You could simply copy the QByteArray (it's a few files) and bundle it with your project, if licensing terms allow.

Otherwise, if you only intend to work on containers with contiguous storage for all elements, the const void* and size_t arguments make perfect sense, and will be most portable and adaptable. You can provide convenience overloads as needed. E.g.

HashType calculateHash(const void*, size_t);

template <typename T> HashType calculateHash(const T& container) {
  static_assert(sizeof(typename T::value_type) == 1, "value_type must be byte-sized");
  assert(&container[container.size()-1] == &container[0]+container.size());
  return calculateHash(&container[0], container.size());
}

To support any container, even those with non-contiguous storage, the base calculateHash can take a range and offer an overload for hashing an entire container.

template <typename I>
HashType calculateHash(I start, I const end) {
  HashType hash;
  for (; start != end; ++start)
    hash.update(*start);
  return hash;
}

template <typename C>
HashType calculateHash(const C& container) {
  using std::begin;
  using std::end;
  return calculateHash(begin(container), end(container));
}
like image 72
Kuba hasn't forgotten Monica Avatar answered Feb 08 '23 06:02

Kuba hasn't forgotten Monica


I do not know such kind of standard container that has the same complex functionality what QByteArray has but I would start with std::vector< char > and would implement a wrapper around that with the missing and necessary functions.

std::vector has high flexibility, you can access each element in constant time and you can easily convert it to std::string (for example Converting a vector to string).

If the insert operation is more important maybe you can try std::list< char >. Mainly this is linked list implementation.

Based on the comment from Jesper Juhl: using uint8_t as template argument would describe the real the byte array behavior.

like image 38
Tibor Takács Avatar answered Feb 08 '23 04:02

Tibor Takács