C++ 编程技巧_数据协议编程技巧

协议无处不在,正是因为统一协议接口的存在,软件可以运行再各种软件上,各种语言都可以编写移动端桌面端软件。

  • 个人总结的数据协议编程进阶技巧,总结如下七层 。

Level 1 无模式

    std::cout << "Level 1 无模式\n";

Level 2 简单模式,数据分离

	//Level 2
    // 方法
    auto DoPrint = [](const char* data)
    {
        std::cout << data;
        std::cout << "\n";
    };
    // 数据
    const char* data = GetData("Level 2 简单模式,数据分离\n");
    // 业务执行
    DoPrint(data);

Level 3 简单模式,数据与方法分离

using DoMethodVRetPStr = void(const char*);
const char* data2 = GetData("Level 3 简单模式,数据与方法分离\n");
DoMethodVRetPStr *method1 = DoPrint;
method1(data2);

Level 4 简单协议模式

// 简单接口协议定义
    struct DataProtocol
    {
        const char* m_para;
        DoMethodVRetPStr* m_handler;
    };
    // 数据容器,存储支持的业务类型
    DataProtocol testData[] = {
        {"Level 4 简单协议模式", DoPrint},
        {"...", DoOthers},
        {nullptr, nullptr}
    };
    // 接口解析器
    auto TestProtocol = [](DataProtocol& data) ->void
    {
        data.m_handler(data.m_para);
    };
    // 业务层调用接口,其他
    TestProtocol(testData[0]);

Level 5 文本协议

使用文本协议定义

  • 类似于http 文本协议,制定类似以下文本协议请求(此处借用json数据格式,现今数据格式众多,比如xml, protobuf, bson,)
  • 当然也可以纯二进制协议(可参考UDP/TCP协议如何定义的,访问国际通用的RFC网站,https://datatracker.ietf.org/doc/rfc793/)
  • 还可以文本与二进制混合的文本协议(http就是文本与二进制混合的协议,图片音视频都可以传输)
    例如 “{ “method”:“DoPrint”,“data”:“通用定制化文本协议模式” }”;

实现如下代码:


    // 定义接口协议
    enum class EKeyType:int
    {
        eKeyType_Data = 0,
        eKeyType_Method,
        eKeyType_Loop
    };
    std::map<EKeyType, const char *> KeyConfigs = {
        {EKeyType::eKeyType_Data,"data"},
        {EKeyType::eKeyType_Loop,"loop"},
        {EKeyType::eKeyType_Method, "method"}
    };
    // 定义支持的业务数据
    std::map<const char *, DoMethodVRetPStr* > MethodConfigs ={
        { "DoPrint", DoPrint},
        { "DoOthers", DoOthers}
    };

    // 解析接口 -- 获取方法
    auto prt_Analyse_GetMethod = [&](const char* data)->DoMethodVRetPStr*
    {
        // 序列化解析
        json requestJson = json::parse(data);
        const char* key = KeyConfigs[EKeyType::eKeyType_Method];
        std::string methodName = requestJson.value(key, "");
        if (methodName == "")
            return nullptr;
        for (auto it : MethodConfigs)
        {
            if (methodName.compare(it.first) == 0)
                return it.second;
        }
        return nullptr;
    };

    // 解析接口 -- 获取数据
    auto prt_Analyse_GetData = [&](const char* data)->std::string
    {
        // 序列化解析
        json requestJson = json::parse(data);
        const char* key = KeyConfigs[EKeyType::eKeyType_Data];
        return requestJson.value(key, "");
    };
    // 接口执行器
    auto prt_Run = [&](const char* data)
    {
        DoMethodVRetPStr* handler = prt_Analyse_GetMethod(data);
        std::string handerData = prt_Analyse_GetData(data);
        // 当然可以直接执行
        // handler(handerData.c_str());
        // level4模式不过时,此处沿用
        DataProtocol _setData = { handerData.c_str() , handler };
        TestProtocol(_setData);
    };
    
    // 调用接口,执行业务
    // 业务数据
    const char* protocolRequest = R"(
            {
	            "method": "DoPrint",
	            "data": "Level 5 TEST PROTOCAL "
            }
        )";
    // 调用接口执行
    prt_Run(protocolRequest);

Level 6 文本协议-- 扩充功能,添加逻辑流程控制

在level5 上添加一个loop控制个数参数

 auto DoLoop = [](int loopCount, DataProtocol* hander) {
        if (!hander) 
            return;
        for (; loopCount > 0; loopCount--)
        {
            hander->m_handler(hander->m_para);
        }
    };

    using LoopLogicType = void(int , DataProtocol*);
    // 定义支持的业务数据,添加一个 Loop控制参数
    std::map<std::string, LoopLogicType* > logicMethodConfigs = {
        { "loop", DoLoop}
    };

    auto prt_Analyse_GetLoop = [&](const char* data,int& outData) -> LoopLogicType*
    {
        json requestJson = json::parse(data);
        std::string key = KeyConfigs[EKeyType::eKeyType_Loop];
        if (requestJson.contains(key))
        {
            outData = requestJson.value(key,1);
            for (auto it : logicMethodConfigs)
            {
                if (key.compare(it.first) != std::string::npos)
                    return it.second;
            }
        }
        return nullptr;
    };

    // 接口执行器
    auto prt_Run_extra = [&](const char* data)
    {
        DoMethodVRetPStr* handler = prt_Analyse_GetMethod(data);
        std::string handerData = prt_Analyse_GetData(data);

        DataProtocol _setData = { handerData.c_str() , handler };
        int loopCount = 0;
        LoopLogicType *loopMethod = prt_Analyse_GetLoop(data, loopCount);
        if(loopMethod)
        {
            loopMethod(loopCount, &_setData);
        }
    };
    
    // 输入业务数据
    const char* protocolRequest_extra = R"(
            {
	            "method": "DoPrint",
	            "data": "Level 6 TEST PROTOCAL extention , add Loop control",
                "loop":3
            }
        )";
    // 执行业务数据
    prt_Run_extra(protocolRequest_extra);

Level 7 自定义脚本语法编译器,此处略过

    // Leve7 
    // 自定义脚本语法编译器,例如以下脚本内容 ---此处代码略过不写了
    const char* script = R"(
            loopCount = 3
            for i in range(0,loopCount){
                print "Level7 run script"
            }     
        )";

测试代码输出如下:

在这里插入图片描述

源码(需要nlohmann/json.hpp)

// DemoPPt.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "nlohmann/json.hpp"
#include <iostream>


using DoMethodVRetPStr = void(const char*);

using nlohmann::json;

const char* GetData(const char* data)
{
    return data;
}

void DoPrint_Simple()
{
    std::cout << "Level 1 无模式\n";
}

void DoOthers(const char* data)
{
    return;
}


int main()
{
    //Level 1
    DoPrint_Simple();

    //Level 2
    // 方法
    auto DoPrint = [](const char* data)
    {
        std::cout << data;
        std::cout << "\n";
    };
    // 数据
    const char* data = GetData("Level 2 简单模式,数据分离\n");
    // 业务执行
    DoPrint(data);

    //Level 3
    const char* data2 = GetData("Level 3 简单模式,数据与方法分离\n");
    DoMethodVRetPStr *method1 = DoPrint;
    method1(data2);

    //Level 4
    // 简单接口协议定义
    struct DataProtocol
    {
        const char* m_para;
        DoMethodVRetPStr* m_handler;
    };
    // 数据容器,存储支持的业务类型
    DataProtocol testData[] = {
        {"Level 4 简单协议模式", DoPrint},
        {"...", DoOthers},
        {nullptr, nullptr}
    };
    // 接口解析器
    auto TestProtocol = [](DataProtocol& data) ->void
    {
        data.m_handler(data.m_para);
    };
    // 业务层调用接口,其他
    TestProtocol(testData[0]);

    //Level 5
    // 使用文本协议定义
    // 类似于http 文本协议,制定类似以下文本协议请求(此处借用json数据格式,现今数据格式众多,比如xml, protobuf, bson,)
    // 当然也可以纯二进制协议(可参考UDP/TCP协议如何定义的,访问国际通用的RFC网站,https://datatracker.ietf.org/doc/rfc793/)
    // 还可以文本与二进制混合的文本协议(http就是文本与二进制混合的协议,图片音视频都可以传输)
    // 例如 const char* protocolRequest = "{ \"method\":\"DoPrint\",\"data\":\"通用定制化文本协议模式\" }";

    // 定义接口协议
    enum class EKeyType:int
    {
        eKeyType_Data = 0,
        eKeyType_Method,
        eKeyType_Loop
    };
    std::map<EKeyType, const char *> KeyConfigs = {
        {EKeyType::eKeyType_Data,"data"},
        {EKeyType::eKeyType_Loop,"loop"},
        {EKeyType::eKeyType_Method, "method"}
    };
    // 定义支持的业务数据
    std::map<const char *, DoMethodVRetPStr* > MethodConfigs ={
        { "DoPrint", DoPrint},
        { "DoOthers", DoOthers}
    };

    // 解析接口 -- 获取方法
    auto prt_Analyse_GetMethod = [&](const char* data)->DoMethodVRetPStr*
    {
        // 序列化解析
        json requestJson = json::parse(data);
        const char* key = KeyConfigs[EKeyType::eKeyType_Method];
        std::string methodName = requestJson.value(key, "");
        if (methodName == "")
            return nullptr;
        for (auto it : MethodConfigs)
        {
            if (methodName.compare(it.first) == 0)
                return it.second;
        }
        return nullptr;
    };

    // 解析接口 -- 获取数据
    auto prt_Analyse_GetData = [&](const char* data)->std::string
    {
        // 序列化解析
        json requestJson = json::parse(data);
        const char* key = KeyConfigs[EKeyType::eKeyType_Data];
        return requestJson.value(key, "");
    };
    // 接口执行器
    auto prt_Run = [&](const char* data)
    {
        DoMethodVRetPStr* handler = prt_Analyse_GetMethod(data);
        std::string handerData = prt_Analyse_GetData(data);
        // 当然可以直接执行
        // handler(handerData.c_str());
        // level4模式不过时,此处沿用
        DataProtocol _setData = { handerData.c_str() , handler };
        TestProtocol(_setData);
    };
    
    // 调用接口,执行业务
    // 业务数据
    const char* protocolRequest = R"(
            {
	            "method": "DoPrint",
	            "data": "Level 5 TEST PROTOCAL "
            }
        )";
    prt_Run(protocolRequest);

    // Level 6
    // 使用文本协议定义 -- 扩充功能,添加逻辑流程控制

    auto DoLoop = [](int loopCount, DataProtocol* hander) {
        if (!hander) 
            return;
        for (; loopCount > 0; loopCount--)
        {
            hander->m_handler(hander->m_para);
        }
    };

    using LoopLogicType = void(int , DataProtocol*);
    // 定义支持的业务数据
    std::map<std::string, LoopLogicType* > logicMethodConfigs = {
        { "loop", DoLoop}
    };

    auto prt_Analyse_GetLoop = [&](const char* data,int& outData) -> LoopLogicType*
    {
        json requestJson = json::parse(data);
        std::string key = KeyConfigs[EKeyType::eKeyType_Loop];
        if (requestJson.contains(key))
        {
            outData = requestJson.value(key,1);
            for (auto it : logicMethodConfigs)
            {
                if (key.compare(it.first) != std::string::npos)
                    return it.second;
            }
        }
        return nullptr;
    };


    // 接口执行器
    auto prt_Run_extra = [&](const char* data)
    {
        DoMethodVRetPStr* handler = prt_Analyse_GetMethod(data);
        std::string handerData = prt_Analyse_GetData(data);

        DataProtocol _setData = { handerData.c_str() , handler };
        int loopCount = 0;
        LoopLogicType *loopMethod = prt_Analyse_GetLoop(data, loopCount);
        if(loopMethod)
        {
            loopMethod(loopCount, &_setData);
        }

    };
       
    const char* protocolRequest_extra = R"(
            {
	            "method": "DoPrint",
	            "data": "Level 6 TEST PROTOCAL extention , add Loop control",
                "loop":3
            }
        )";
    
    prt_Run_extra(protocolRequest_extra);


    // Leve7 
    // 自定义脚本语法编译器,例如以下脚本内容 ---此处代码略过不写了
    const char* script = R"(
            loopCount = 3
            for i in range(0,loopCount){
                print "Level7 run script"
            }     
        )";
  
    return 1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值