140 lines
3.0 KiB
C++
140 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include <unordered_map>
|
|
//#include <cstring>
|
|
#include <string.h>
|
|
#include <memory>
|
|
#include "logging.hpp"
|
|
|
|
// this and the cpp are creds to "Altimor"
|
|
|
|
class RecvTable;
|
|
class RecvProp;
|
|
|
|
class equal_char {
|
|
public:
|
|
bool operator() (const char* const& v1, const char* const& v2) const {
|
|
return !strcmp(v1, v2);
|
|
}
|
|
};
|
|
|
|
struct hash_char {
|
|
public:
|
|
size_t operator()(const char* obj) const {
|
|
size_t res = 0;
|
|
const size_t prime = 31;
|
|
for (size_t i = 0; i < strlen(obj); ++i) {
|
|
res = obj[i] + (res * prime);
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
|
|
class netvar_tree
|
|
{
|
|
struct node;
|
|
using map_type = std::unordered_map<const char*, std::shared_ptr<node>, hash_char, equal_char>;
|
|
|
|
struct node
|
|
{
|
|
node(int offset, RecvProp *p) : offset(offset), prop(p) {}
|
|
|
|
map_type nodes;
|
|
int offset;
|
|
RecvProp *prop;
|
|
};
|
|
|
|
map_type nodes;
|
|
|
|
public:
|
|
//netvar_tree ( );
|
|
|
|
void init();
|
|
|
|
private:
|
|
void populate_nodes(class RecvTable *recv_table, map_type *map);
|
|
|
|
/**
|
|
* get_offset_recursive - Return the offset of the final node
|
|
* @map: Node map to scan
|
|
* @acc: Offset accumulator
|
|
* @name: Netvar name to search for
|
|
*
|
|
* Get the offset of the last netvar from map and return the sum of it and accum
|
|
*/
|
|
int get_offset_recursive(map_type &map, int acc, const char *name)
|
|
{
|
|
if (!map.count(name)) {
|
|
logging::Info("can't find %s!", name);
|
|
return 0;
|
|
}
|
|
return acc + map[name]->offset;
|
|
}
|
|
|
|
/**
|
|
* get_offset_recursive - Recursively grab an offset from the tree
|
|
* @map: Node map to scan
|
|
* @acc: Offset accumulator
|
|
* @name: Netvar name to search for
|
|
* @args: Remaining netvar names
|
|
*
|
|
* Perform tail recursion with the nodes of the specified branch of the tree passed for map
|
|
* and the offset of that branch added to acc
|
|
*/
|
|
template <typename... args_t>
|
|
int get_offset_recursive(map_type &map, int acc, const char *name, args_t... args)
|
|
{
|
|
if (!map.count(name)) {
|
|
logging::Info("can't find %s!", name);
|
|
return 0;
|
|
}
|
|
const auto &node = map[name];
|
|
return get_offset_recursive(node->nodes, acc + node->offset, args...);
|
|
}
|
|
|
|
|
|
RecvProp *get_prop_recursive(map_type &map, const char *name)
|
|
{
|
|
return map[name]->prop;
|
|
}
|
|
|
|
template<typename... args_t>
|
|
RecvProp *get_prop_recursive(map_type &map, const char *name, args_t... args)
|
|
{
|
|
const auto &node = map[name];
|
|
return get_prop_recursive(node->nodes, args...);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* get_offset - Get the offset of a netvar given a list of branch names
|
|
* @name: Top level datatable name
|
|
* @args: Remaining netvar names
|
|
*
|
|
* Initiate a recursive search down the branch corresponding to the specified datable name
|
|
*/
|
|
template <typename... args_t>
|
|
int get_offset(const char *name, args_t... args)
|
|
{
|
|
const auto &node = nodes[name];
|
|
if (node == 0) {
|
|
logging::Info("Invalid NetVar node: %s", name);
|
|
return 0;
|
|
}
|
|
int offset = get_offset_recursive(node->nodes, node->offset, args...);
|
|
return offset;
|
|
}
|
|
|
|
template<typename... args_t>
|
|
RecvProp *get_prop(const char *name, args_t... args)
|
|
{
|
|
const auto &node = nodes[name];
|
|
return get_prop_recursive(node->nodes, args...);
|
|
}
|
|
|
|
|
|
void dump();
|
|
};
|
|
|
|
extern netvar_tree gNetvars;
|