Как инкапсулировать передачу байтов между двумя контейнерами - PullRequest
1 голос
/ 16 мая 2019

У меня есть два независимых класса, каждый из которых поддерживает буфер ограниченного размера:

class A {
private:
    std::deque<uint8_t> buffer;
    size_t max_size;
};

class B {
private:
    static const size_t MAX_SIZE = 1024;
    uint8_t buffer[MAX_SIZE];
}

Теперь у меня также есть функция C, которая не является членом A или B. Эта функция должна принимать(т.е. удалить) как можно больше байтов из начала из A и записать его в B. Ofc переполнение буфера не допускается.

Вопрос: Как я могу сделать это эффективно, гарантируя, что Aи Б инкапсулированы?Т.е. A, B и C не знают, как реализованы другие.

Вещи, которые я не хочу, по понятным причинам:

  • A выставляетОткрытый метод, который возвращает неконстантный итератор в deque
  • B, предоставляет открытый метод, который возвращает неконстантный указатель на массив

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

Мимические стандартные контейнеры. Используйте begin и end. Это минимальный интерфейс, который я вижу для вашего случая использования:

class A {
private:
    std::deque<uint8_t> buffer_;
    size_t max_size_;

public:
    using const_iterator = decltype(buffer_)::const_iterator;

    auto begin() const -> const_iterator { return buffer_.begin(); }
    auto end() const -> const_iterator { return buffer_.end(); }
};

class B {
private:
    static const size_t MAX_SIZE = 1024;
    std::array<uint8_t, MAX_SIZE> buffer_;

public:

    /// fills the buffer with elements in [first, last)
    /// excessive elements are ignored
    /// returns the number of successfully filled elements

    template <class It>
    auto fill_as_much_as_possible(It first, It last) -> std::size_t
    {
        auto in_size = std::distance(first, last);
        if (in_size > static_cast<decltype(in_size)>(MAX_SIZE))
        {
            last = first;
            std::advance(last, MAX_SIZE);
        }

        auto out_last = std::copy(first, last, buffer_.begin());

        return std::distance(buffer_.begin(), out_last);
    }
};

auto foo(const A& a, B& b)
{
    b.fill_as_much_as_possible(a.begin(), a.end());
}
2 голосов
/ 16 мая 2019

class A возвращает итератор const с помощью нового открытого метода.class B предоставляет метод для копирования этих байтов.

class A {
public:
    const std::deque<uint8_t>& getBuffer() const
    {
        return buffer;
    }
private:
    std::deque<uint8_t> buffer;
    size_t max_size;
    size_t current_size;
};

class B {
public:
    B() : max_size(MAX_SIZE), current_size(0)
    {
    }
    void Transfer(const std::deque<uint8_t>& data)
    {
        size_t remaining = max_size - current_size;
        size_t toCopy = data.size() > remaining  ? remaining : data.size();
        for (size_t i = 0; i < toCopy; i++)
        {
            buffer[i+current_size] = data[i];
        }
        current_size += toCopy;
    }
private:
    static const size_t MAX_SIZE = 1024;
    uint8_t buffer[MAX_SIZE];
};


CopyAToB(const A& a, B& b)
{
    b.Transfer(a.getBuffer());
}
...