我尝试实现基于地址(值)的数据访问。我有一个地址范围从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));
}
};
首先,您需要处理重叠范围。我想你已经这样做了。
由于允许值的范围是固定的(而不是那么大),因此解决方案可能非常简单。
你的选择:
std::unordered_map
)。RegAdr
和函数指针的容器,例如std::vector<std::pair<RegAdr, func_ptr>>
。插入很简单。在寻址时,迭代容器并检查给定地址是否在范围内。您获得(摊销)恒定时间插入,并以与范围数量成比例的查找时间为代价最小化内存使用。根据@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的提示!