Создание функции с использованием std::span вместо старого способа

#c #std #c 20

#c #std #c 20

Вопрос:

Я только что узнал, что могу использовать VS 2019 с C 20, и я пытаюсь его использовать. Я пытаюсь использовать следующую функцию std::span , потому что этот способ data_size и key_size был бы избыточным.

Все в порядке, кроме *data и data . Что это должно быть?

 int rc4(rc4_context* context, const std::uint8_t* data, const std::size_t data_size, const std::uint8_t* key, const std::size_t key_size, std::uint8_t* output)
{
    std::uint32_t i, j;

    // Check parameters
    if (!context || !key)
        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;
    }

    // Restore context
    i = context->i;
    j = context->j;
    auto* s = context->s;

    // Encryption loop
    for (size_t x = 0; x < data_size;   x)
    {
        // Adjust indices
        i = (i   1) % 256;
        j = (j   s[i]) % 256;

        // Swap the values of S[i] and S[j]
        const auto temp = s[i];
        s[i] = s[j];
        s[j] = temp;

        // Valid input and output?
        if (data amp;amp; output)
        {
            // XOR the input data with the RC4 stream
            *output = *data ^ s[(s[i]   s[j]) % 256];

            // Increment data pointers
            data  ;
            output  ;
        }
    }

    // Save context
    context->i = i;
    context->j = j;

    return NO_ERROR;
}
 

Моя попытка

 int rc4(rc4_context* context, const std::span<uint8_t*> data, const std::span<std::uint8_t*> key, 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 (size_t x = 0; x < data.size();   x)
    {
        // Adjust indices
        i = (i   1) % 256;
        j = (j   s[i]) % 256;

        // Swap the values of S[i] and S[j]
        const auto temp = s[i];
        s[i] = s[j];
        s[j] = temp;

        // Valid input and output?
        if (data.empty() amp;amp; output)
        {
            // XOR the input data with the RC4 stream
            *output = *data ^ s[(s[i]   s[j]) % 256];

            // Increment data pointers
            data  ;
            output  ;
        }
    }

    // Save context
    context->i = i;
    context->j = j;

    return NO_ERROR;
}
 

Комментарии:

1. std::span<uint8_t*> -> std::span<uint8_t> .

Ответ №1:

Во-первых, пара параметров (const std::uint8_t* data, const std::size_t data_size) может быть заменена на std::span<uint8_t> , not std::span<uint8_t*> .

Во-вторых, вам не нужно беспокоиться о приращении data , поскольку вы можете переписать это как цикл for на основе диапазона:

 for (uint8_t 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];
    }   
}
 

Комментарии:

1. @nop Вам не нужно создавать все аргументы заранее, вы можете просто передать массив и вектор непосредственно в вашу функцию : rc4(amp;context, log_data, key, result) . Это log_size не просто log_data.size() , похоже, что это не обязательно должен быть дополнительный вызов. const autoamp; result = new uint8_t[log_size]; очень подозрительно, либо оберните это, unique_ptr либо используйте a vector , чтобы управлять вашей памятью.

2. Only log_data не хочет передаваться напрямую. Cannot convert lvalue of type const std::vector<std::byte> to parameter type std::span<uint8_t> . Это функция read_log_file pastebin.com/2Vp6TL0M

3. @nop Просто измените его на a vector<uint8_t> ? Если вам нужно uint8_t , вам нужно uint8_t

4. Это может быть std::ranges::copy(data, output, [](std::uint8_t elem) { /* body of loop with return instead of assign */ });