hemplate

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

commit c5294d1c704cdb3f305970a2e3ef46fa98e6fda1
parent 7b79f6bda1d93c11b4e581d375b585cb9bbe9c63
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Sat, 3 May 2025 11:26:24 +0200

Rename classes to common

Diffstat:
M CMakeLists.txt | ++ ---
M include/hemplate/atom.hpp | + -
D include/hemplate/classes.hpp | --------------------------------------------------------------
A include/hemplate/common.hpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M include/hemplate/html.hpp | + -
M include/hemplate/rss.hpp | + -
M include/hemplate/sitemap.hpp | + -
D source/classes.cpp | ------------------------------------------------------------
A source/common.cpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M test/CMakeLists.txt | + -
D test/source/classes_test.cpp | ---------------------------------------------------------------------------
A test/source/common_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

12 files changed, 204 insertions(+), 205 deletions(-)


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

@@ -13,13 +13,13 @@ project( include(cmake/project-is-top-level.cmake) include(cmake/variables.cmake)
find_package(based 0.1 CONFIG REQUIRED)
find_package(based 0.1.1 CONFIG REQUIRED)
# ---- Declare library ---- add_library( hemplate_hemplate
source/classes.cpp
source/common.cpp
source/attribute.cpp ) target_link_libraries(hemplate_hemplate PUBLIC based::based)

@@ -76,7 +76,6 @@ if(PROJECT_IS_TOP_LEVEL) endif() endif()
# ---- Developer mode ---- if(NOT hemplate_DEVELOPER_MODE)

diff --git a/ include/hemplate/atom.hpp b/ include/hemplate/atom.hpp

@@ -1,6 +1,6 @@ #pragma once
#include "hemplate/classes.hpp"
#include "hemplate/common.hpp"
#include "hemplate/hemplate_export.hpp" namespace hemplate::atom

diff --git a/ include/hemplate/classes.hpp b/ include/hemplate/classes.hpp

@@ -1,62 +0,0 @@
#pragma once
#include <array>
#include <based/string.hpp>
#include <based/type_traits.hpp>
#include "hemplate/element.hpp"
#include "hemplate/hemplate_export.hpp"
namespace hemplate
{
class HEMPLATE_EXPORT comment : public element
{
public:
explicit comment(std::string_view data)
: element(std::format("<-- {} -->", data))
{
}
};
class HEMPLATE_EXPORT xml : public element
{
static auto attrs(std::string_view version, std::string_view encoding)
{
return attribute_list {
{"version", version},
{"encoding", encoding},
};
}
public:
static constexpr const auto def_version = "1.0";
static constexpr const auto def_encoding = "UTF-8";
explicit xml(
std::string_view version = def_version,
std::string_view encoding = def_encoding
)
: element(std::format("<? xml {}?>", attrs(version, encoding)))
{
}
};
template<std::ranges::forward_range R>
element transform(
const R& range,
based::Procedure<element, std::ranges::range_value_t<R>> auto proc
)
{
std::vector<element> res;
res.reserve(std::size(range));
for (const auto& elem : range) {
res.emplace_back(proc(elem));
}
return element {res};
}
} // namespace hemplate

diff --git a/ include/hemplate/common.hpp b/ include/hemplate/common.hpp

@@ -0,0 +1,62 @@
#pragma once
#include <array>
#include <based/string.hpp>
#include <based/type_traits.hpp>
#include "hemplate/element.hpp"
#include "hemplate/hemplate_export.hpp"
namespace hemplate
{
class HEMPLATE_EXPORT comment : public element
{
public:
explicit comment(std::string_view data)
: element(std::format("<-- {} -->", data))
{
}
};
class HEMPLATE_EXPORT xml : public element
{
static auto attrs(std::string_view version, std::string_view encoding)
{
return attribute_list {
{"version", version},
{"encoding", encoding},
};
}
public:
static constexpr const auto def_version = "1.0";
static constexpr const auto def_encoding = "UTF-8";
explicit xml(
std::string_view version = def_version,
std::string_view encoding = def_encoding
)
: element(std::format("<? xml {}?>", attrs(version, encoding)))
{
}
};
template<std::ranges::forward_range R>
element transform(
const R& range,
based::Procedure<element, std::ranges::range_value_t<R>> auto proc
)
{
std::vector<element> res;
res.reserve(std::size(range));
for (const auto& elem : range) {
res.emplace_back(proc(elem));
}
return element {res};
}
} // namespace hemplate

diff --git a/ include/hemplate/html.hpp b/ include/hemplate/html.hpp

@@ -1,6 +1,6 @@ #pragma once
#include "hemplate/classes.hpp"
#include "hemplate/common.hpp"
namespace hemplate::html {

diff --git a/ include/hemplate/rss.hpp b/ include/hemplate/rss.hpp

@@ -1,6 +1,6 @@ #pragma once
#include "hemplate/classes.hpp"
#include "hemplate/common.hpp"
#include "hemplate/hemplate_export.hpp" namespace hemplate::rss

diff --git a/ include/hemplate/sitemap.hpp b/ include/hemplate/sitemap.hpp

@@ -1,6 +1,6 @@ #pragma once
#include "hemplate/classes.hpp"
#include "hemplate/common.hpp"
#include "hemplate/hemplate_export.hpp" namespace hemplate::sitemap

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

@@ -1,60 +0,0 @@
#include <chrono>
#include <ctime>
#include <format>
#include <string>
#include "hemplate/atom.hpp"
#include "hemplate/rss.hpp"
namespace
{
auto sec_since_epoch(int64_t sec)
{
return std::chrono::time_point_cast<std::chrono::seconds>(
std::chrono::system_clock::from_time_t(time_t {0})
+ std::chrono::seconds(sec)
);
}
auto get_time_now()
{
return std::chrono::current_zone()
->to_local(std::chrono::system_clock::now())
.time_since_epoch()
/ std::chrono::seconds(1);
}
} // namespace
namespace hemplate::atom
{
std::string format_time(int64_t sec)
{
static constexpr const char* rfc3339_f = "{:%FT%H:%M:%SZ}";
return std::format(rfc3339_f, sec_since_epoch(sec));
}
std::string format_time_now()
{
return format_time(get_time_now());
}
} // namespace hemplate::atom
namespace hemplate::rss
{
std::string format_time(int64_t sec)
{
static constexpr const char* rfc882_f = "{:%a, %d %b %Y %H:%M:%S %z}";
return std::format(rfc882_f, sec_since_epoch(sec));
}
std::string format_time_now()
{
return format_time(get_time_now());
}
} // namespace hemplate::rss

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

@@ -0,0 +1,60 @@
#include <chrono>
#include <ctime>
#include <format>
#include <string>
#include "hemplate/atom.hpp"
#include "hemplate/rss.hpp"
namespace
{
auto sec_since_epoch(int64_t sec)
{
return std::chrono::time_point_cast<std::chrono::seconds>(
std::chrono::system_clock::from_time_t(time_t {0})
+ std::chrono::seconds(sec)
);
}
auto get_time_now()
{
return std::chrono::current_zone()
->to_local(std::chrono::system_clock::now())
.time_since_epoch()
/ std::chrono::seconds(1);
}
} // namespace
namespace hemplate::atom
{
std::string format_time(int64_t sec)
{
static constexpr const char* rfc3339_f = "{:%FT%H:%M:%SZ}";
return std::format(rfc3339_f, sec_since_epoch(sec));
}
std::string format_time_now()
{
return format_time(get_time_now());
}
} // namespace hemplate::atom
namespace hemplate::rss
{
std::string format_time(int64_t sec)
{
static constexpr const char* rfc882_f = "{:%a, %d %b %Y %H:%M:%S %z}";
return std::format(rfc882_f, sec_since_epoch(sec));
}
std::string format_time_now()
{
return format_time(get_time_now());
}
} // namespace hemplate::rss

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

@@ -24,7 +24,7 @@ endfunction() add_test(attribute_test) add_test(attribute_list_test) add_test(element_test)
add_test(classes_test)
add_test(common_test)
add_test(html_test) add_test(atom_test) add_test(rss_test)

diff --git a/ test/source/classes_test.cpp b/ test/source/classes_test.cpp

@@ -1,75 +0,0 @@
#include "hemplate/classes.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("comment", "[classes/comment]")
{
const hemplate::comment comment {"hello world"};
REQUIRE(std::string(comment) == "<-- hello world -->\n");
}
TEST_CASE("xml", "[classes/xml]")
{
SECTION("default")
{
const hemplate::xml xml;
REQUIRE(
std::string(xml) == "<? xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version")
{
const hemplate::xml xml {"ver"};
REQUIRE(
std::string(xml) == "<? xml version=\"ver\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version encoding")
{
const hemplate::xml xml {"ver", "utf"};
REQUIRE(std::string(xml) == "<? xml version=\"ver\" encoding=\"utf\"?>\n");
}
}
TEST_CASE("transform", "[classes/transform]")
{
using tag = hemplate::element_boolean<"t">;
using child = hemplate::element_boolean<"c">;
SECTION("direct")
{
const std::vector<std::string> vec = {"1", "2"};
const auto t = tag {hemplate::transform(
vec,
[](const auto& e)
{
return child {e};
}
)};
REQUIRE(
std::string(t)
== "<t>\n <c>1</c>\n <c>2</c>\n</t>\n"
);
}
SECTION("indirect")
{
const std::vector<std::string> vec = {"1", "2"};
const auto t = tag {hemplate::transform(
vec,
[](const auto& e)
{
return hemplate::element {e};
}
)};
REQUIRE(std::string(t) == "<t>\n 1\n 2\n</t>\n");
}
}

diff --git a/ test/source/common_test.cpp b/ test/source/common_test.cpp

@@ -0,0 +1,75 @@
#include "hemplate/common.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("comment", "[common/comment]")
{
const hemplate::comment comment {"hello world"};
REQUIRE(std::string(comment) == "<-- hello world -->\n");
}
TEST_CASE("xml", "[common/xml]")
{
SECTION("default")
{
const hemplate::xml xml;
REQUIRE(
std::string(xml) == "<? xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version")
{
const hemplate::xml xml {"ver"};
REQUIRE(
std::string(xml) == "<? xml version=\"ver\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version encoding")
{
const hemplate::xml xml {"ver", "utf"};
REQUIRE(std::string(xml) == "<? xml version=\"ver\" encoding=\"utf\"?>\n");
}
}
TEST_CASE("transform", "[common/transform]")
{
using tag = hemplate::element_boolean<"t">;
using child = hemplate::element_boolean<"c">;
SECTION("direct")
{
const std::vector<std::string> vec = {"1", "2"};
const auto t = tag {hemplate::transform(
vec,
[](const auto& e)
{
return child {e};
}
)};
REQUIRE(
std::string(t)
== "<t>\n <c>1</c>\n <c>2</c>\n</t>\n"
);
}
SECTION("indirect")
{
const std::vector<std::string> vec = {"1", "2"};
const auto t = tag {hemplate::transform(
vec,
[](const auto& e)
{
return hemplate::element {e};
}
)};
REQUIRE(std::string(t) == "<t>\n 1\n 2\n</t>\n");
}
}