ROC profiler prototype sources importing
Αυτή η υποβολή περιλαμβάνεται σε:
@@ -0,0 +1,279 @@
|
||||
#ifndef _SRC_XML_EXPR_H
|
||||
#define _SRC_XML_EXPR_H
|
||||
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
namespace xml {
|
||||
class exception_t : public std::exception {
|
||||
public:
|
||||
explicit exception_t(const std::string& msg) : str_(msg) {}
|
||||
const char* what() const throw() { return str_.c_str(); }
|
||||
protected:
|
||||
const std::string str_;
|
||||
};
|
||||
|
||||
typedef uint64_t args_t;
|
||||
typedef std::map<std::string, args_t> args_map_t;
|
||||
class Expr;
|
||||
|
||||
template <class T>
|
||||
class any_cache_t {
|
||||
public:
|
||||
virtual ~any_cache_t() {}
|
||||
virtual bool Lookup(const std::string& name, T& result) const = 0;
|
||||
};
|
||||
|
||||
typedef any_cache_t<std::string> expr_cache_t;
|
||||
typedef any_cache_t<args_t> args_cache_t;
|
||||
|
||||
class bin_expr_t {
|
||||
public:
|
||||
static const bin_expr_t* CreateExpr(const bin_expr_t* arg1, const bin_expr_t* arg2, const char op);
|
||||
static const bin_expr_t* CreateArg(Expr *obj, const std::string str);
|
||||
|
||||
bin_expr_t() : arg1_(NULL), arg2_(NULL) {}
|
||||
bin_expr_t(const bin_expr_t* arg1, const bin_expr_t* arg2) : arg1_(arg1), arg2_(arg2) {}
|
||||
|
||||
virtual args_t Eval(const args_cache_t& args) const = 0;
|
||||
virtual std::string Symbol() const = 0;
|
||||
|
||||
std::string String() const {
|
||||
std::string str;
|
||||
if (arg1_) { str = "(" + arg1_->String() + " " + Symbol() + " " + arg2_->String() + ")"; }
|
||||
else str = Symbol();
|
||||
return str;
|
||||
}
|
||||
|
||||
protected:
|
||||
const bin_expr_t* arg1_;
|
||||
const bin_expr_t* arg2_;
|
||||
};
|
||||
|
||||
class Expr {
|
||||
public:
|
||||
explicit Expr(const std::string& expr, const expr_cache_t* cache) :
|
||||
expr_(expr),
|
||||
pos_(0),
|
||||
sub_count_(0),
|
||||
cache_(cache)
|
||||
{
|
||||
sub_vec_ = new std::vector<const Expr*>;
|
||||
var_vec_ = new std::vector<std::string>;
|
||||
tree_ = ParseExpr();
|
||||
}
|
||||
|
||||
explicit Expr(const std::string& expr, const Expr* obj) :
|
||||
expr_(expr),
|
||||
pos_(0),
|
||||
sub_count_(0),
|
||||
cache_(obj->cache_),
|
||||
sub_vec_(obj->sub_vec_),
|
||||
var_vec_(obj->var_vec_)
|
||||
{
|
||||
sub_vec_->push_back(this);
|
||||
tree_ = ParseExpr();
|
||||
if (!SubCheck()) throw exception_t("expr '" + expr_ + "', bad parenthesis count");
|
||||
}
|
||||
|
||||
~Expr() {
|
||||
delete cache_;
|
||||
for (auto it : *sub_vec_) delete it;
|
||||
delete sub_vec_;
|
||||
delete var_vec_;
|
||||
}
|
||||
|
||||
std::string GetStr() const { return expr_; }
|
||||
const expr_cache_t* GetCache() const { return cache_; }
|
||||
const bin_expr_t* GetTree() const { return tree_; }
|
||||
|
||||
args_t Eval(const args_cache_t& args) const { return tree_->Eval(args); }
|
||||
|
||||
std::string Lookup(const std::string& str) const {
|
||||
std::string result;
|
||||
if (cache_ && !(cache_->Lookup(str, result))) throw exception_t("expr '" + expr_ + "', lookup '" + str + "' failed");
|
||||
return result;
|
||||
}
|
||||
|
||||
void AddVar(const std::string& str) {
|
||||
bool found = false;
|
||||
for (std::string s : *var_vec_) if (s == str) found = true;
|
||||
if (!found) var_vec_->push_back(str);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& GetVars() const { return *var_vec_; }
|
||||
|
||||
std::string String() const { return tree_->String(); }
|
||||
|
||||
private:
|
||||
const bin_expr_t* ParseExpr() {
|
||||
const bin_expr_t* expr = ParseArg();
|
||||
while (!IsEnd()) {
|
||||
const char op = Symb();
|
||||
const bin_expr_t* second_arg = NULL;
|
||||
if (IsSymb(')')) {
|
||||
Next();
|
||||
SubClose();
|
||||
break;
|
||||
} if (IsSymb('*') || IsSymb('/')) {
|
||||
Next();
|
||||
second_arg = ParseArg();
|
||||
expr = bin_expr_t::CreateExpr(expr, second_arg, op);
|
||||
} else if (IsSymb('+') || IsSymb('-')) {
|
||||
Next();
|
||||
second_arg = ParseExpr();
|
||||
expr = bin_expr_t::CreateExpr(expr, second_arg, op);
|
||||
break;
|
||||
} else {
|
||||
throw exception_t("expr '" + expr_ + "', bad operator '" + op + "'");
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
const bin_expr_t* ParseArg() {
|
||||
const bin_expr_t* arg = NULL;
|
||||
if (IsSymb('(')) {
|
||||
Next();
|
||||
SubOpen();
|
||||
arg = ParseExpr();
|
||||
} else {
|
||||
const unsigned pos = FindOp();
|
||||
const std::string str = CutTill(pos);
|
||||
arg = bin_expr_t::CreateArg(this, str);
|
||||
if (arg == NULL) throw exception_t("expr '" + expr_ + "', bad argument '" + str + "'");
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
char Symb() const { return Symb(pos_); }
|
||||
char Symb(const unsigned ind) const { return expr_[ind]; }
|
||||
bool IsEnd() const { return (pos_ >= expr_.length()); }
|
||||
bool IsSymb(const char c) const { return IsSymb(pos_, c); }
|
||||
bool IsSymb(const unsigned ind, const char c) const { return (expr_[ind] == c); }
|
||||
void Next() { ++pos_; }
|
||||
void SubOpen() { ++sub_count_; }
|
||||
void SubClose() { --sub_count_; }
|
||||
bool SubCheck() const { return (sub_count_ == 0); }
|
||||
unsigned FindOp() const {
|
||||
unsigned i = pos_;
|
||||
while (i < expr_.length()) {
|
||||
switch (Symb(i)) {
|
||||
case '*':
|
||||
case '/':
|
||||
case '+':
|
||||
case '-':
|
||||
case '(':
|
||||
case ')':
|
||||
goto end;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
end:
|
||||
return i;
|
||||
}
|
||||
std::string CutTill(const unsigned pos) {
|
||||
const std::string str = (pos > pos_) ? expr_.substr(pos_, pos - pos_) : "";
|
||||
pos_ = pos;
|
||||
return str;
|
||||
}
|
||||
|
||||
const std::string expr_;
|
||||
unsigned pos_;
|
||||
unsigned sub_count_;
|
||||
const bin_expr_t* tree_;
|
||||
const expr_cache_t* const cache_;
|
||||
std::vector<const Expr*>* sub_vec_;
|
||||
std::vector<std::string>* var_vec_;
|
||||
};
|
||||
|
||||
class add_expr_t : public bin_expr_t {
|
||||
public:
|
||||
add_expr_t(const bin_expr_t* arg1, const bin_expr_t* arg2) : bin_expr_t(arg1, arg2) {}
|
||||
args_t Eval(const args_cache_t& args) const { return (arg1_->Eval(args) + arg2_->Eval(args)); }
|
||||
std::string Symbol() const { return "+"; }
|
||||
};
|
||||
class sub_expr_t : public bin_expr_t {
|
||||
public:
|
||||
sub_expr_t(const bin_expr_t* arg1, const bin_expr_t* arg2) : bin_expr_t(arg1, arg2) {}
|
||||
args_t Eval(const args_cache_t& args) const { return (arg1_->Eval(args) - arg2_->Eval(args)); }
|
||||
std::string Symbol() const { return "-"; }
|
||||
};
|
||||
class mul_expr_t : public bin_expr_t {
|
||||
public:
|
||||
mul_expr_t(const bin_expr_t* arg1, const bin_expr_t* arg2) : bin_expr_t(arg1, arg2) {}
|
||||
args_t Eval(const args_cache_t& args) const { return (arg1_->Eval(args) * arg2_->Eval(args)); }
|
||||
std::string Symbol() const { return "*"; }
|
||||
};
|
||||
class div_expr_t : public bin_expr_t {
|
||||
public:
|
||||
div_expr_t(const bin_expr_t* arg1, const bin_expr_t* arg2) : bin_expr_t(arg1, arg2) {}
|
||||
args_t Eval(const args_cache_t& args) const { return (arg1_->Eval(args) / arg2_->Eval(args)); }
|
||||
std::string Symbol() const { return "/"; }
|
||||
};
|
||||
class const_expr_t : public bin_expr_t {
|
||||
public:
|
||||
const_expr_t(const args_t value) : value_(value) {}
|
||||
args_t Eval(const args_cache_t&) const { return value_; }
|
||||
std::string Symbol() const { std::ostringstream os; os << value_; return os.str(); }
|
||||
private:
|
||||
const args_t value_;
|
||||
};
|
||||
class var_expr_t : public bin_expr_t {
|
||||
public:
|
||||
var_expr_t(const std::string name) : name_(name) {}
|
||||
args_t Eval(const args_cache_t& args) const {
|
||||
args_t result = 0;
|
||||
if (!args.Lookup(name_, result)) throw exception_t("expr arg lookup '" + name_ + "' failed");
|
||||
return result;
|
||||
}
|
||||
std::string Symbol() const { return name_; }
|
||||
private:
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
inline const bin_expr_t* bin_expr_t::CreateExpr(const bin_expr_t* arg1, const bin_expr_t* arg2, const char op) {
|
||||
const bin_expr_t* expr = NULL;
|
||||
switch (op) {
|
||||
case '+':
|
||||
expr = new add_expr_t(arg1, arg2);
|
||||
break;
|
||||
case '-':
|
||||
expr = new sub_expr_t(arg1, arg2);
|
||||
break;
|
||||
case '*':
|
||||
expr = new mul_expr_t(arg1, arg2);
|
||||
break;
|
||||
case '/':
|
||||
expr = new div_expr_t(arg1, arg2);
|
||||
break;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
inline const bin_expr_t* bin_expr_t::CreateArg(Expr* obj, const std::string str) {
|
||||
const bin_expr_t* arg = NULL;
|
||||
const unsigned i = strspn(str.c_str(), "1234567890");
|
||||
if (i == str.length()) {
|
||||
const unsigned value = atoi(str.c_str());
|
||||
arg = new const_expr_t(value);
|
||||
} else {
|
||||
const std::string sub_expr = obj->Lookup(str);
|
||||
if (sub_expr.empty()) {
|
||||
arg = new var_expr_t(str);
|
||||
obj->AddVar(str);
|
||||
} else {
|
||||
const Expr* expr = new Expr(sub_expr, obj);
|
||||
arg = expr->GetTree();
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
|
||||
#endif // _SRC_XML_EXPR_H
|
||||
@@ -0,0 +1,221 @@
|
||||
#ifndef SRC_XML_XML_H_
|
||||
#define SRC_XML_XML_H_
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace xml {
|
||||
|
||||
class Xml {
|
||||
public:
|
||||
typedef std::vector<char> token_t;
|
||||
struct level_t {
|
||||
std::string tag;
|
||||
std::vector<level_t*> nodes;
|
||||
std::map<std::string, std::string> opts;
|
||||
};
|
||||
typedef std::vector<level_t*> nodes_vec_t;
|
||||
|
||||
enum {
|
||||
DECL_STATE,
|
||||
BODY_STATE
|
||||
};
|
||||
|
||||
Xml(const char* file_name) :
|
||||
file_name_(file_name),
|
||||
file_line_(0),
|
||||
data_size_(0),
|
||||
index_(0),
|
||||
state_(BODY_STATE),
|
||||
level_(NULL),
|
||||
comment_(false)
|
||||
{
|
||||
AddLevel("top");
|
||||
|
||||
fd_ = open(file_name, O_RDONLY);
|
||||
if (fd_ == -1) {
|
||||
std::cout << "XML file not found: " << file_name << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
token_t remainder;
|
||||
while (1) {
|
||||
token_t token = (remainder.size()) ? remainder : NextToken();
|
||||
remainder.clear();
|
||||
// End of file
|
||||
if (token.size() == 0) break;
|
||||
|
||||
// token_t token1 = token;
|
||||
// token1.push_back('\0');
|
||||
// std::cout << "> " << &token1[0] << std::endl;
|
||||
|
||||
switch(state_) {
|
||||
case BODY_STATE:
|
||||
if (token[0] == '<') {
|
||||
bool node_begin = true;
|
||||
unsigned ind = 1;
|
||||
if (token[1] == '/') {
|
||||
node_begin = false;
|
||||
++ind;
|
||||
}
|
||||
|
||||
unsigned i = ind;
|
||||
while (i < token.size()) { if (token[i] == '>') break; ++i; }
|
||||
for (unsigned j = i + 1; j < token.size(); ++j) remainder.push_back(token[j]);
|
||||
|
||||
if (i == token.size()) {
|
||||
if (node_begin) state_ = DECL_STATE;
|
||||
else BadFormat(token);
|
||||
token.push_back('\0');
|
||||
} else token[i] = '\0';
|
||||
|
||||
const char* tag = strdup(&token[ind]);
|
||||
if (node_begin) {
|
||||
AddLevel(tag);
|
||||
} else {
|
||||
if (strncmp(CurrentLevel().c_str(), tag, strlen(tag))) {
|
||||
token.back() = '>';
|
||||
BadFormat(token);
|
||||
}
|
||||
UpLevel();
|
||||
}
|
||||
} else BadFormat(token);
|
||||
break;
|
||||
case DECL_STATE:
|
||||
if (token[0] == '>') {
|
||||
state_ = BODY_STATE;
|
||||
for (unsigned j = 1; j < token.size(); ++j) remainder.push_back(token[j]);
|
||||
continue;
|
||||
} else {
|
||||
token.push_back('\0');
|
||||
unsigned j = 0;
|
||||
for (j = 0; j < token.size(); ++j) if (token[j] == '=') break;
|
||||
if (j == token.size()) BadFormat(token);
|
||||
token[j] = '\0';
|
||||
const char* key = &token[0];
|
||||
const char* value = &token[j + 1];
|
||||
AddOption(key, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::cout << "Wrong state: " << state_ << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<level_t*> GetNodes(std::string global_tag) {
|
||||
return map_[global_tag];
|
||||
}
|
||||
|
||||
void Print() const {
|
||||
for(auto& elem : map_) {
|
||||
for (auto node : elem.second) {
|
||||
if (node->opts.size()) {
|
||||
std::cout << elem.first << ":" << std::endl;
|
||||
for (auto& opt : node->opts) {
|
||||
std::cout << " " << opt.first << " = " << opt.second << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool LineEndCheck() {
|
||||
bool found = false;
|
||||
if (buffer_[index_] == '\n') {
|
||||
buffer_[index_] = ' ';
|
||||
++file_line_;
|
||||
found = true;
|
||||
comment_ = false;
|
||||
} else if (comment_ || (buffer_[index_] == '#')) {
|
||||
found = true;
|
||||
comment_ = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
token_t NextToken() {
|
||||
token_t token;
|
||||
|
||||
while (1) {
|
||||
if (data_size_ == 0) {
|
||||
data_size_ = read(fd_, buffer_, buf_size_);
|
||||
if (data_size_ <= 0) break;
|
||||
}
|
||||
if (token.empty()) while ((index_ < data_size_) && ((buffer_[index_] == ' ') || LineEndCheck())) {
|
||||
++index_;
|
||||
}
|
||||
while ((index_ < data_size_) && (buffer_[index_] != ' ') && !LineEndCheck()) {
|
||||
token.push_back(buffer_[index_++]);
|
||||
}
|
||||
if (index_ == data_size_) {
|
||||
index_ = 0;
|
||||
data_size_ = 0;
|
||||
} else break;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
void BadFormat(token_t token) {
|
||||
token.push_back('\0');
|
||||
std::cout << "Error: " << file_name_ << ", line " << file_line_ << ", bad XML token '" << &token[0] << "'" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void AddLevel(const std::string& tag) {
|
||||
level_t* level = new level_t;
|
||||
level->tag = tag;
|
||||
if (level_) {
|
||||
level_->nodes.push_back(level);
|
||||
stack_.push_back(level_);
|
||||
}
|
||||
level_ = level;
|
||||
|
||||
std::string global_tag;
|
||||
for (level_t* level : stack_) { global_tag += level->tag + "."; }
|
||||
global_tag += tag;
|
||||
map_[global_tag].push_back(level_);
|
||||
}
|
||||
|
||||
void UpLevel() {
|
||||
level_ = stack_.back();
|
||||
stack_.pop_back();
|
||||
}
|
||||
|
||||
std::string CurrentLevel() const {
|
||||
return level_->tag;
|
||||
}
|
||||
|
||||
void AddOption(const std::string& key, const std::string& value) {
|
||||
level_->opts[key] = value;
|
||||
}
|
||||
|
||||
const char* file_name_;
|
||||
unsigned file_line_;
|
||||
int fd_;
|
||||
static const unsigned buf_size_ = 256;
|
||||
char buffer_[buf_size_];
|
||||
unsigned data_size_;
|
||||
unsigned index_;
|
||||
unsigned state_;
|
||||
level_t* level_;
|
||||
std::vector<level_t*> stack_;
|
||||
std::map<std::string, nodes_vec_t> map_;
|
||||
bool comment_;
|
||||
};
|
||||
|
||||
} // namespace xml
|
||||
|
||||
#endif // SRC_XML_XML_H_
|
||||
Αναφορά σε νέο ζήτημα
Block a user