moudi
moudi

Reputation: 518

C++11 map with keys define a value range

I try to implement an address (value) based data access. I have a address range from 0x0000 - 0xFFFF and different functions for data access dependent on the address.

Until now, I used a switch case implementation which does select the correct function based on the given address. Now, I'm looking for a new solution, by using a Map. The idea is, that the key is a object including a start and an end value (resulting in a address range). The map entry is a function pointer which should be called when a address is in the range.

To find the correct function pointer, I would use the find method with a single value (address). For that I implemented also the operator<.

Unfortunately the find function doesn't find any entry in the Map. Does any one see a possible issue? Or may has a better idea to solve my issue?

struct RegAdr {
uint32_t start;
uint32_t end;

RegAdr() = delete;
RegAdr(uint32_t value);
RegAdr(uint32_t start, uint32_t end);

bool operator<(const RegAdr& rhs) const {
    return this->end < rhs.end;
}
bool operator>(const RegAdr& rhs) const {
    return rhs < *this;
}
bool operator<=(const RegAdr& rhs) const {
    return !(*this > rhs);
}
bool operator>=(const RegAdr& rhs) const {
    return !(*this < rhs);
}
bool operator==(const RegAdr& rhs) const {
    return (this->start <= rhs.start && this->end >= rhs.start);
}
bool operator!=(const RegAdr& rhs) const {
    return !(*this == rhs);
}
bool operator()(const RegAdr& rhs) const {
    return !((this->end < rhs.start) || (rhs.end < this->start));
}
};

Upvotes: 3

Views: 505

Answers (2)

moudi
moudi

Reputation: 518

Based on the Options given by @Krzysiek Karbowiak i implemented a vector based solution. For anyone which is interest on the solution, i add some code snipped:

Vector definition and initialization:

typedef int (DataRead::*readPtr)(const uint32_t address, void* buffer, uint32_t* bufSize);
std::map<RegAdr, readPtr> readMap;
std::vector<std::pair<RegAdr, readPtr>> readVector;

RegAdr localMemory(0x0000,0x0255);
readVector.push_back(std::make_pair(localMemory, &DataRead::readLocalMemory));

RegAdr libraryMemory(0x1000,0x1255);
readVector.push_back(std::make_pair(libraryMemory, &DataRead::readLibraryMemory));

Function for address based data access:

int DataRead::readMemory(const uint32_t address, void* buffer, uint32_t* bufSize) {
  int ret = -42;

  for (auto element : readVector) {
    uint32_t elementStart = element.first.start;
    uint32_t elementEnd = element.first.end;

    if (elementStart <= address && address <= elementEnd) {
        // address in range
        auto rfp = element.second;
        ret = (this->*rfp)(address, buffer, bufSize);
        break;
    }
  }
  if (ret == -42) {
    char cMsg[] = "Mover Thread read failed! Address not found!";
    std::vector<uint8_t> vMsg(cMsg, cMsg + sizeof(cMsg));
    sharedData->threadData->setStream(Addr::MOVER_LAST_ERROR, vMsg);
  }
  if (ret < 0) {
    // error message should be written in function call...
    bufSize = 0;
    return -1;
  }
  return 0;
}

Thanks to anyone and specially to Krzysiek Karbowiak for the hints!

Upvotes: 0

Krzysiek Karbowiak
Krzysiek Karbowiak

Reputation: 1954

First of all, you need to take care of overlapping ranges. I suppose you already do that.

Since the range of the allowed values is fixed (and not that big), the solution may be quite simple.

Your options:

  1. Use a fixed array of 0x10000 elements as a lookup table. When a new range is added, set all corresponding entries to given function pointer. You get constant time lookup at the cost of additional memory used and insertion time proportional to range size.

  2. As above, but use a hash table (std::unordered_map).

  3. Use a container of pairs of RegAdr and function pointer, e.g. std::vector<std::pair<RegAdr, func_ptr>>. Inserting is straightforward. When addressing you iterate over the container and check whether given address is in the range. You get (amortised) constant time insertion and you minimise memory usage at the cost of lookup time proportional to number of ranges.

Upvotes: 1

Related Questions