#include <iostream> // For cout
#include <string> // For strings
#include <vector>
#include <cstdint>
#include <iomanip>
#include <random>
std::random_device rd;
std::mt19937 eng{rd()};
std::uniform_int_distribution<uint8_t> rng{0, 255};
void prettyprintbyte(uint8_t b)
{
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << unsigned(b) << " ";
std::cout << std::dec;
}
template <class UINT>
class VectorOfVectors
{
public:
VectorOfVectors() { m_data.push_back(std::vector<UINT>(0)); }
// print the values in a table format
void print()
{
for(std::vector<UINT> row: m_data)
{
for(UINT col: row)
{
prettyprintbyte(col);
}
std::cout << std::dec << std::endl;
}
}
// get the row count
unsigned int rowsize() { return m_data.size(); }
// get the col count
unsigned int colsize(unsigned int row)
{
if (row < m_data.size()) { return m_data[row].size(); }
return 0;
}
// get cell count
unsigned int size()
{
int cell_count = 0;
for(std::vector<UINT> row: m_data)
cell_count += row.size();
return cell_count;
}
// get cell value
int get(const unsigned int row, const unsigned int col) {
if (row < m_data.size())
{
if (col < m_data[row].size())
{
return m_data[row][col];
}
}
return -1;
}
// set cell value
unsigned int set(const unsigned int row, const unsigned int col, const UINT &value) {
if (row < m_data.size())
{
if (col < m_data[row].size())
{
m_data[row][col] = value;
return 0;
}
else
{
m_data[row].push_back(value);
return 0;
}
}
else
{
m_data.push_back(std::vector<UINT>{value});
return 0;
}
return 1;
}
// push new cell value to row
unsigned int push_back(const unsigned int row, const UINT &value)
{
if (row < m_data.size())
{
m_data[row].push_back(value);
return 0;
}
else
{
m_data.push_back(std::vector<UINT>{value});
return 0;
}
}
// row iterators object and getter
struct RowIter
{
typename std::vector<std::vector<UINT>>::iterator begin;
typename std::vector<std::vector<UINT>>::iterator end;
};
void get_row_iters(
RowIter &iterpair
)
{
iterpair.begin = m_data.begin();
iterpair.end = m_data.end();
}
// column iterators object and getter
struct ColIter
{
typename std::vector<UINT>::iterator begin;
typename std::vector<UINT>::iterator end;
};
void get_column_iters(
const typename std::vector<std::vector<UINT>>::iterator &rowiter,
ColIter &coliterpair
)
{
coliterpair.begin = (*rowiter).begin();
coliterpair.end = (*rowiter).end();
}
private:
std::vector<std::vector<UINT>> m_data;
};
int main(int argc, char *argv[]) {
using U8VectorOfVectors = VectorOfVectors<uint8_t>;
{
U8VectorOfVectors v2;
for (int c = 0; c < 4; c++) { v2.push_back(0, rng(eng)); }
for (int c = 0; c < 3; c++) { v2.push_back(1, rng(eng)); }
for (int c = 0; c < 2; c++) { v2.push_back(2, rng(eng)); }
for (int c = 0; c < 6; c++) { v2.push_back(3, rng(eng)); }
std::cout << "=======================" << std::endl;
v2.print();
std::cout << "=======================" << std::endl;
std::cout << "rows: " << v2.rowsize() << std::endl;
std::cout << "row[1] size: " << v2.colsize(1) << std::endl;
std::cout << "cells: " << v2.size() << std::endl;
std::cout << "[3][4] = ";
prettyprintbyte(v2.get(3, 4));
std::cout << std::endl << "[5][5] = "<< (v2.get(5, 5)) << std::endl;
U8VectorOfVectors::ColIter col_iters;
U8VectorOfVectors::RowIter row_iters;
// for(int i = 0; i < v2.rowsize(); i++)
v2.get_row_iters(row_iters);
for(auto rowit = row_iters.begin; rowit != row_iters.end; rowit++)
{
v2.get_column_iters(rowit, col_iters);
// get some useful index info for demo purposes
std::size_t rowpos = std::distance(row_iters.begin, rowit);
std::cout << "row[" << rowpos << "] iterator: ";
for(auto colit = col_iters.begin; colit != col_iters.end; colit++)
{
prettyprintbyte(*colit);
}
std::cout << std::endl;
}
}
return 0;
}
=======================
0xd4 0x6f 0x27 0x4e
0xb1 0x34 0x23
0x39 0x1e
0xa1 0xcd 0x5a 0x3c 0x57 0x70
=======================
rows: 4
row[1] size: 3
cells: 15
[3][4] = 0x57
[5][5] = -1
row[0] iterator: 0xd4 0x6f 0x27 0x4e
row[1] iterator: 0xb1 0x34 0x23
row[2] iterator: 0x39 0x1e
row[3] iterator: 0xa1 0xcd 0x5a 0x3c 0x57 0x70
https://godbolt.org/z/35nMYs9YG