cemplateSimple C++ template engine |
git clone git://git.dimitrijedobrota.com/cemplate.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 51cc42e95b4ed60855abf0b74cf22fc1fb8a4c8f |
parent | 9c7f4ab5de0c9e4042a356a239bb497537b22061 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sun, 23 Feb 2025 15:54:19 +0100 |
Handle indent; Add initlist, decl, string
Diffstat:M | .clang-tidy | | | + |
M | CMakeLists.txt | | | +- |
M | example/example.cpp | | | ++++ |
M | include/cemplate/cemplate.hpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
M | source/cemplate.cpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
5 files changed, 140 insertions(+), 23 deletions(-)
diff --git a/.clang-tidy b/.clang-tidy
@@ -18,6 +18,7 @@ Checks: "*,\
-modernize-use-ranges,\
-modernize-use-trailing-return-type,\
-misc-include-cleaner,\
-misc-no-recursion,\
"
WarningsAsErrors: ''
CheckOptions:
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
cemplate
VERSION 0.1.5
VERSION 0.1.6
DESCRIPTION "Simple C++ template engine"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/cemplate.git"
LANGUAGES CXX
diff --git a/example/example.cpp b/example/example.cpp
@@ -23,6 +23,10 @@ int main()
std::cout << func("test");
std::cout << func_decl("decl", "void", {});
std::cout << '\n';
std::cout << "static const test_class test = ";
std::cout << initlist({"val11", "val12", {"val21", "val22"}, "val13"});
std::cout << nspace("cemplate");
diff --git a/include/cemplate/cemplate.hpp b/include/cemplate/cemplate.hpp
@@ -1,11 +1,68 @@
#pragma once
#include <cstdint>
#include <string>
#include <variant>
#include <vector>
namespace cemplate
{
struct param_t
{
std::string type;
std::string name;
};
struct initlist_elem;
struct initlist
{
std::string format(std::uint64_t lvl) const;
friend std::ostream& operator<<(std::ostream& ost, const initlist& list);
template<typename... Args>
void emplace_back(Args... args)
{
values.emplace_back(std::forward<Args>(args)...);
}
std::vector<initlist_elem> values; // NOLINT
};
struct initlist_elem
{
initlist_elem(std::string value) // NOLINT
: m_value(std::move(value))
{
}
initlist_elem(std::string_view value) // NOLINT
: m_value(std::in_place_type<std::string>, value)
{
}
initlist_elem(const char* value) // NOLINT
: m_value(value)
{
}
initlist_elem(std::initializer_list<initlist_elem> list) // NOLINT
: m_value(std::in_place_type<initlist>, list)
{
}
initlist_elem(initlist list) // NOLINT
: m_value(std::move(list))
{
}
const auto& value() const { return m_value; }
private:
std::variant<std::string, initlist> m_value;
};
std::string pragma_once();
std::string include(const std::string& header, bool local = false);
@@ -14,11 +71,9 @@ std::string nspace(const std::string& name);
std::string ret(const std::string& val);
struct param_t
{
std::string type;
std::string name;
};
std::string string(const std::string& string);
std::string decl(const std::string& type, const std::string& name);
std::string func(const std::string& name,
const std::string& ret = "",
diff --git a/source/cemplate.cpp b/source/cemplate.cpp
@@ -1,4 +1,5 @@
#include <format>
#include <functional>
#include <iostream>
#include <stack>
#include <unordered_set>
@@ -8,6 +9,13 @@
namespace
{
static std::uint64_t indent_lvl = 0; // NOLINT
auto indent(std::uint64_t lvl = indent_lvl)
{
return std::string(lvl * 2, ' ');
}
void warning(const std::string& message, const std::string& addition) // NOLINT
{
std::cerr << "Warning: " << message;
@@ -17,13 +25,28 @@ void warning(const std::string& message, const std::string& addition) // NOLINT
std::cerr << '\n' << std::flush;
}
template<typename T>
std::string accumulate(const std::vector<T>& values,
const std::function<std::string(const T&)>& format,
const std::string& delim)
{
std::string res;
if (!values.empty()) {
res += format(values[0]);
for (std::size_t i = 1; i < values.size(); i++) {
res += delim + format(values[i]);
}
}
return res;
}
} // namespace
namespace cemplate
{
static std::uint32_t indent = 0; // NOLINT
std::string pragma_once()
{
return "#pragma once\n\n";
@@ -58,30 +81,62 @@ std::string nspace(const std::string& name)
std::string ret(const std::string& val)
{
return std::format("return {};\n", val);
return std::format("{}return {};\n", indent(), val);
}
std::string func_helper(const std::string& name,
const std::string& ret,
const std::vector<param_t>& params)
std::string string(const std::string& string)
{
static const auto format = [](const param_t& param)
{ return param.name.empty() ? param.type : param.type + ' ' + param.name; };
return std::format(R"("{}")", string);
}
std::string decl(const std::string& type, const std::string& name)
{
return std::format("{}{} {} = ", indent(), type, name);
}
std::string eval(const std::string& val, std::uint64_t lvl); // NOLINT
std::string eval(const initlist& list, std::uint64_t lvl); // NOLINT
std::string initlist::format(uint64_t lvl) const
{
std::string res;
res += ret + ' ';
res += name + '(';
if (!params.empty()) {
res += format(params[0]);
for (std::size_t i = 1; i < params.size(); i++) {
res += ", " + format(params[i]);
}
for (const auto& node : values) {
std::visit([&](const auto& value) { res += eval(value, lvl + 1); },
node.value());
}
return res;
}
std::string eval(const initlist& list, std::uint64_t lvl)
{
return std::format(
"{}{{\n{}{}}},\n", indent(lvl), list.format(lvl + 1), indent(lvl));
}
std::string eval(const std::string& val, std::uint64_t lvl)
{
return std::format("{}{},\n", indent(lvl), val);
}
std::ostream& operator<<(std::ostream& ost, const initlist& list)
{
return ost << std::format(
"{{\n{}{}}};\n", list.format(indent_lvl + 1), indent());
}
std::string func_helper(const std::string& name, // NOLINT
const std::string& ret,
const std::vector<param_t>& params)
{
static const auto format = [](const param_t& param)
{ return param.name.empty() ? param.type : param.type + ' ' + param.name; };
return std::format(
"{} {}({})", ret, name, accumulate<param_t>(params, format, ", "));
}
std::string func(const std::string& name,
const std::string& ret,
const std::vector<param_t>& params)
@@ -94,7 +149,8 @@ std::string func(const std::string& name,
}
last = name;
return func_helper(name, ret, params) + ") {\n";
indent_lvl++;
return func_helper(name, ret, params) + " {\n";
}
if (last != name) {
@@ -102,6 +158,7 @@ std::string func(const std::string& name,
}
last.clear();
indent_lvl--;
return "}\n\n";
}
@@ -109,7 +166,7 @@ std::string func_decl(const std::string& name,
const std::string& ret,
const std::vector<param_t>& params)
{
return func_helper(name, ret, params) + ");\n";
return func_helper(name, ret, params) + ";\n";
}
} // namespace cemplate