Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

throw exception if a file cannot be opened, fix travis-ci builds #117

Merged
merged 4 commits into from
Sep 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ target_include_directories(inja INTERFACE
$<INSTALL_INTERFACE:${INJA_INSTALL_INCLUDE_DIR}>
)

# target_compile_features(inja INTERFACE cxx_std_11)
target_compile_features(inja INTERFACE cxx_std_11)

set(INJA_PACKAGE_USE_EMBEDDED_JSON OFF)

Expand Down Expand Up @@ -89,6 +89,7 @@ if(BUILD_TESTING)


add_library(single_inja INTERFACE)
target_compile_features(single_inja INTERFACE cxx_std_11)
target_include_directories(single_inja INTERFACE single_include include third_party/include)

add_executable(single_inja_test
Expand Down
3 changes: 2 additions & 1 deletion include/inja/environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "renderer.hpp"
#include "string_view.hpp"
#include "template.hpp"
#include "utils.hpp"


namespace inja {
Expand Down Expand Up @@ -144,7 +145,7 @@ class Environment {
}

json load_json(const std::string& filename) {
std::ifstream file(m_impl->input_path + filename);
std::ifstream file = open_file_or_throw(m_impl->input_path + filename);
json j;
file >> j;
return j;
Expand Down
8 changes: 5 additions & 3 deletions include/inja/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,10 @@ class Parser {
}
// sys::path::remove_dots(pathname, true, sys::path::Style::posix);

Template include_template = parse_template(pathname);
m_included_templates.emplace(pathname, include_template);
if (m_included_templates.find(pathname) == m_included_templates.end()) {
Template include_template = parse_template(pathname);
m_included_templates.emplace(pathname, include_template);
}

// generate a reference bytecode
tmpl.bytecodes.emplace_back(Bytecode::Op::Include, json(pathname), Bytecode::Flag::ValueImmediate);
Expand Down Expand Up @@ -505,7 +507,7 @@ class Parser {
}

std::string load_file(nonstd::string_view filename) {
std::ifstream file(static_cast<std::string>(filename));
std::ifstream file = open_file_or_throw(static_cast<std::string>(filename));
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
return text;
}
Expand Down
12 changes: 12 additions & 0 deletions include/inja/utils.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef PANTOR_INJA_UTILS_HPP
#define PANTOR_INJA_UTILS_HPP

#include <fstream>
#include <stdexcept>

#include "string_view.hpp"
Expand All @@ -12,6 +13,17 @@ inline void inja_throw(const std::string& type, const std::string& message) {
throw std::runtime_error("[inja.exception." + type + "] " + message);
}

inline std::ifstream open_file_or_throw(const std::string& path) {
std::ifstream file;
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
file.open(path);
} catch(const std::ios_base::failure& e) {
inja_throw("file_error", "failed accessing file at '" + path + "'");
}
return file;
}

namespace string_view {
inline nonstd::string_view slice(nonstd::string_view view, size_t start, size_t end) {
start = std::min(start, view.size());
Expand Down
24 changes: 20 additions & 4 deletions single_include/inja/inja.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,7 @@ struct Token {
#ifndef PANTOR_INJA_UTILS_HPP
#define PANTOR_INJA_UTILS_HPP

#include <fstream>
#include <stdexcept>

// #include "string_view.hpp"
Expand All @@ -1705,6 +1706,17 @@ inline void inja_throw(const std::string& type, const std::string& message) {
throw std::runtime_error("[inja.exception." + type + "] " + message);
}

inline std::ifstream open_file_or_throw(const std::string& path) {
std::ifstream file;
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
file.open(path);
} catch(const std::ios_base::failure& e) {
inja_throw("file_error", "failed accessing file at '" + path + "'");
}
return file;
}

namespace string_view {
inline nonstd::string_view slice(nonstd::string_view view, size_t start, size_t end) {
start = std::min(start, view.size());
Expand Down Expand Up @@ -2384,8 +2396,10 @@ class Parser {
}
// sys::path::remove_dots(pathname, true, sys::path::Style::posix);

Template include_template = parse_template(pathname);
m_included_templates.emplace(pathname, include_template);
if (m_included_templates.find(pathname) == m_included_templates.end()) {
Template include_template = parse_template(pathname);
m_included_templates.emplace(pathname, include_template);
}

// generate a reference bytecode
tmpl.bytecodes.emplace_back(Bytecode::Op::Include, json(pathname), Bytecode::Flag::ValueImmediate);
Expand Down Expand Up @@ -2505,7 +2519,7 @@ class Parser {
}

std::string load_file(nonstd::string_view filename) {
std::ifstream file(static_cast<std::string>(filename));
std::ifstream file = open_file_or_throw(static_cast<std::string>(filename));
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
return text;
}
Expand Down Expand Up @@ -3184,6 +3198,8 @@ class Renderer {

// #include "template.hpp"

// #include "utils.hpp"



namespace inja {
Expand Down Expand Up @@ -3313,7 +3329,7 @@ class Environment {
}

json load_json(const std::string& filename) {
std::ifstream file(m_impl->input_path + filename);
std::ifstream file = open_file_or_throw(m_impl->input_path + filename);
json j;
file >> j;
return j;
Expand Down
6 changes: 6 additions & 0 deletions test/unit-files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ TEST_CASE("loading") {
SECTION("File includes should be rendered") {
CHECK( env.render_file(test_file_directory + "include.txt", data) == "Answer: Hello Jeff." );
}

SECTION("File error should throw") {
std::string path(test_file_directory + "does-not-exist");
CHECK_THROWS_WITH( env.load_file(path), "[inja.exception.file_error] failed accessing file at '" + path + "'" );
CHECK_THROWS_WITH( env.load_json(path), "[inja.exception.file_error] failed accessing file at '" + path + "'" );
}
}

TEST_CASE("complete-files") {
Expand Down
1 change: 1 addition & 0 deletions test/unit-renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ TEST_CASE("templates") {

inja::Template t2 = env.parse("{% include \"greeting\" %}!");
CHECK( env.render(t2, data) == "Hello Peter!" );
CHECK_THROWS_WITH( env.parse("{% include \"does-not-exist\" %}!"), "[inja.exception.file_error] failed accessing file at 'does-not-exist'" );
}
}

Expand Down