cemplate

Simple C++ template engine
git clone git://git.dimitrijedobrota.com/cemplate.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |

commit5997059066d9a7acd8b7a593ea86ca1b0a539cb0
parent36b5321d23281086549dbb857fdbcc39dbcf57fd
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateSat, 22 Feb 2025 22:57:32 +0100

Consolidate and check opening and closing

Diffstat:
MCMakeLists.txt|+-
Mexample/example.cpp|++++++++++++-----
Minclude/cemplate/cemplate.hpp|++++++-------
Msource/cemplate.cpp|++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------

4 files changed, 73 insertions(+), 24 deletions(-)


diff --git a/CMakeLists.txt b/CMakeLists.txt

@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)

project(
cemplate
VERSION 0.1.3
VERSION 0.1.4
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

@@ -12,12 +12,19 @@ int main()

std::cout << include("iostream");
std::cout << include("string");
std::cout << '\n';
std::cout << nspace("cemplate");
std::cout << func("test", "int", {});
std::cout << ret("3");
std::cout << func("test");
std::cout << func("test", "void", {{"int", "val1"}, {"std::string", "val2"}});
std::cout << func("test");
std::cout << func_decl("decl", "void", {});
std::cout << nspace("cemplate");
std::cout << func("void", "test", {});
std::cout << func_close();
std::cout << func("void", "test", {{"int", "val1"}, {"std::string", "val2"}});
std::cout << func_close();
std::cout << nspace_close("cemplate");
return 0;
}

diff --git a/include/cemplate/cemplate.hpp b/include/cemplate/cemplate.hpp

@@ -12,8 +12,6 @@ std::string include(const std::string& header, bool local = false);

std::string nspace(const std::string& name);
std::string nspace_close(const std::string& name);
std::string ret(const std::string& val);
struct param_t

@@ -22,11 +20,12 @@ struct param_t

std::string name;
};
std::string func(const std::string& ret,
const std::string& name,
std::vector<param_t> params,
bool delc = false);
std::string func(const std::string& name,
const std::string& ret = "",
const std::vector<param_t>& params = {});
std::string func_close();
std::string func_decl(const std::string& name,
const std::string& ret = "",
const std::vector<param_t>& params = {});
} // namespace cemplate

diff --git a/source/cemplate.cpp b/source/cemplate.cpp

@@ -1,10 +1,15 @@

#include <format>
#include <iostream>
#include <stack>
#include <unordered_set>
#include "cemplate/cemplate.hpp"
namespace cemplate
{
static std::uint32_t indent = 0; // NOLINT
std::string pragma_once()
{
return "#pragma once\n\n";

@@ -18,11 +23,24 @@ std::string include(const std::string& header, bool local)

std::string nspace(const std::string& name)
{
return std::format("namespace {}\n{{\n\n", name);
}
static std::unordered_set<std::string> seen;
static std::stack<std::string> stk;
std::string nspace_close(const std::string& name)
{
if (stk.empty() || stk.top() != name) {
if (seen.contains(name)) {
std::cerr << "Warning: nesting namespaces of the same name - " << name
<< '\n'
<< std::flush;
}
seen.insert(name);
stk.push(name);
return std::format("namespace {}\n{{\n\n", name);
}
seen.erase(name);
stk.pop();
return std::format("\n}} // namespace {}\n\n", name);
}

@@ -31,10 +49,9 @@ std::string ret(const std::string& val)

return std::format("return {};\n", val);
}
std::string func(const std::string& ret,
const std::string& name,
std::vector<param_t> params,
bool decl)
std::string func_helper(const std::string& name,
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; };

@@ -49,15 +66,41 @@ std::string func(const std::string& ret,

res += ", " + format(params[i]);
}
}
res += ')';
res += decl ? ";\n" : " {\n";
return res;
}
std::string func_close()
std::string func(const std::string& name,
const std::string& ret,
const std::vector<param_t>& params)
{
static std::string last;
if (last.empty()) {
if (ret.empty()) {
std::cerr << "Warning: function should have a return type - " << name
<< '\n'
<< std::flush;
}
last = name;
return func_helper(name, ret, params) + ") {\n";
}
if (last != name) {
std::cerr << "Warning: function is not closed - " << last << '\n'
<< std::flush;
}
last.clear();
return "}\n\n";
}
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";
}
} // namespace cemplate