从动态数组迁移到 unique_ptr 但无法转换为 std::span
Migrating to unique_ptr from a dynamic array and failing to convert to std::span
我正在尝试加密和解密一个文件,基本上是在练习 std::span
和 std::unique_ptr
。这些问题在代码中进行了评论。
-
rc4
的第二个参数是 std::span
但我的参数是 vector<uint8_t>
用于加密,unique_ptr<uint8_t>
用于解密,我无法转换为。
*output++ = elem ^ s[(s[i] + s[j]) % 256];
不能用 unique_ptr 完成。
const auto log_data = read_log_file(log_path);
const auto log_size = static_cast<std::size_t>(std::filesystem::file_size(log_path));
// Generate a random key
std::uint8_t key[32];
generate_random_key(key);
// Encrypt
const auto result = std::make_unique<std::uint8_t>(log_size);
rc4_context context{};
rc4(&context, log_data, key, std::move(result)); // TODO: log_data: Cannot convert lvalue of type const std::vector<uint8_t> to parameter type const std::span<uint8_t>
// Decrypt
const auto result2 = std::make_unique<std::uint8_t>(log_size);
rc4(&context, std::move(result), key, std::move(result2)); // TODO: Again the second parameter cannot be casted from unique_ptr<unsigned char> to span<uint8_t>
std::vector<std::uint8_t> read_log_file(const std::wstring& path)
{
std::ifstream ifs(path, std::ios::binary | std::ios::ate);
if (!ifs)
throw std::runtime_error("Could not load file.");
const auto end = ifs.tellg();
ifs.seekg(0, std::ios::beg);
const auto size = static_cast<std::size_t>(end - ifs.tellg());
if (size == 0)
return {};
std::vector<std::uint8_t> buffer(size);
if (!ifs.read(reinterpret_cast<char*>(buffer.data()), buffer.size()))
throw std::runtime_error("Could not read file.");
return buffer;
}
int rc4(rc4_context* context, const std::span<std::uint8_t>& data, const std::span<std::uint8_t>& key, const std::unique_ptr<std::uint8_t>& output)
{
// INITIALIZATION
std::uint32_t i, j;
// Check parameters
if (!context || !key.empty())
return ERROR_INVALID_PARAMETER;
// Clear context
context->i = 0;
context->j = 0;
// Initialize the S array with identity permutation
for (i = 0; i < 256; i++)
{
context->s[i] = static_cast<std::uint8_t>(i);
}
// S is then processed for 256 iterations
for (i = 0, j = 0; i < 256; i++)
{
// Randomize the permutations using the supplied key
j = (j + context->s[i] + key[i % key.size()]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
// MAIN LOGIC PART
// Restore context
i = context->i;
j = context->j;
auto* s = context->s;
// Encryption loop
for (auto elem : data)
{
// Adjust indices
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// Swap the values of S[i] and S[j]
std::swap(s[i], s[j]);
// Valid output?
if (output)
{
// XOR the input data with the RC4 stream
*output++ = elem ^ s[(s[i] + s[j]) % 256]; // TODO: error happens here, because of *output++
}
}
// Save context
context->i = i;
context->j = j;
return NO_ERROR;
}
我也建议将 std::vector<uint8_t>
用于 result
,但这里是修复现有代码的方法。我在回答中将重点放在了问题上。
#include <cstdint>
#include <iostream>
#include <memory>
#include <span>
#include <vector>
// rc4's span should be over const uint8_t's:
void rc4(const std::span<const std::uint8_t>& data) {
std::cout << data.size() << '\n';
}
int main() {
size_t log_size = 100;
const std::vector<uint8_t> log_data{1, 2, 3}; // ... since this is const
rc4(log_data);
// you should allocate an array, not a single uint8_t here:
const auto result = std::make_unique<std::uint8_t[]>(log_size);
// and you can create the span like this in your argument list:
rc4( {result.get(), log_size} );
}
输出:
3
100
输入和输出都使用 vector
s 的替代方法:
#include <cstdint>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
int rc4(const std::vector<std::uint8_t>& data,
std::vector<std::uint8_t>& output)
{
output.clear();
output.reserve(data.size());
for(auto byte : data) {
output.push_back(0xFF - byte); // a simple algoritm
}
return 0; // NO_ERROR;
}
int main() {
const std::vector<uint8_t> log_data{'A', 'B', 'C'};
std::vector<std::uint8_t> result;
rc4(log_data, result); // encrypt
for(auto byte : result) {
std::cout << std::hex << (int)byte << '\n'; // probably be, bd, bc
}
std::cout << '\n';
std::vector<std::uint8_t> result2;
rc4(result, result2); // decrypt
for(auto byte : result2) {
std::cout << byte; // prints ABC
}
std::cout << '\n';
}
我正在尝试加密和解密一个文件,基本上是在练习 std::span
和 std::unique_ptr
。这些问题在代码中进行了评论。
-
rc4
的第二个参数是std::span
但我的参数是vector<uint8_t>
用于加密,unique_ptr<uint8_t>
用于解密,我无法转换为。 *output++ = elem ^ s[(s[i] + s[j]) % 256];
不能用 unique_ptr 完成。
const auto log_data = read_log_file(log_path);
const auto log_size = static_cast<std::size_t>(std::filesystem::file_size(log_path));
// Generate a random key
std::uint8_t key[32];
generate_random_key(key);
// Encrypt
const auto result = std::make_unique<std::uint8_t>(log_size);
rc4_context context{};
rc4(&context, log_data, key, std::move(result)); // TODO: log_data: Cannot convert lvalue of type const std::vector<uint8_t> to parameter type const std::span<uint8_t>
// Decrypt
const auto result2 = std::make_unique<std::uint8_t>(log_size);
rc4(&context, std::move(result), key, std::move(result2)); // TODO: Again the second parameter cannot be casted from unique_ptr<unsigned char> to span<uint8_t>
std::vector<std::uint8_t> read_log_file(const std::wstring& path)
{
std::ifstream ifs(path, std::ios::binary | std::ios::ate);
if (!ifs)
throw std::runtime_error("Could not load file.");
const auto end = ifs.tellg();
ifs.seekg(0, std::ios::beg);
const auto size = static_cast<std::size_t>(end - ifs.tellg());
if (size == 0)
return {};
std::vector<std::uint8_t> buffer(size);
if (!ifs.read(reinterpret_cast<char*>(buffer.data()), buffer.size()))
throw std::runtime_error("Could not read file.");
return buffer;
}
int rc4(rc4_context* context, const std::span<std::uint8_t>& data, const std::span<std::uint8_t>& key, const std::unique_ptr<std::uint8_t>& output)
{
// INITIALIZATION
std::uint32_t i, j;
// Check parameters
if (!context || !key.empty())
return ERROR_INVALID_PARAMETER;
// Clear context
context->i = 0;
context->j = 0;
// Initialize the S array with identity permutation
for (i = 0; i < 256; i++)
{
context->s[i] = static_cast<std::uint8_t>(i);
}
// S is then processed for 256 iterations
for (i = 0, j = 0; i < 256; i++)
{
// Randomize the permutations using the supplied key
j = (j + context->s[i] + key[i % key.size()]) % 256;
// Swap the values of S[i] and S[j]
const auto temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
// MAIN LOGIC PART
// Restore context
i = context->i;
j = context->j;
auto* s = context->s;
// Encryption loop
for (auto elem : data)
{
// Adjust indices
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// Swap the values of S[i] and S[j]
std::swap(s[i], s[j]);
// Valid output?
if (output)
{
// XOR the input data with the RC4 stream
*output++ = elem ^ s[(s[i] + s[j]) % 256]; // TODO: error happens here, because of *output++
}
}
// Save context
context->i = i;
context->j = j;
return NO_ERROR;
}
我也建议将 std::vector<uint8_t>
用于 result
,但这里是修复现有代码的方法。我在回答中将重点放在了问题上。
#include <cstdint>
#include <iostream>
#include <memory>
#include <span>
#include <vector>
// rc4's span should be over const uint8_t's:
void rc4(const std::span<const std::uint8_t>& data) {
std::cout << data.size() << '\n';
}
int main() {
size_t log_size = 100;
const std::vector<uint8_t> log_data{1, 2, 3}; // ... since this is const
rc4(log_data);
// you should allocate an array, not a single uint8_t here:
const auto result = std::make_unique<std::uint8_t[]>(log_size);
// and you can create the span like this in your argument list:
rc4( {result.get(), log_size} );
}
输出:
3
100
输入和输出都使用 vector
s 的替代方法:
#include <cstdint>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
int rc4(const std::vector<std::uint8_t>& data,
std::vector<std::uint8_t>& output)
{
output.clear();
output.reserve(data.size());
for(auto byte : data) {
output.push_back(0xFF - byte); // a simple algoritm
}
return 0; // NO_ERROR;
}
int main() {
const std::vector<uint8_t> log_data{'A', 'B', 'C'};
std::vector<std::uint8_t> result;
rc4(log_data, result); // encrypt
for(auto byte : result) {
std::cout << std::hex << (int)byte << '\n'; // probably be, bd, bc
}
std::cout << '\n';
std::vector<std::uint8_t> result2;
rc4(result, result2); // decrypt
for(auto byte : result2) {
std::cout << byte; // prints ABC
}
std::cout << '\n';
}