162 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| This file is part of Telegram Desktop,
 | |
| the official desktop application for the Telegram messaging service.
 | |
| 
 | |
| For license and copyright information please follow this link:
 | |
| https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | |
| */
 | |
| #pragma once
 | |
| 
 | |
| #include "base/basic_types.h"
 | |
| #include <gsl/gsl>
 | |
| #include <gsl/gsl_byte>
 | |
| 
 | |
| namespace bytes {
 | |
| 
 | |
| using type = gsl::byte;
 | |
| using span = gsl::span<type>;
 | |
| using const_span = gsl::span<const type>;
 | |
| using vector = std::vector<type>;
 | |
| 
 | |
| template <gsl::index Size>
 | |
| using array = std::array<type, Size>;
 | |
| 
 | |
| inline span make_detached_span(QByteArray &container) {
 | |
| 	return gsl::as_writeable_bytes(gsl::make_span(container));
 | |
| }
 | |
| 
 | |
| template <
 | |
| 	typename Container,
 | |
| 	typename = std::enable_if_t<
 | |
| 		!std::is_const_v<Container>
 | |
| 		&& !std::is_same_v<Container, QByteArray>>>
 | |
| inline span make_span(Container &container) {
 | |
| 	return gsl::as_writeable_bytes(gsl::make_span(container));
 | |
| }
 | |
| 
 | |
| template <typename Container>
 | |
| inline const_span make_span(const Container &container) {
 | |
| 	return gsl::as_bytes(gsl::make_span(container));
 | |
| }
 | |
| 
 | |
| template <typename Type, std::ptrdiff_t Extent>
 | |
| inline span make_span(gsl::span<Type, Extent> container) {
 | |
| 	return gsl::as_writeable_bytes(container);
 | |
| }
 | |
| 
 | |
| template <typename Type, std::ptrdiff_t Extent>
 | |
| inline const_span make_span(gsl::span<const Type, Extent> container) {
 | |
| 	return gsl::as_bytes(container);
 | |
| }
 | |
| 
 | |
| template <typename Type>
 | |
| inline span make_span(Type *value, std::size_t count) {
 | |
| 	return gsl::as_writeable_bytes(gsl::make_span(value, count));
 | |
| }
 | |
| 
 | |
| template <typename Type>
 | |
| inline const_span make_span(const Type *value, std::size_t count) {
 | |
| 	return gsl::as_bytes(gsl::make_span(value, count));
 | |
| }
 | |
| 
 | |
| template <typename Type>
 | |
| inline span object_as_span(Type *value) {
 | |
| 	return bytes::make_span(value, 1);
 | |
| }
 | |
| 
 | |
| template <typename Type>
 | |
| inline const_span object_as_span(const Type *value) {
 | |
| 	return bytes::make_span(value, 1);
 | |
| }
 | |
| 
 | |
| template <typename Container>
 | |
| inline vector make_vector(const Container &container) {
 | |
| 	const auto buffer = bytes::make_span(container);
 | |
| 	return { buffer.begin(), buffer.end() };
 | |
| }
 | |
| 
 | |
| inline void copy(span destination, const_span source) {
 | |
| 	Expects(destination.size() >= source.size());
 | |
| 
 | |
| 	memcpy(destination.data(), source.data(), source.size());
 | |
| }
 | |
| 
 | |
| inline void move(span destination, const_span source) {
 | |
| 	Expects(destination.size() >= source.size());
 | |
| 
 | |
| 	memmove(destination.data(), source.data(), source.size());
 | |
| }
 | |
| 
 | |
| inline void set_with_const(span destination, type value) {
 | |
| 	memset(
 | |
| 		destination.data(),
 | |
| 		gsl::to_integer<unsigned char>(value),
 | |
| 		destination.size());
 | |
| }
 | |
| 
 | |
| inline int compare(const_span a, const_span b) {
 | |
| 	const auto aSize = a.size(), bSize = b.size();
 | |
| 	return (aSize > bSize)
 | |
| 		? 1
 | |
| 		: (aSize < bSize)
 | |
| 		? -1
 | |
| 		: memcmp(a.data(), b.data(), aSize);
 | |
| }
 | |
| 
 | |
| namespace details {
 | |
| 
 | |
| template <typename Arg>
 | |
| std::size_t spansLength(Arg &&arg) {
 | |
| 	return bytes::make_span(arg).size();
 | |
| }
 | |
| 
 | |
| template <typename Arg, typename ...Args>
 | |
| std::size_t spansLength(Arg &&arg, Args &&...args) {
 | |
| 	return bytes::make_span(arg).size() + spansLength(args...);
 | |
| }
 | |
| 
 | |
| template <typename Arg>
 | |
| void spansAppend(span destination, Arg &&arg) {
 | |
| 	bytes::copy(destination, bytes::make_span(arg));
 | |
| }
 | |
| 
 | |
| template <typename Arg, typename ...Args>
 | |
| void spansAppend(span destination, Arg &&arg, Args &&...args) {
 | |
| 	const auto data = bytes::make_span(arg);
 | |
| 	bytes::copy(destination, data);
 | |
| 	spansAppend(destination.subspan(data.size()), args...);
 | |
| }
 | |
| 
 | |
| } // namespace details
 | |
| 
 | |
| template <
 | |
| 	typename ...Args,
 | |
| 	typename = std::enable_if_t<(sizeof...(Args) > 1)>>
 | |
| vector concatenate(Args &&...args) {
 | |
| 	const auto size = details::spansLength(args...);
 | |
| 	auto result = vector(size);
 | |
| 	details::spansAppend(make_span(result), args...);
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| template <
 | |
| 	typename SpanRange>
 | |
| vector concatenate(SpanRange args) {
 | |
| 	auto size = std::size_t(0);
 | |
| 	for (const auto &arg : args) {
 | |
| 		size += bytes::make_span(arg).size();
 | |
| 	}
 | |
| 	auto result = vector(size);
 | |
| 	auto buffer = make_span(result);
 | |
| 	for (const auto &arg : args) {
 | |
| 		const auto part = bytes::make_span(arg);
 | |
| 		bytes::copy(buffer, part);
 | |
| 		buffer = buffer.subspan(part.size());
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| // Implemented in base/openssl_help.h
 | |
| void set_random(span destination);
 | |
| 
 | |
| } // namespace bytes
 | 
