C++ 模板代码自动生成

37 篇文章 0 订阅
14 篇文章 0 订阅

https://github.com/pantor/inja

#include <inja/inja.hpp>

// Just for convenience
using namespace inja;

void testFile() {
    Environment env;
    json data;
    // Render a string with json data
    std::string result = env.render("Hello {{ name }}!", data); // "Hello world!"

    // Or directly read a template file
    Template temp = env.parse_template("./templates/greeting.txt");
    result = env.render(temp, data); // "Hello world!"

    data["name"] = "Inja";
    result = env.render(temp, data); // "Hello Inja!"

    // Or read the template file (and/or the json file) directly from the environment
    result = env.render_file("./templates/greeting.txt", data);
    result = env.render_file_with_json_file("./templates/greeting.txt", "./data.json");

    // Or write a rendered template file
    env.write(temp, data, "./result.txt");
    env.write_with_json_file("./templates/greeting.txt", "./data.json", "./result.txt");
}

void testFunc() {
    Environment env;
    json data;
    // Upper and lower function, for string cases
    render("Hello {{ upper(neighbour) }}!", data); // "Hello PETER!"
    render("Hello {{ lower(neighbour) }}!", data); // "Hello peter!"

    // Range function, useful for loops
    render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data); // "1234"
    render("{% for i in range(3) %}{{ at(guests, i) }} {% endfor %}", data); // "Jeff Tom Patrick "

    // Length function (please don't combine with range, use list directly...)
    render("I count {{ length(guests) }} guests.", data); // "I count 3 guests."

    // Get first and last element in a list
    render("{{ first(guests) }} was first.", data); // "Jeff was first."
    render("{{ last(guests) }} was last.", data); // "Patir was last."

    // Sort a list
    render("{{ sort([3,2,1]) }}", data); // "[1,2,3]"
    render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]"

    // Join a list with a separator
    render("{{ join([1,2,3], \" + \") }}", data); // "1 + 2 + 3"
    render("{{ join(guests, \", \") }}", data); // "Jeff, Patrick, Tom"

    // Round numbers to a given precision
    render("{{ round(3.1415, 0) }}", data); // 3
    render("{{ round(3.1415, 3) }}", data); // 3.142

    // Check if a value is odd, even or divisible by a number
    render("{{ odd(42) }}", data); // false
    render("{{ even(42) }}", data); // true
    render("{{ divisibleBy(42, 7) }}", data); // true

    // Maximum and minimum values from a list
    render("{{ max([1, 2, 3]) }}", data); // 3
    render("{{ min([-2.4, -1.2, 4.5]) }}", data); // -2.4

    // Convert strings to numbers
    render("{{ int(\"2\") == 2 }}", data); // true
    render("{{ float(\"1.8\") > 2 }}", data); // false

    // Set default values if variables are not defined
    render("Hello {{ default(neighbour, \"my friend\") }}!", data); // "Hello Peter!"
    render("Hello {{ default(colleague, \"my friend\") }}!", data); // "Hello my friend!"

    // Access an objects value dynamically
    render("{{ at(time, \"start\") }} to {{ time.end }}", data); // "16 to 22"

    // Check if a key exists in an object
    render("{{ exists(\"guests\") }}", data); // "true"
    render("{{ exists(\"city\") }}", data); // "false"
    render("{{ existsIn(time, \"start\") }}", data); // "true"
    render("{{ existsIn(time, neighbour) }}", data); // "false"

    // Check if a key is a specific type
    render("{{ isString(neighbour) }}", data); // "true"
    render("{{ isArray(guests) }}", data); // "true"
    // Implemented type checks: isArray, isBoolean, isFloat, isInteger, isNumber, isObject, isString,
}

void testCallback() {
    Environment env;
    json data;

    /*
     * Callbacks are defined by its:
     * - name,
     * - (optional) number of arguments,
     * - callback function.
     */
    env.add_callback("double", 1, [](Arguments& args) {
        int number = args.at(0)->get<int>(); // Adapt the index and type of the argument
        return 2 * number;
        });

    // You can then use a callback like a regular function
    env.render("{{ double(16) }}", data); // "32"

    // Inja falls back to variadic callbacks if the number of expected arguments is omitted.
    env.add_callback("argmax", [](Arguments& args) {
        auto result = std::max_element(args.begin(), args.end(), [](const json* a, const json* b) { return *a < *b; });
        return std::distance(args.begin(), result);
        });
    env.render("{{ argmax(4, 2, 6) }}", data); // "2"
    env.render("{{ argmax(0, 2, 6, 8, 3) }}", data); // "3"

    // A callback without argument can be used like a dynamic variable:
    std::string greet = "Hello";
    env.add_callback("double-greetings", 0, [greet](Arguments args) {
        return greet + " " + greet + "!";
        });
    env.render("{{ double-greetings }}", data); // "Hello Hello!"

    env.add_void_callback("log", 1, [greet](Arguments args) {
        std::cout << "logging: " << args[0] << std::endl;
        });
    env.render("{{ log(neighbour) }}", data); // Prints nothing to result, only to cout...
}

void test() {
    json data;
    data["name"] = "world";

    render("Hello {{ name }}!", data); // Returns std::string "Hello world!"
    render_to(std::cout, "Hello {{ name }}!", data); // Writes "Hello world!" to stream

    //testFile(); // 文件读写

    // With default settings
    Environment env_default;

    // With global path to template files and where files will be saved
    Environment env_1{ "../path/templates/" };

    // With separate input and output path
    Environment env_2{ "../path/templates/", "../path/results/" };

    // With other opening and closing strings (here the defaults)
    Environment env;
    env.set_expression("{{", "}}"); // Expressions
    env.set_comment("{#", "#}"); // Comments
    env.set_statement("{%", "%}"); // Statements {% %} for many things, see below
    env.set_line_statement("##"); // Line statements ## (just an opener)


    // json成员解析
    data["neighbour"] = "Peter";
    data["guests"] = { "Jeff", "Tom", "Patrick" };
    data["time"]["start"] = 16;
    data["time"]["end"] = 22;

    // Indexing in array
    render("{{ guests.1 }}", data); // "Tom"

    // Objects
    render("{{ time.start }} to {{ time.end + 1 }}pm", data); // "16 to 23pm"
    // If no variable is found, valid JSON is printed directly, otherwise an inja::RenderError is thrown.

    // Combining loops and line statements
    //render(R"(Guest List: ## for guest in guests {{ loop.index1 }}: {{ guest }} ## endfor )", data);
    // loop.is_first   loop.is_last  loop.parent.index   {% for key, value in time %}

    // Conditions
    // Standard comparisons with a variable
    render("{% if time.hour >= 20 %}Serve{% else if time.hour >= 18 %}Make{% endif %} dinner.", data); // Serve dinner.

    // Variable in list
    render("{% if neighbour in guests %}Turn up the music!{% endif %}", data); // Turn up the music!

    // Logical operations
    render("{% if guest_count < (3+2) and all_tired %}Sleepy...{% else %}Keep going...{% endif %}", data); // Sleepy...

    // Negations
    render("{% if not guest_count %}The End{% endif %}", data); // The End

    // To include in-memory templates, add them to the environment first
    inja::Template content_template = env.parse("Hello {{ neighbour }}!");
    env.include_template("content", content_template);
    env.render("Content: {% include \"content\" %}", data); // "Content: Hello Peter!"

    // Other template files are included relative from the current file location
    render("{% include \"footer.html\" %}", data);

    // The callback takes the current path and the wanted include name and returns a template
    env.set_include_callback([&env](const std::string& path, const std::string& template_name) {
        return env.parse("Hello {{ neighbour }} from " + template_name);
        });

    // You can disable to search for templates in the file system via
    env.set_search_included_templates_in_files(false);  // env.set_throw_at_missing_includes(false)

    render("{% set new_hour=23 %}{{ new_hour }}pm", data); // "23pm"
    render("{% set time.start=18 %}{{ time.start }}pm", data); // using json pointers

    env.set_trim_blocks(true);
    env.set_lstrip_blocks(true);

    render("Hello{# Todo #}!", data); // "Hello!"

    // INJA_NOEXCEPTION
}

// 从模板创建单例类
void createSingletonClass() {
    std::string tmplH = "class {{port}} {{name}} \n{\npublic:\n    using SP = std::shared_ptr<{{name}}>;\n\n    static {{name}} *getInstance();\n    static void release();\npublic:\n    static {{name}} *m_instance;\n};\n";
    std::string tmplCpp = "{{name}} *{{name}}::m_instance = nullptr;\n{{name}} *{{name}}::getInstance(){\n    if(!m_instance){\n     m_instnace = new {{name}}();\n    }\n    return m_instance;\n}\n";
    std::string tmplCpp2 = "void *{{name}}::release(){\n    if(m_instance){\n\tdelete m_instnace; \n    }\n    m_instance = nullptr;\n}\n";

    json data;
    data["name"] = "Singleton";
    data["port"] = "";
    render_to(std::cout, tmplH, data);
    render_to(std::cout, tmplCpp + tmplCpp2, data);
}

输出:

class  Singleton
{
public:
        using SP = std::shared_ptr<Singleton>;

        static Singleton *getInstance();
        static void release();
public:
        static Singleton *m_instance;
};
Singleton *Singleton::m_instance = nullptr;
Singleton *Singleton::getInstance(){
        if(!m_instance){
         m_instnace = new Singleton();
        }
        return m_instance;
}
void *Singleton::release(){
        if(m_instance){
        delete m_instnace;
        }
        m_instance = nullptr;
}


创作不易,小小的支持一下吧!

  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值