带有键的C ++ 11映射定义了一个值范围

时间:2019-03-04 15:15:36

标签: c++

我尝试实现基于地址(值)的数据访问。我的地址范围是0x0000-0xFFFF,并且根据地址不同,数据访问的功能也不同。

直到现在,我使用了一个开关盒实现,它确实根据给定的地址选择了正确的功能。 现在,我正在通过使用地图寻找新的解决方案。这个想法是,键是一个包含开始值和结束值(在地址范围内)的对象。映射条目是一个函数指针,当地址在范围内时应调用该指针。

要找到正确的函数指针,我将使用具有单个值(地址)的find方法。为此,我还实现了operator <。

不幸的是,find函数在Map中找不到任何条目。有没有人看到可能的问题?还是有更好的主意来解决我的问题?

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));
}
};

2 个答案:

答案 0 :(得分:1)

首先,您需要注意重叠范围。我想你已经做到了。

由于允许值的范围是固定的(并且不是那么大),所以解决方案可能非常简单。

您的选择:

  1. 使用0x10000元素的固定数组作为查找表。添加新范围后,将所有相应条目设置为给定的函数指针。您可以获得恒定的时间查找,但要花费额外的内存,插入时间与范围大小成正比。

  2. 如上所述,但是使用哈希表(std::unordered_map)。

  3. 使用一对RegAdr和函数指针组成的容器,例如std::vector<std::pair<RegAdr, func_ptr>>。插入很简单。在寻址时,请遍历容器并检查给定的地址是否在范围内。您可以获得(摊销的)固定时间插入,并且以与范围数成正比的查找时间为代价,将内存使用降至最低。

答案 1 :(得分:0)

基于@Krzysiek Karbowiak给出的选项,我实现了基于矢量的解决方案。对于对该解决方案感兴趣的任何人,我都会添加一些代码片段:

向量定义和初始化:

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));

用于基于地址的数据访问的功能:

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;
}

感谢所有人,尤其是Krzysiek Karbowiak的提示!