Hi there,
The little example program shown here compiles and runs fine in GCC with C++14 language support enabled.
The objective of this program is to simulate the behavior of microcontroller memory. Instead of declaring a giant array for the entire address range of the microcontroller memory. I'd like to declare just what is needed. So the idea is this datastructure:
struct addr_range
{
uint8_t addr;
uint8_t size;
};
typedef std::vector< uint8_t > vector_t;
typedef std::map< addr_range, vector_t, std::less<> > map_t;
with an initialization like this:
map_t mem =
{
{ {0xC0, 3}, { 1, 2, 3 } },
{ {0xD0, 8}, { 7, 6, 5, 4, 3, 2, 1, 0 } },
{ {0xB0, 4}, { 0xA, 0xB, 0xC, 0xD } },
{ {0x66, 2}, { 0xC, 0xD } },
{ {0x6D, 2}, { 0xF, 0xE } },
{ {0x70, 2}, { 0x3, 0x4 } }
};
For now addresses and data values are just one byte. addr is the start address, size is the size to which data values are specified and the vector is just the data there. Obviously size should always be equal to the vector size.
With proper housekeeping I'll make sure that no address range will be overlapping another one. Also when a write occurs that will make an address range consecutive to another one I will assign the vector to the end of the vector in the lowest address and remove the vector in the higher address as well as the map entry. So for example a write to address 0x6F with the value 0x2 will have the memory look like:
map_t mem =
{
{ {0xC0, 3}, { 1, 2, 3 } },
{ {0xD0, 8}, { 7, 6, 5, 4, 3, 2, 1, 0 } },
{ {0xB0, 4}, { 0xA, 0xB, 0xC, 0xD } },
{ {0x66, 2}, { 0xC, 0xD } },
{ {0x6D, 5}, { 0xF, 0xE, 0x2, 0x3, 0x4 } }
};
Now for the C++ code. As you can see I have a bunch of operator< overloads. The last two can compare a single uint8_t to an address range. And these are used in the map::find function call. Notice that for map::find I only have an uint8_t argument. For insertion the full keys are being compared and that is done in the first operator< overload.
I not quite sure if it is ok to have different compare function objects depending on which member function of map is called. Do you know if that is fine? Comments and caveats on this code? How would you program something like this?
#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <vector>
#include <map>
struct addr_range
{
uint8_t addr;
uint8_t size;
};
typedef std::vector< uint8_t > vector_t;
typedef std::map< addr_range, vector_t, std::less<> > map_t;
bool operator<( const addr_range& a, const addr_range& b ){
//printf( "try %2.2X < %2.2X: %u\n", a.addr, b.addr, a.addr < b.addr );
return a.addr < b.addr;
}
bool operator<( const addr_range& a, const uint8_t& b )
{
bool result = (a.addr + a.size - 1) < b;
//printf( "1 try %2.2X+%2.2X=%2.2X < %2.2X: %u\n",
// a.addr, a.size - 1, (a.addr + a.size - 1), b, result );
return result;
}
bool operator<( const uint8_t& a, const addr_range& b )
{
bool result = a < b.addr;
//printf( "2 try %2.2X < %2.2X: %u\n", a, b.addr, result );
return result;
}
int main()
{
map_t mem =
{
{ {0xC0, 3}, { 1, 2, 3 } },
{ {0xD0, 8}, { 7, 6, 5, 4, 3, 2, 1, 0 } },
{ {0xB0, 4}, { 0xA, 0xB, 0xC, 0xD } },
{ {0x66, 2}, { 0xC, 0xD } },
{ {0x6D, 2}, { 0xF, 0xE } },
{ {0x70, 2}, { 0x3, 0x4 } }
};
mem.insert( {{0xCC, 1}, {8}} );
uint8_t i = 0;
next_lookup:
auto search = mem.find( i );
if ( search != mem.end() )
{
uint8_t pos = i - search->first.addr;
printf( "%2.2X: %2.2X\n", i, search->second[pos] );
}
if ( i == 255 ) { goto quit_loop; }
i++;
goto next_lookup;
quit_loop:
getchar();
return 0;
}
Regards, Zeyneb