#pragma once #include #include #include #include #include #include #include #include #include #include namespace StatExp { using std::string; using std::vector; using namespace std::chrono; /** * @brief 保持时间仿函数 * 内部变量: * 1.当前保持时间 keep_time ms * 2.起始时间点 t1 */ struct KeepT { /** * @brief KeepT(lt,rt) * @param lt double * @param rt double * @return int 累计的lt==rt的时间 (ms) */ inline int64_t operator()(double lt, double rt) { if (fabs(lt - rt) > std::numeric_limits::epsilon()) { t1 = std::chrono::system_clock::now(); keep_time = 0; return 0; } else { keep_time = duration_cast(std::chrono::system_clock::now() - t1) .count(); } return keep_time; } private: int64_t keep_time = 0; std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now(); }; /** * @brief KeepC 保持次数仿函数 * 内部变量: * 保持次数 keep_times */ struct KeepC { /** * @brief KeepC(lt,rt) * @param lt double * @param rt double * @return int 累计的lt==rt的次数 */ inline int operator()(double lt, double rt) { if (fabs(lt - rt) > std::numeric_limits::epsilon()) { keep_times = 0; return 0; } else { keep_times += 1; } return keep_times; } private: int keep_times = 0; }; /** * @brief 上升沿次数 */ struct RiseEdge { /** * @brief RiseEdge 上升沿次数累计仿函数 * @param data 数据项 * @param is_reset 是否重置 * @return int 次数 */ inline int operator()(double data, double is_reset) { last_data = now_data; now_data = (bool)data; if (keep_times == -1) { return ++keep_times; } keep_times += int(!last_data && now_data); if (is_reset) { keep_times = -1; return 0; } return keep_times; } private: bool last_data = false; bool now_data = false; int keep_times = -1; }; /** * @brief 真 检测器 * 为真的次数 */ struct Detect { /** * @brief Detect 为真检测的仿函数 * @param data 数据 * @param is_reset 是否重置 * @return int */ inline int operator()(double data, double is_reset) { if (is_reset) { keep_times = 0; return 0; } if (data) { return ++keep_times; } return keep_times; } private: int keep_times = 0; }; /** * @brief */ struct DelayT { using Clock = std::chrono::steady_clock; using Milliseconds = std::chrono::milliseconds; int operator()(bool data, bool is_reset) { if (is_reset) { accumulated_time = 0; last_data = false; counting = false; return 0; } if (!last_data && data) { start_time = Clock::now(); counting = true; } else if (last_data && !data) { if (counting) { auto current_time = Clock::now(); accumulated_time += std::chrono::duration_cast(current_time - start_time) .count(); counting = false; } } last_data = data; if (counting) { auto current_time = Clock::now(); int current_duration = std::chrono::duration_cast(current_time - start_time) .count(); return accumulated_time + current_duration; } else { return accumulated_time; } } private: int accumulated_time = 0; bool last_data = false; bool counting = false; Clock::time_point start_time{}; }; using FIDD = std::function; enum class FiddType { KeepT = 0, KeepC, RiseEdge, Detect }; const std::map Fidd2M = { {"KeepT", FiddType::KeepT}, {"KeepC", FiddType::KeepC}, {"RiseEdge", FiddType::RiseEdge}, {"Detect", FiddType::Detect}}; const std::map FType2Regex = { {FiddType::KeepT, "KeepT\\((\\S+?),(\\S+?)\\)"}, {FiddType::KeepC, "KeepC\\((\\S+?),(\\S+?)\\)"}, {FiddType::RiseEdge, "RiseEdge\\((\\S+?),(\\S+?)\\)"}, {FiddType::Detect, "Detect\\((\\S+?),(\\S+?)\\)"}}; const std::map FType2RegexAll = { {FiddType::KeepT, "(KeepT\\(\\S+?,\\S+?\\))"}, {FiddType::KeepC, "(KeepC\\(\\S+?,\\S+?\\))"}, {FiddType::RiseEdge, "(RiseEdge\\(\\S+?,\\S+?\\))"}, {FiddType::Detect, "(Detect\\(\\S+?,\\S+?\\))"}}; inline FIDD CreateFIDD(FiddType type) { switch (type) { case FiddType::KeepC: return KeepC{}; break; case FiddType::KeepT: return KeepT{}; break; case FiddType::RiseEdge: return RiseEdge{}; break; case FiddType::Detect: return Detect{}; break; default: return KeepT{}; break; } } inline mix_cc::json search_regs(const string &str, const string ®_str) { mix_cc::json res; boost::regex reg(reg_str.c_str()); string::const_iterator start(str.begin()), end(str.end()); boost::match_results what; int i = 0; res[i] = reg_str; while (regex_search(start, end, what, reg, boost::match_default)) { vector v1; for (int j = 1; j < what.size(); j++) { v1.push_back(what[j]); } res[i + 1] = v1; i++; start = what[0].second; } return res; } inline std::string regex_str(const string ®_str, const string ®_t) { boost::regex base_regex(("(\\" + reg_t + ")").c_str()); std::string plv; std::stringstream ss; ss << R"(\\$1)"; plv = ss.str(); auto ret = boost::regex_replace(reg_str, base_regex, plv); return ret; } inline std::string regex_str(const string ®_str) { std::string str2 = reg_str; std::vector rex = {"+", "*", "(", ")", ".", "^", "|"}; for (auto item : rex) { str2 = StatExp::regex_str(str2, item); } return str2; } struct BinaryF { BinaryF() {} BinaryF(const string &exp_str, std::map *const mm_vars, FiddType type) { ftype = type; try { auto res = search_regs(exp_str, FType2Regex.at(type)); var1 = std::make_unique( res[1][0].get(), mm_vars); var2 = std::make_unique( res[1][1].get(), mm_vars); Fun = CreateFIDD(type); } catch (const std::exception &e) { } } FIDD Fun; FiddType ftype; std::unique_ptr var1; std::unique_ptr var2; inline double operator()() { if (var1 != nullptr && var2 != nullptr) { switch (ftype) { case FiddType::RiseEdge: case FiddType::Detect: return (double)Fun( var2->evaluate() ? var1->evaluate() : !var1->evaluate(), 0); break; default: return (double)Fun(var1->evaluate(), var2->evaluate()); break; } } else { return 0; } } }; class FunVars { public: FunVars() {} ~FunVars() {} inline std::pair add_exp_str(const std::string &exp_str, std::map *const mm_vars) { std::string out_str = exp_str; try { for (auto item : FType2RegexAll) { auto res = search_regs(exp_str, item.second); if (res.size() > 1) { for (int i = 1; i < res.size(); i++) { std::string expi = res[i][0].get(); if (exp2fvar.find(expi) == exp2fvar.end()) { exp2binayF[expi] = BinaryF(expi, mm_vars, item.first); std::string f_var = pre_var + std::to_string(index++); exp2fvar[expi] = f_var; exp2ftype[expi] = item.first; mm_vars->operator[](f_var) = 0; out_str = boost::regex_replace( out_str, boost::regex(regex_str(expi).c_str()), f_var.c_str()); } else { std::string f_var = exp2fvar[expi]; out_str = boost::regex_replace( out_str, boost::regex(regex_str(expi).c_str()), f_var.c_str()); } } } } return std::make_pair(true, out_str); } catch (const std::exception &e) { return std::make_pair(false, e.what()); } } /** * @brief 刷新 fun[index]变量 * @param is_reset 是否重置 bool * @param mm_vars std::map* const * @return true 刷新成功 * @return false 刷新失败 */ inline bool refresh_fun_vars(bool is_reset, std::map *const mm_vars) { try { for (auto fi : exp2fvar) { if (is_reset) { mm_vars->operator[](fi.second) = (double)exp2binayF[fi.first].Fun(0.0, 1.0); } else { mm_vars->operator[](fi.second) = exp2binayF[fi.first](); } } return true; } catch (const std::exception &e) { return false; } } inline bool empty() { return exp2fvar.empty(); } private: const std::string pre_var = "fun"; int index = 0; std::map exp2binayF; std::map exp2fvar; std::map exp2ftype; }; }