This repository has been archived on 2024-06-01. You can view files and clone it, but cannot push or open issues or pull requests.
2017-11-13 09:41:53 +03:00

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;