sylar高性能服务器-配置(P12-p14)内容记录

news2024/12/28 2:53:21

文章目录

    • p12:复杂类型解析
      • 一、方法函数
      • 二、结果展示
    • p13:复杂类型解析完善
      • 一、方法函数
      • 二、结果展示
    • p14:自定义类型解析
      • 一、方法函数
      • 二、小结

p12:复杂类型解析

​ 本节内容主要针对完了配置类中对于复杂类型的转换。之前只实现了基础类型之间的转换,而对于容器等复杂类型无法转换,所以本节实现了对于vectorstring之间的转换方式。

一、方法函数

ConfigVar

​ 之前由于只有基础类型转换,代码里面直接调用lexical_cast,这样做无法在传入复杂类型时进行解析。因此把lexical_cast的转化过程函数化,方便在外部针对特定类型的转化。

template<class T, class FromStr = LexicalCast<std::string, T>, class ToStr = LexicalCast<T, std::string>>
class ConfigVar : public ConfigvarBase {
public:
    typedef std::shared_ptr<ConfigVar> ptr;

    ConfigVar(const std::string& name, const T& default_value, const std::string& description = "") // 初始化配置名称、参数值以及参数描述
        :ConfigvarBase(name,description)
        ,m_val(default_value) {

        }
    std::string toString() override {   // 将参数值转换为string类型
        try {
            // return boost::lexical_cast<std::string>(m_val);
            return ToStr()(m_val);
        } catch(std::exception& e) {
            SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ConfigVar::toString exception"
                << e.what() << "convert: " << typeid(m_val).name() << " to string";
        }
        return "";
    }
    bool fromString(const std::string& val) override {  // 从string转换为参数值
        try {
            // m_val = boost::lexical_cast<T>(val);
            setValue(FromStr()(val));
        } catch (std::exception& e) {
            SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ConfigVar::fromString exception "
                << e.what() << " convert: string to " << typeid(m_val).name();
        }
        return false;
    }

    const T getValue() const { return m_val; }
    void setValue(const T& v) { m_val = v; }

private:
    T m_val;
};

LexicalCast

​ 如果是int float等基础类型转化,使用下列函数,

// 基础类型转换 把F转换成T类型
template<class F, class T>
class LexicalCast {
public:
    T operator()(const F& v) {
        return boost::lexical_cast<T>(v);
    }
};

​ [string -> vector]。代码比较清楚,直接看注释就行。

// 复杂类型转换 偏特化[string -> vector]
template<class T>
class LexicalCast<std::string, std::vector<T>> {
public:
    std::vector<T> operator()(const std::string& v) {
        // 调用YAML中的load函数,接收一个string类型输入,将其转换成node结构
        YAML::Node node = YAML::Load(v);
        std::vector<T> vec;     // 定义结果vec
        std::stringstream ss;   // 使用字符串流来获取node中的每个string值
        for(size_t i = 0; i < node.size(); ++ i) {
            ss.str("");
            ss << node[i];
            vec.push_back(LexicalCast<std::string, T>()(ss.str())); // 这里相当于调用基础类型转换,如果传入的vec里面元素是int类型,那么就是string -> int
        }
        return vec;
    }
};

[vector -> string]

// 复杂类型转换 偏特化[vector -> string]
template<class T>
class LexicalCast<std::vector<T>, std::string> {
public:
    std::string operator()(const std::vector<T>& v) {
        // 定义一个node容器
        YAML::Node node;
        for(auto& i : v) {
            node.push_back(YAML::Load(LexicalCast<T, std::string>()(i))); // 基础类型转换
        }
        std::stringstream ss;
        ss << node;
        return ss.str();
    }
};

二、结果展示

​ 下面代自定义了一个配置参数项g_vec_value_config,输出后载入log.yml文件,更改了g_vec_value_config里面的元素值。


sylar::ConfigVar<std::vector<int>>::ptr g_vec_value_config = 
    sylar::Config::Lookup("system.vec", std::vector<int>{1,2,3}, "system vec");
void test_config() {
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << g_int_value_config->getValue(); 
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << g_float_value_config->toString();
    auto v = g_vec_value_config->getValue();
    auto res = g_vec_value_config->toString();
    std::cout << res << std::endl;
    for(auto& i : v) {
        SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "before:" << i;
    }
    YAML::Node root = YAML::LoadFile("/root/Web-learning/sylar/bin/conf/log.yml");
    sylar::Config::LoadFromYaml(root);
    v = g_vec_value_config->getValue();
    for(auto& i : v) {
        SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << i;
    }
    
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << g_int_value_config->getValue(); 
    // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "after:" << g_float_value_config->toString();
}

int main(int argc, char** argv) {
    // test_yaml();
    test_config();
    return 0;
}

image-20231213123210283

p13:复杂类型解析完善

​ 本节内容是对上一节STL容器的完善,新增了对list、map、set、unordered_map、unordered_set的支持。由于本节的代码内容和上一节比较重复,所以简单记录一下部分内容。

一、方法函数

map

​ 注意循环的迭代方式与vector等容器不同,然后目前对于map里面的类型只支持基本类型的转换,所以后期需要按我们目前做的方式让map里面的内容支持复杂类型。

template<class T>
class LexicalCast<std::string, std::map<std::string, T>> {
public:
    std::map<std::string, T> operator()(const std::string& v) {
        YAML::Node node = YAML::Load(v);
        std::map<std::string,T> vec;     
        for(auto it = node.begin(); it != node.end(); ++ it) {
            ss.str("");
            ss << it->second;
            vec.insert(std::make_pair(it->first.Scalar(), LexicalCast<std::string, T>()(ss.str()))); 
        }
        return vec;
    }
};

宏定义

​ 测试时代码重复比较大,通过下面两个宏函数简化。

#define XX(g_var,name,prefix) \
    { \
        auto v = g_var->getValue(); \
        for(auto& i : v) { \
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << #prefix " " #name ": " << i; \
        } \
    }

#define XX_M(g_var,name,prefix) \
    { \
        auto v = g_var->getValue(); \
        for(auto& i : v) { \
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << #prefix " " #name ": {" << i.first << " : " << i.second << "}"; \
        } \
    }

二、结果展示

image-20231213151855855

p14:自定义类型解析

​ 本节内容主要讲解了Config解析自定义类型,和上面两节一样,处理复杂类型或者自定义类型的关键是片特化函数LexicalCast,下面是一些简单比较记录。

一、方法函数

​ 之前代码在解析yml文件时,如果遇到相同key但是类型不同,会直接忽略。比如下列代码,key:system.port的值存在两种类型,当我们使用Config::Lookup(system.port)`查找时,不知道最后找到的是谁,所以程序应该在这里报错提示。

sylar::ConfigVar<int>::ptr g_int_value_config = 
    sylar::Config::Lookup("system.port", (int)8080, "system port");

sylar::ConfigVar<float>::ptr g_int_valuex_config = 
    sylar::Config::Lookup("system.port", (float)8080, "system port");

Lookup

​ 对该函数进行修改,核心思想就是利用dynamic_pointer_cast,如果相同key的类型不同,则会转换失败返回nullptr

auto it = s_datas.find(name); // 直接从配置容器中查找
        if(it != s_datas.end()) {
            auto tmp = std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
            if(tmp) {
                SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exists"; 
            } else {
                SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "Lookup name = " << name << " exists but type not " << typeid(T).name(); 
                return nullptr;
            }
        }

再次运行可以看到已经有了报错提示

image-20231213155114465

自定义类型

​ 以下我们定义了一个Person类,希望能从log.yml文件中解析出相应的配置项。

class Person {
public:
    std::string m_name;
    int m_age = 0;
    bool m_sex = 0;

    std::string toString() const {
        std::stringstream ss;
        ss << "[Person name = " << m_name
           << " age = " << m_age
           << " sex = " << m_sex
           << "]";
        return ss.str();
    }
};

​ 第一步肯定是去书写对应的片特化函数LexicalCast,函数里面的内容无非就是YAML::NODE类型与自定义类型之间的值传递。

namespace sylar {
// 复杂类型转换 偏特化[string -> Person]
template<>
class LexicalCast<std::string, Person> {
public:
    Person operator()(const std::string& v) {
        // 调用YAML中的load函数,接收一个string类型输入,将其转换成node结构
        YAML::Node node = YAML::Load(v);
        Person p;
        p.m_name = node["name"].as<std::string>();
        p.m_age = node["age"].as<int>();
        p.m_sex = node["sex"].as<bool>();
        return p;
    }
};

// 复杂类型转换 偏特化[Person -> string]
template<>
class LexicalCast<Person, std::string> {
public:
    std::string operator()(const Person& p) {
        // 定义一个node容器
        YAML::Node node;
        node["name"] = p.m_name;
        node["age"] = p.m_age;
        node["sex"] = p.m_sex;
        std::stringstream ss;
        ss << node;
        return ss.str();
    }
};
}

​ 来一个测试用例

// 1.自定义类型
sylar::ConfigVar<Person>::ptr g_person = 
    sylar::Config::Lookup("class.person", Person(), "system person");

// log.yml
class:
  person:
    name: ikun
    age: 25
    sex: true

​ 输出结果:

image-20231213202609316

自定义类型与STL的嵌套

​ 设计一些复杂的用例

// 2.自定义类型与STL嵌套
sylar::ConfigVar<std::map<std::string, Person>>::ptr g_person_map = 
    sylar::Config::Lookup("class.map", std::map<std::string, Person>(), "system map");
// 3.更加复杂的类型map<string,vector<Person>>
sylar::ConfigVar<std::map<std::string, std::vector<Person>>>::ptr g_person_vec_map = 
    sylar::Config::Lookup("class.vec_map", std::map<std::string,  std::vector<Person>>(), "system vec_map");
// log.yml
map:
    person1:
      name: ikun2
      age: 252
      sex: true
    person2:
      name: ikun3
      age: 152
      sex: false
  vec_map:
    vec1:
      - name: ikun
        age: 25
        sex: true
      - name: ikun2
        age: 252
        sex: true
    vec2:
      - name: ikun4
        age: 225
        sex: true
      - name: ikun21
        age: 2152
        sex: true

输出结果:

image-20231213203115964

二、小结

​ 整个配置模块到这基本完成,这几节的内容目的就是尽可能的去解析不同类型的配置内容,所以只要12节视频基本弄懂,后面两节的内容也没什么大问题。建议自己跟着视频写好代码后可以把解析过程每一步的内容打印出来,看和自己想的是否一样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【UE 材质】角色触碰空气墙效果

效果 步骤 1. 新建一个工程&#xff0c;创建一个Basic关卡&#xff0c;添加一个第三人称游戏资源到内容浏览器 2. 新建一个材质参数集&#xff0c;这里命名为“MPC_Vector” 打开“MPC_Vector”&#xff0c;添加一个向量参数 3. 新建一个材质&#xff0c;这里命名为“M_Wall”…

【开源软件】最好的开源软件-2023-第23名 Apache Druid

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

LeetCode-旋转链表问题

1.旋转链表 题目描述&#xff1a; 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 思路&#xff1a; 这里向右移动k个位置&#xff0c;相当于从链表的倒数第k个节点处断开&#xff0c;之后再将断开的两个子链表按照相反顺序…

Java基础语法之继承

为什么要继承 会发现&#xff0c;狗和猫只有叫声不同&#xff0c;因为它们都是动物&#xff0c;会有相同的属性和行为&#xff0c;所以它们可以继承animla类 如何继承 用到extends关键字 这样就会简化好多 注意 1.Animal称为父类/超类/基类&#xff1b;dog&#xff0c;cat称…

多项目同时进行如何做好进度管理?

许多企业都面临着同时进行多个项目的情况&#xff0c;因此项目经理经常需要管理多个项目。多项目管理的难点不仅在于项目数量增加&#xff0c;还在于资源分配不均、难以监控多个项目进度以及复杂的沟通协作。 一、从项目经理的角度分析 首先&#xff0c;要把握高效项目管理的几…

Jmeter接口自动化测试 —— Jmeter变量的使用

​在使用jmeter进行接口测试时&#xff0c;我们难免会遇到需要从上下文中获取测试数据的情况&#xff0c;这个时候就需要引入变量了。 定义变量 添加->配置元件->用户自定义的变量 添加->配置元件->CSV 数据文件设置 变量的调用方式&#xff1a;${变量名} 变量的…

融了超24亿一分钱不花,放银行吃利息,这家存储创企厉害了

​引言&#xff1a;AI与大模型风起云涌&#xff0c;催生了这匹存储“黑马” 【全球存储观察 &#xff5c; 科技热点关注】 这家总部设在美国的存储初创公司&#xff0c;真的赶上AI与大模型时代的风口了。Vast Data公司最新再次获得E轮融资1.18亿美元&#xff0c;但是这个存储…

玩转Docker(二):centos7安装Docker

文章目录 一、安装Docker&#xff08;centos7&#xff09;二、运行第一个容器 环境选择&#xff1a; &#xff08;1&#xff09;管理工具&#xff1a;Docker Engine。使用最广泛。 &#xff08;2&#xff09;runtime&#xff1a;runc。Docker的默认runtime。 &#xff08;3&…

【开源软件】最好的开源软件-2023-第25名 nbdev

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

智能优化算法应用:基于蜻蜓算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蜻蜓算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蜻蜓算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蜻蜓算法4.实验参数设定5.算法结果6.参考文献7.MA…

科技赋能医疗设备管理提质增效,实现医院高质量发展

近日&#xff0c;苏州阿基米德网络科技有限公司与医疗领域头部级媒体健康界&#xff0c;联合举办“数智为擎 提质增效——医学装备智慧管理创新发展论坛”的直播活动。 直播现场&#xff0c;来自上海交通大学医学院附属同仁医院、中华医学会航海医学分会、苏州阿基米德的专家们…

【ret2hbp】一道板子测试题 和 SCTF2023 - sycrpg

前言 ret2hbp 主要是利用在内核版本 v6.2.0 之前&#xff0c;cpu_entry_area mapping 区域没有参与随机化的利用。其主要针对的场景如下&#xff1a; 1&#xff09;存在任意地址读&#xff0c;泄漏内核地址 2&#xff09;存在无数次任意地址写&#xff0c;泄漏内核地址并提权…

Linux下网络通信及socket编程

文章目录 网络通信socket应用编程函数介绍IP地址转换函数程序源代码程序执行结果 网络通信 网络通信本质上是一种进程间通信&#xff0c;是位于网络中不同主机上的进程之间的通信。网络通信大致分为以下三层。 在硬件层&#xff0c;两台主机都提供了网卡设备&#xff0c;满足…

ADC学习总结

ADC的架构分类&#xff1a; 1、Delta-Sigma 采样率一般是在1M以内&#xff0c;位数一般可以做的很高&#xff0c;比如24位&#xff0c;Delta-Sigma ADC采用了过采样技术&#xff0c;不需要在模拟输入端加抗混叠滤波&#xff0c;由后端数字滤波器进行处理&#xff0c;通过信噪…

DDD领域驱动架构设计学习网站和开源框架

文章目录 介绍1、国外Axon2、阿里Cola 介绍 近年来&#xff0c;关于DDD的讨论越来越多&#xff0c;关于网上的文章很多都是理论上的介绍&#xff0c;由于自己最近也在学习相关知识&#xff0c;所以分享几个关于DDD落地的开源框架。 1、国外Axon Axon是国外一款比较系统的DDD…

Re59:读论文 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称&#xff1a;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks 模型开源地址&#xff1a;https://huggingface.co/facebook/rag-token-nq ArXiv下载地址&#xff1a;https://arxi…

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

元宇宙&#xff0c;是一个虚拟的网络世界&#xff0c;它与现实世界相互连接&#xff0c;为人们提供了一个身临其境的数字体验。元宇宙的概念并不新鲜&#xff0c;早在上个世纪就有科幻作家和电影导演对它进行了想象和创造。但是&#xff0c;随着科技的发展&#xff0c;特别是5G…

iic应用篇

一.iic的优点 1. IIC总线物理链路简单&#xff0c;硬件实现方便&#xff0c;扩展性非常好&#xff08;1个主机控制器可以根据需求增加从机数量&#xff0c;同时删减从机数量也不会影响总线通信&#xff09;&#xff1b;IIC总线只需要SDA和SCL两条信号线&#xff0c;相比于PCI/…

python和pygame实现烟花特效

python和pygame实现烟花特效 新年来临之际&#xff0c;来一个欢庆新年烟花祝贺&#xff0c;需要安装使用第三方库pygame&#xff0c;关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 效果图及源码 先看效果图&#xff1a…

c#异常强大的统计运行时间功能,一行代码,监控 C# 方法执行耗时

MethodTimer.Fody MethodTimer.Fody 是一个功能强大的库&#xff0c;可以用于测量 .NET 应用程序中的方法的执行时间。 它使用 Fody 插件框架可以无缝集成到您的项目中&#xff0c;所以向代码中添加性能测量功能变得非常容易。 如何使用 首先&#xff0c;需要安装 Nuget 包&am…