bytes.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "base/basic_types.h"
  9. #include <gsl/gsl>
  10. #include <gsl/byte>
  11. #include <vector>
  12. #include <array>
  13. namespace bytes {
  14. using type = gsl::byte;
  15. using span = gsl::span<type>;
  16. using const_span = gsl::span<const type>;
  17. using vector = std::vector<type>;
  18. template <gsl::index Size>
  19. using array = std::array<type, Size>;
  20. inline span make_detached_span(QByteArray &container) {
  21. return gsl::as_writable_bytes(gsl::make_span(container));
  22. }
  23. template <
  24. typename Container,
  25. typename = std::enable_if_t<
  26. !std::is_const_v<Container>
  27. && !std::is_same_v<Container, QByteArray>>>
  28. inline span make_span(Container &container) {
  29. return gsl::as_writable_bytes(gsl::make_span(container));
  30. }
  31. template<>
  32. inline span make_span<span, void>(span &container) {
  33. return container;
  34. }
  35. template <typename Container>
  36. inline const_span make_span(const Container &container) {
  37. return gsl::as_bytes(gsl::make_span(container));
  38. }
  39. inline const_span make_span(const_span &container) {
  40. return container;
  41. }
  42. template <typename Type, std::ptrdiff_t Extent>
  43. inline span make_span(gsl::span<Type, Extent> container) {
  44. return gsl::as_writable_bytes(container);
  45. }
  46. template <typename Type, std::ptrdiff_t Extent>
  47. inline const_span make_span(gsl::span<const Type, Extent> container) {
  48. return gsl::as_bytes(container);
  49. }
  50. template <typename Type>
  51. inline span make_span(Type *value, std::size_t count) {
  52. return gsl::as_writable_bytes(gsl::make_span(value, count));
  53. }
  54. template <typename Type>
  55. inline const_span make_span(const Type *value, std::size_t count) {
  56. return gsl::as_bytes(gsl::make_span(value, count));
  57. }
  58. template <typename Type>
  59. inline span object_as_span(Type *value) {
  60. return bytes::make_span(value, 1);
  61. }
  62. template <typename Type>
  63. inline const_span object_as_span(const Type *value) {
  64. return bytes::make_span(value, 1);
  65. }
  66. template <typename Container>
  67. inline vector make_vector(const Container &container) {
  68. const auto buffer = bytes::make_span(container);
  69. return { buffer.begin(), buffer.end() };
  70. }
  71. inline void copy(span destination, const_span source) {
  72. Expects(destination.size() >= source.size());
  73. memcpy(destination.data(), source.data(), source.size());
  74. }
  75. inline void move(span destination, const_span source) {
  76. Expects(destination.size() >= source.size());
  77. memmove(destination.data(), source.data(), source.size());
  78. }
  79. inline void set_with_const(span destination, type value) {
  80. memset(
  81. destination.data(),
  82. gsl::to_integer<unsigned char>(value),
  83. destination.size());
  84. }
  85. inline int compare(const_span a, const_span b) {
  86. const auto aSize = a.size(), bSize = b.size();
  87. return (aSize > bSize)
  88. ? 1
  89. : (aSize < bSize)
  90. ? -1
  91. : memcmp(a.data(), b.data(), aSize);
  92. }
  93. namespace details {
  94. template <typename Arg>
  95. std::size_t spansLength(Arg &&arg) {
  96. return bytes::make_span(arg).size();
  97. }
  98. template <typename Arg, typename ...Args>
  99. std::size_t spansLength(Arg &&arg, Args &&...args) {
  100. return bytes::make_span(arg).size() + spansLength(args...);
  101. }
  102. template <typename Arg>
  103. void spansAppend(span destination, Arg &&arg) {
  104. bytes::copy(destination, bytes::make_span(arg));
  105. }
  106. template <typename Arg, typename ...Args>
  107. void spansAppend(span destination, Arg &&arg, Args &&...args) {
  108. const auto data = bytes::make_span(arg);
  109. bytes::copy(destination, data);
  110. spansAppend(destination.subspan(data.size()), args...);
  111. }
  112. } // namespace details
  113. template <
  114. typename ...Args,
  115. typename = std::enable_if_t<(sizeof...(Args) > 1)>>
  116. vector concatenate(Args &&...args) {
  117. const auto size = details::spansLength(args...);
  118. auto result = vector(size);
  119. details::spansAppend(make_span(result), args...);
  120. return result;
  121. }
  122. template <typename SpanRange>
  123. vector concatenate(SpanRange args) {
  124. auto size = std::size_t(0);
  125. for (const auto &arg : args) {
  126. size += bytes::make_span(arg).size();
  127. }
  128. auto result = vector(size);
  129. auto buffer = make_span(result);
  130. for (const auto &arg : args) {
  131. const auto part = bytes::make_span(arg);
  132. bytes::copy(buffer, part);
  133. buffer = buffer.subspan(part.size());
  134. }
  135. return result;
  136. }
  137. void set_random(span destination);
  138. } // namespace bytes