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

问题描述 投票:2回答:2

我尝试实现基于地址(值)的数据访问。我有一个地址范围从0x0000 - 0xFFFF和不同的数据访问功能取决于地址。

到目前为止,我使用了一个switch case实现,它根据给定的地址选择了正确的函数。现在,我正在寻找一种新的解决方案,使用Map。这个想法是,密钥是一个包含起始值和结束值的对象(产生一个地址范围)。映射条目是一个函数指针,当地址在范围内时应该调用它。

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

不幸的是,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));
}
};
c++
2个回答
1
投票

首先,您需要处理重叠范围。我想你已经这样做了。

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

你的选择:

  1. 使用固定的0x10000元素数组作为查找表。添加新范围时,将所有相应的条目设置为给定的函数指针。您可以获得恒定的时间查询,但需要使用额外的内存,插入时间与范围大小成正比。
  2. 如上所述,但使用哈希表(std::unordered_map)。
  3. 使用成对的RegAdr和函数指针的容器,例如std::vector<std::pair<RegAdr, func_ptr>>。插入很简单。在寻址时,迭代容器并检查给定地址是否在范围内。您获得(摊销)恒定时间插入,并以与范围数量成比例的查找时间为代价最小化内存使用。

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的提示!

© www.soinside.com 2019 - 2024. All rights reserved.