diff --git a/isis/src/base/apps/topds4/20190612T090019S776_map_L0pan.xml.tpl b/isis/src/base/apps/topds4/20190612T090019S776_map_L0pan.xml.tpl
new file mode 100644
index 0000000000..4eddb57ad9
--- /dev/null
+++ b/isis/src/base/apps/topds4/20190612T090019S776_map_L0pan.xml.tpl
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+ filename
+ dateandtime
+ filesize
+
+
+ headeroffset
+ headerLength
+ fileType
+
+
+ Active Area
+ imageOffsetBytes
+ numAxes
+ Last Index Fastest
+ OCAMS image 1024 by 1024 pixel active array.
+
+ bitType
+ DN
+ 1
+ WHAT IS THIS
+
+
+ Line
+ {{MainLabel.IsisCube.Core.Dimensions.Lines.Value}}
+ 1
+
+
+ Sample
+ {{MainLabel.IsisCube.Core.Dimensions.Samples.Value}}
+ 2
+
+
+
+
diff --git a/isis/src/base/apps/topds4/config.h b/isis/src/base/apps/topds4/config.h
deleted file mode 100644
index 201a429f36..0000000000
--- a/isis/src/base/apps/topds4/config.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2019 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_CONFIG_HPP_
-#define INCLUDE_INJA_CONFIG_HPP_
-
-#include
-#include
-
-#include "string_view.h"
-
-namespace inja {
-
-/*!
- * \brief Class for lexer configuration.
- */
-struct LexerConfig {
- std::string statement_open {"{%"};
- std::string statement_open_no_lstrip {"{%+"};
- std::string statement_open_force_lstrip {"{%-"};
- std::string statement_close {"%}"};
- std::string statement_close_force_rstrip {"-%}"};
- std::string line_statement {"##"};
- std::string expression_open {"{{"};
- std::string expression_open_force_lstrip {"{{-"};
- std::string expression_close {"}}"};
- std::string expression_close_force_rstrip {"-}}"};
- std::string comment_open {"{#"};
- std::string comment_close {"#}"};
- std::string open_chars {"#{"};
-
- bool trim_blocks {false};
- bool lstrip_blocks {false};
-
- void update_open_chars() {
- open_chars = "";
- if (open_chars.find(line_statement[0]) == std::string::npos) {
- open_chars += line_statement[0];
- }
- if (open_chars.find(statement_open[0]) == std::string::npos) {
- open_chars += statement_open[0];
- }
- if (open_chars.find(statement_open_no_lstrip[0]) == std::string::npos) {
- open_chars += statement_open_no_lstrip[0];
- }
- if (open_chars.find(statement_open_force_lstrip[0]) == std::string::npos) {
- open_chars += statement_open_force_lstrip[0];
- }
- if (open_chars.find(expression_open[0]) == std::string::npos) {
- open_chars += expression_open[0];
- }
- if (open_chars.find(expression_open_force_lstrip[0]) == std::string::npos) {
- open_chars += expression_open_force_lstrip[0];
- }
- if (open_chars.find(comment_open[0]) == std::string::npos) {
- open_chars += comment_open[0];
- }
- }
-};
-
-/*!
- * \brief Class for parser configuration.
- */
-struct ParserConfig {
- bool search_included_templates_in_files {true};
-};
-
-/*!
- * \brief Class for render configuration.
- */
-struct RenderConfig {
- bool throw_at_missing_includes {true};
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_CONFIG_HPP_
diff --git a/isis/src/base/apps/topds4/environment2.h b/isis/src/base/apps/topds4/environment2.h
deleted file mode 100644
index 730496be7d..0000000000
--- a/isis/src/base/apps/topds4/environment2.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2019 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
-#define INCLUDE_INJA_ENVIRONMENT_HPP_
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "config.h"
-#include "function_storage.h"
-#include "parser.h"
-#include "renderer.h"
-#include "string_view.h"
-#include "template2.h"
-#include "utils.h"
-
-namespace inja {
-
-using json = nlohmann::json;
-
-/*!
- * \brief Class for changing the configuration.
- */
-class Environment {
- std::string input_path;
- std::string output_path;
-
- LexerConfig lexer_config;
- ParserConfig parser_config;
- RenderConfig render_config;
-
- FunctionStorage function_storage;
- TemplateStorage template_storage;
-
-public:
- Environment() : Environment("") {}
-
- explicit Environment(const std::string &global_path) : input_path(global_path), output_path(global_path) {}
-
- Environment(const std::string &input_path, const std::string &output_path)
- : input_path(input_path), output_path(output_path) {}
-
- /// Sets the opener and closer for template statements
- void set_statement(const std::string &open, const std::string &close) {
- lexer_config.statement_open = open;
- lexer_config.statement_open_no_lstrip = open + "+";
- lexer_config.statement_open_force_lstrip = open + "-";
- lexer_config.statement_close = close;
- lexer_config.statement_close_force_rstrip = "-" + close;
- lexer_config.update_open_chars();
- }
-
- /// Sets the opener for template line statements
- void set_line_statement(const std::string &open) {
- lexer_config.line_statement = open;
- lexer_config.update_open_chars();
- }
-
- /// Sets the opener and closer for template expressions
- void set_expression(const std::string &open, const std::string &close) {
- lexer_config.expression_open = open;
- lexer_config.expression_open_force_lstrip = open + "-";
- lexer_config.expression_close = close;
- lexer_config.expression_close_force_rstrip = "-" + close;
- lexer_config.update_open_chars();
- }
-
- /// Sets the opener and closer for template comments
- void set_comment(const std::string &open, const std::string &close) {
- lexer_config.comment_open = open;
- lexer_config.comment_close = close;
- lexer_config.update_open_chars();
- }
-
- /// Sets whether to remove the first newline after a block
- void set_trim_blocks(bool trim_blocks) {
- lexer_config.trim_blocks = trim_blocks;
- }
-
- /// Sets whether to strip the spaces and tabs from the start of a line to a block
- void set_lstrip_blocks(bool lstrip_blocks) {
- lexer_config.lstrip_blocks = lstrip_blocks;
- }
-
- /// Sets the element notation syntax
- void set_search_included_templates_in_files(bool search_in_files) {
- parser_config.search_included_templates_in_files = search_in_files;
- }
-
- /// Sets whether a missing include will throw an error
- void set_throw_at_missing_includes(bool will_throw) {
- render_config.throw_at_missing_includes = will_throw;
- }
-
- Template parse(nonstd::string_view input) {
- Parser parser(parser_config, lexer_config, template_storage, function_storage);
- return parser.parse(input);
- }
-
- Template parse_template(const std::string &filename) {
- Parser parser(parser_config, lexer_config, template_storage, function_storage);
- auto result = Template(parser.load_file(input_path + static_cast(filename)));
- parser.parse_into_template(result, input_path + static_cast(filename));
- return result;
- }
-
- Template parse_file(const std::string &filename) {
- return parse_template(filename);
- }
-
- std::string render(nonstd::string_view input, const json &data) { return render(parse(input), data); }
-
- std::string render(const Template &tmpl, const json &data) {
- std::stringstream os;
- render_to(os, tmpl, data);
- return os.str();
- }
-
- std::string render_file(const std::string &filename, const json &data) {
- return render(parse_template(filename), data);
- }
-
- std::string render_file_with_json_file(const std::string &filename, const std::string &filename_data) {
- const json data = load_json(filename_data);
- return render_file(filename, data);
- }
-
- void write(const std::string &filename, const json &data, const std::string &filename_out) {
- std::ofstream file(output_path + filename_out);
- file << render_file(filename, data);
- file.close();
- }
-
- void write(const Template &temp, const json &data, const std::string &filename_out) {
- std::ofstream file(output_path + filename_out);
- file << render(temp, data);
- file.close();
- }
-
- void write_with_json_file(const std::string &filename, const std::string &filename_data,
- const std::string &filename_out) {
- const json data = load_json(filename_data);
- write(filename, data, filename_out);
- }
-
- void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out) {
- const json data = load_json(filename_data);
- write(temp, data, filename_out);
- }
-
- std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) {
- Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
- return os;
- }
-
- std::string load_file(const std::string &filename) {
- Parser parser(parser_config, lexer_config, template_storage, function_storage);
- return parser.load_file(input_path + filename);
- }
-
- json load_json(const std::string &filename) {
- std::ifstream file;
- open_file_or_throw(input_path + filename, file);
- json j;
- file >> j;
- return j;
- }
-
- /*!
- @brief Adds a variadic callback
- */
- void add_callback(const std::string &name, const CallbackFunction &callback) {
- add_callback(name, -1, callback);
- }
-
- /*!
- @brief Adds a variadic void callback
- */
- void add_void_callback(const std::string &name, const VoidCallbackFunction &callback) {
- add_void_callback(name, -1, callback);
- }
-
- /*!
- @brief Adds a callback with given number or arguments
- */
- void add_callback(const std::string &name, int num_args, const CallbackFunction &callback) {
- function_storage.add_callback(name, num_args, callback);
- }
-
- /*!
- @brief Adds a void callback with given number or arguments
- */
- void add_void_callback(const std::string &name, int num_args, const VoidCallbackFunction &callback) {
- function_storage.add_callback(name, num_args, [callback](Arguments& args) { callback(args); return json(); });
- }
-
- /** Includes a template with a given name into the environment.
- * Then, a template can be rendered in another template using the
- * include "" syntax.
- */
- void include_template(const std::string &name, const Template &tmpl) {
- template_storage[name] = tmpl;
- }
-};
-
-/*!
-@brief render with default settings to a string
-*/
-inline std::string render(nonstd::string_view input, const json &data) {
- return Environment().render(input, data);
-}
-
-/*!
-@brief render with default settings to the given output stream
-*/
-inline void render_to(std::ostream &os, nonstd::string_view input, const json &data) {
- Environment env;
- env.render_to(os, env.parse(input), data);
-}
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_ENVIRONMENT_HPP_
diff --git a/isis/src/base/apps/topds4/exceptions.h b/isis/src/base/apps/topds4/exceptions.h
deleted file mode 100644
index 2784da8188..0000000000
--- a/isis/src/base/apps/topds4/exceptions.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
-#define INCLUDE_INJA_EXCEPTIONS_HPP_
-
-#include
-#include
-
-namespace inja {
-
-struct SourceLocation {
- size_t line;
- size_t column;
-};
-
-struct InjaError : public std::runtime_error {
- const std::string type;
- const std::string message;
-
- const SourceLocation location;
-
- explicit InjaError(const std::string &type, const std::string &message)
- : std::runtime_error("[inja.exception." + type + "] " + message), type(type), message(message), location({0, 0}) {}
-
- explicit InjaError(const std::string &type, const std::string &message, SourceLocation location)
- : std::runtime_error("[inja.exception." + type + "] (at " + std::to_string(location.line) + ":" +
- std::to_string(location.column) + ") " + message),
- type(type), message(message), location(location) {}
-};
-
-struct ParserError : public InjaError {
- explicit ParserError(const std::string &message, SourceLocation location) : InjaError("parser_error", message, location) {}
-};
-
-struct RenderError : public InjaError {
- explicit RenderError(const std::string &message, SourceLocation location) : InjaError("render_error", message, location) {}
-};
-
-struct FileError : public InjaError {
- explicit FileError(const std::string &message) : InjaError("file_error", message) {}
- explicit FileError(const std::string &message, SourceLocation location) : InjaError("file_error", message, location) {}
-};
-
-struct JsonError : public InjaError {
- explicit JsonError(const std::string &message, SourceLocation location) : InjaError("json_error", message, location) {}
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_EXCEPTIONS_HPP_
diff --git a/isis/src/base/apps/topds4/function_storage.h b/isis/src/base/apps/topds4/function_storage.h
deleted file mode 100644
index 3aec3c7014..0000000000
--- a/isis/src/base/apps/topds4/function_storage.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
-#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
-
-#include
-
-#include "string_view.h"
-
-namespace inja {
-
-using json = nlohmann::json;
-
-using Arguments = std::vector;
-using CallbackFunction = std::function;
-using VoidCallbackFunction = std::function;
-
-/*!
- * \brief Class for builtin functions and user-defined callbacks.
- */
-class FunctionStorage {
-public:
- enum class Operation {
- Not,
- And,
- Or,
- In,
- Equal,
- NotEqual,
- Greater,
- GreaterEqual,
- Less,
- LessEqual,
- Add,
- Subtract,
- Multiplication,
- Division,
- Power,
- Modulo,
- AtId,
- At,
- Default,
- DivisibleBy,
- Even,
- Exists,
- ExistsInObject,
- First,
- Float,
- Int,
- IsArray,
- IsBoolean,
- IsFloat,
- IsInteger,
- IsNumber,
- IsObject,
- IsString,
- Last,
- Length,
- Lower,
- Max,
- Min,
- Odd,
- Range,
- Round,
- Sort,
- Upper,
- Callback,
- ParenLeft,
- ParenRight,
- None,
- };
-
- struct FunctionData {
- explicit FunctionData(const Operation &op, const CallbackFunction &cb = CallbackFunction{}) : operation(op), callback(cb) {}
- const Operation operation;
- const CallbackFunction callback;
- };
-
-private:
- const int VARIADIC {-1};
-
- std::map, FunctionData> function_storage = {
- {std::make_pair("at", 2), FunctionData { Operation::At }},
- {std::make_pair("default", 2), FunctionData { Operation::Default }},
- {std::make_pair("divisibleBy", 2), FunctionData { Operation::DivisibleBy }},
- {std::make_pair("even", 1), FunctionData { Operation::Even }},
- {std::make_pair("exists", 1), FunctionData { Operation::Exists }},
- {std::make_pair("existsIn", 2), FunctionData { Operation::ExistsInObject }},
- {std::make_pair("first", 1), FunctionData { Operation::First }},
- {std::make_pair("float", 1), FunctionData { Operation::Float }},
- {std::make_pair("int", 1), FunctionData { Operation::Int }},
- {std::make_pair("isArray", 1), FunctionData { Operation::IsArray }},
- {std::make_pair("isBoolean", 1), FunctionData { Operation::IsBoolean }},
- {std::make_pair("isFloat", 1), FunctionData { Operation::IsFloat }},
- {std::make_pair("isInteger", 1), FunctionData { Operation::IsInteger }},
- {std::make_pair("isNumber", 1), FunctionData { Operation::IsNumber }},
- {std::make_pair("isObject", 1), FunctionData { Operation::IsObject }},
- {std::make_pair("isString", 1), FunctionData { Operation::IsString }},
- {std::make_pair("last", 1), FunctionData { Operation::Last }},
- {std::make_pair("length", 1), FunctionData { Operation::Length }},
- {std::make_pair("lower", 1), FunctionData { Operation::Lower }},
- {std::make_pair("max", 1), FunctionData { Operation::Max }},
- {std::make_pair("min", 1), FunctionData { Operation::Min }},
- {std::make_pair("odd", 1), FunctionData { Operation::Odd }},
- {std::make_pair("range", 1), FunctionData { Operation::Range }},
- {std::make_pair("round", 2), FunctionData { Operation::Round }},
- {std::make_pair("sort", 1), FunctionData { Operation::Sort }},
- {std::make_pair("upper", 1), FunctionData { Operation::Upper }},
- };
-
-public:
- void add_builtin(nonstd::string_view name, int num_args, Operation op) {
- function_storage.emplace(std::make_pair(static_cast(name), num_args), FunctionData { op });
- }
-
- void add_callback(nonstd::string_view name, int num_args, const CallbackFunction &callback) {
- function_storage.emplace(std::make_pair(static_cast(name), num_args), FunctionData { Operation::Callback, callback });
- }
-
- FunctionData find_function(nonstd::string_view name, int num_args) const {
- auto it = function_storage.find(std::make_pair(static_cast(name), num_args));
- if (it != function_storage.end()) {
- return it->second;
-
- // Find variadic function
- } else if (num_args > 0) {
- it = function_storage.find(std::make_pair(static_cast(name), VARIADIC));
- if (it != function_storage.end()) {
- return it->second;
- }
- }
-
- return FunctionData { Operation::None };
- }
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_FUNCTION_STORAGE_HPP_
diff --git a/isis/src/base/apps/topds4/inja.h b/isis/src/base/apps/topds4/inja.h
deleted file mode 100644
index bb0d6e8f33..0000000000
--- a/isis/src/base/apps/topds4/inja.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_INJA_HPP_
-#define INCLUDE_INJA_INJA_HPP_
-
-#include
-
-#include "environment2.h"
-#include "exceptions.h"
-#include "parser.h"
-#include "renderer.h"
-#include "string_view.h"
-#include "template2.h"
-
-#endif // INCLUDE_INJA_INJA_HPP_
diff --git a/isis/src/base/apps/topds4/lexer.h b/isis/src/base/apps/topds4/lexer.h
deleted file mode 100644
index 3fbaa96218..0000000000
--- a/isis/src/base/apps/topds4/lexer.h
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_LEXER_HPP_
-#define INCLUDE_INJA_LEXER_HPP_
-
-#include
-#include
-
-#include "config.h"
-#include "token.h"
-#include "utils.h"
-
-namespace inja {
-
-/*!
- * \brief Class for lexing an inja Template.
- */
-class Lexer {
- enum class State {
- Text,
- ExpressionStart,
- ExpressionStartForceLstrip,
- ExpressionBody,
- LineStart,
- LineBody,
- StatementStart,
- StatementStartNoLstrip,
- StatementStartForceLstrip,
- StatementBody,
- CommentStart,
- CommentBody,
- };
-
- enum class MinusState {
- Operator,
- Number,
- };
-
- const LexerConfig &config;
-
- State state;
- MinusState minus_state;
- nonstd::string_view m_in;
- size_t tok_start;
- size_t pos;
-
-
- Token scan_body(nonstd::string_view close, Token::Kind closeKind, nonstd::string_view close_trim = nonstd::string_view(), bool trim = false) {
- again:
- // skip whitespace (except for \n as it might be a close)
- if (tok_start >= m_in.size()) {
- return make_token(Token::Kind::Eof);
- }
- char ch = m_in[tok_start];
- if (ch == ' ' || ch == '\t' || ch == '\r') {
- tok_start += 1;
- goto again;
- }
-
- // check for close
- if (!close_trim.empty() && inja::string_view::starts_with(m_in.substr(tok_start), close_trim)) {
- state = State::Text;
- pos = tok_start + close_trim.size();
- Token tok = make_token(closeKind);
- skip_whitespaces_and_newlines();
- return tok;
- }
-
- if (inja::string_view::starts_with(m_in.substr(tok_start), close)) {
- state = State::Text;
- pos = tok_start + close.size();
- Token tok = make_token(closeKind);
- if (trim) {
- skip_whitespaces_and_first_newline();
- }
- return tok;
- }
-
- // skip \n
- if (ch == '\n') {
- tok_start += 1;
- goto again;
- }
-
- pos = tok_start + 1;
- if (std::isalpha(ch)) {
- minus_state = MinusState::Operator;
- return scan_id();
- }
-
- MinusState current_minus_state = minus_state;
- if (minus_state == MinusState::Operator) {
- minus_state = MinusState::Number;
- }
-
- switch (ch) {
- case '+':
- return make_token(Token::Kind::Plus);
- case '-':
- if (current_minus_state == MinusState::Operator) {
- return make_token(Token::Kind::Minus);
- }
- return scan_number();
- case '*':
- return make_token(Token::Kind::Times);
- case '/':
- return make_token(Token::Kind::Slash);
- case '^':
- return make_token(Token::Kind::Power);
- case '%':
- return make_token(Token::Kind::Percent);
- case '.':
- return make_token(Token::Kind::Dot);
- case ',':
- return make_token(Token::Kind::Comma);
- case ':':
- return make_token(Token::Kind::Colon);
- case '(':
- return make_token(Token::Kind::LeftParen);
- case ')':
- minus_state = MinusState::Operator;
- return make_token(Token::Kind::RightParen);
- case '[':
- return make_token(Token::Kind::LeftBracket);
- case ']':
- minus_state = MinusState::Operator;
- return make_token(Token::Kind::RightBracket);
- case '{':
- return make_token(Token::Kind::LeftBrace);
- case '}':
- minus_state = MinusState::Operator;
- return make_token(Token::Kind::RightBrace);
- case '>':
- if (pos < m_in.size() && m_in[pos] == '=') {
- pos += 1;
- return make_token(Token::Kind::GreaterEqual);
- }
- return make_token(Token::Kind::GreaterThan);
- case '<':
- if (pos < m_in.size() && m_in[pos] == '=') {
- pos += 1;
- return make_token(Token::Kind::LessEqual);
- }
- return make_token(Token::Kind::LessThan);
- case '=':
- if (pos < m_in.size() && m_in[pos] == '=') {
- pos += 1;
- return make_token(Token::Kind::Equal);
- }
- return make_token(Token::Kind::Unknown);
- case '!':
- if (pos < m_in.size() && m_in[pos] == '=') {
- pos += 1;
- return make_token(Token::Kind::NotEqual);
- }
- return make_token(Token::Kind::Unknown);
- case '\"':
- return scan_string();
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- minus_state = MinusState::Operator;
- return scan_number();
- case '_':
- minus_state = MinusState::Operator;
- return scan_id();
- default:
- return make_token(Token::Kind::Unknown);
- }
- }
-
- Token scan_id() {
- for (;;) {
- if (pos >= m_in.size()) {
- break;
- }
- char ch = m_in[pos];
- if (!std::isalnum(ch) && ch != '.' && ch != '/' && ch != '_' && ch != '-') {
- break;
- }
- pos += 1;
- }
- return make_token(Token::Kind::Id);
- }
-
- Token scan_number() {
- for (;;) {
- if (pos >= m_in.size()) {
- break;
- }
- char ch = m_in[pos];
- // be very permissive in lexer (we'll catch errors when conversion happens)
- if (!std::isdigit(ch) && ch != '.' && ch != 'e' && ch != 'E' && ch != '+' && ch != '-') {
- break;
- }
- pos += 1;
- }
- return make_token(Token::Kind::Number);
- }
-
- Token scan_string() {
- bool escape {false};
- for (;;) {
- if (pos >= m_in.size()) {
- break;
- }
- char ch = m_in[pos++];
- if (ch == '\\') {
- escape = true;
- } else if (!escape && ch == m_in[tok_start]) {
- break;
- } else {
- escape = false;
- }
- }
- return make_token(Token::Kind::String);
- }
-
- Token make_token(Token::Kind kind) const { return Token(kind, string_view::slice(m_in, tok_start, pos)); }
-
- void skip_whitespaces_and_newlines() {
- if (pos < m_in.size()) {
- while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t' || m_in[pos] == '\n' || m_in[pos] == '\r')) {
- pos += 1;
- }
- }
- }
-
- void skip_whitespaces_and_first_newline() {
- if (pos < m_in.size()) {
- while (pos < m_in.size() && (m_in[pos] == ' ' || m_in[pos] == '\t')) {
- pos += 1;
- }
- }
-
- if (pos < m_in.size()) {
- char ch = m_in[pos];
- if (ch == '\n') {
- pos += 1;
- } else if (ch == '\r') {
- pos += 1;
- if (pos < m_in.size() && m_in[pos] == '\n') {
- pos += 1;
- }
- }
- }
- }
-
- static nonstd::string_view clear_final_line_if_whitespace(nonstd::string_view text) {
- nonstd::string_view result = text;
- while (!result.empty()) {
- char ch = result.back();
- if (ch == ' ' || ch == '\t') {
- result.remove_suffix(1);
- } else if (ch == '\n' || ch == '\r') {
- break;
- } else {
- return text;
- }
- }
- return result;
- }
-
-public:
- explicit Lexer(const LexerConfig &config) : config(config), state(State::Text), minus_state(MinusState::Number) {}
-
- SourceLocation current_position() const {
- return get_source_location(m_in, tok_start);
- }
-
- void start(nonstd::string_view input) {
- m_in = input;
- tok_start = 0;
- pos = 0;
- state = State::Text;
- minus_state = MinusState::Number;
-
- // Consume byte order mark (BOM) for UTF-8
- if (inja::string_view::starts_with(m_in, "\xEF\xBB\xBF")) {
- m_in = m_in.substr(3);
- }
- }
-
- Token scan() {
- tok_start = pos;
-
- again:
- if (tok_start >= m_in.size()) {
- return make_token(Token::Kind::Eof);
- }
-
- switch (state) {
- default:
- case State::Text: {
- // fast-scan to first open character
- size_t open_start = m_in.substr(pos).find_first_of(config.open_chars);
- if (open_start == nonstd::string_view::npos) {
- // didn't find open, return remaining text as text token
- pos = m_in.size();
- return make_token(Token::Kind::Text);
- }
- pos += open_start;
-
- // try to match one of the opening sequences, and get the close
- nonstd::string_view open_str = m_in.substr(pos);
- bool must_lstrip = false;
- if (inja::string_view::starts_with(open_str, config.expression_open)) {
- if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) {
- state = State::ExpressionStartForceLstrip;
- must_lstrip = true;
- } else {
- state = State::ExpressionStart;
- }
- } else if (inja::string_view::starts_with(open_str, config.statement_open)) {
- if (inja::string_view::starts_with(open_str, config.statement_open_no_lstrip)) {
- state = State::StatementStartNoLstrip;
- } else if (inja::string_view::starts_with(open_str, config.statement_open_force_lstrip )) {
- state = State::StatementStartForceLstrip;
- must_lstrip = true;
- } else {
- state = State::StatementStart;
- must_lstrip = config.lstrip_blocks;
- }
- } else if (inja::string_view::starts_with(open_str, config.comment_open)) {
- state = State::CommentStart;
- must_lstrip = config.lstrip_blocks;
- } else if ((pos == 0 || m_in[pos - 1] == '\n') && inja::string_view::starts_with(open_str, config.line_statement)) {
- state = State::LineStart;
- } else {
- pos += 1; // wasn't actually an opening sequence
- goto again;
- }
-
- nonstd::string_view text = string_view::slice(m_in, tok_start, pos);
- if (must_lstrip) {
- text = clear_final_line_if_whitespace(text);
- }
-
- if (text.empty()) {
- goto again; // don't generate empty token
- }
- return Token(Token::Kind::Text, text);
- }
- case State::ExpressionStart: {
- state = State::ExpressionBody;
- pos += config.expression_open.size();
- return make_token(Token::Kind::ExpressionOpen);
- }
- case State::ExpressionStartForceLstrip: {
- state = State::ExpressionBody;
- pos += config.expression_open_force_lstrip.size();
- return make_token(Token::Kind::ExpressionOpen);
- }
- case State::LineStart: {
- state = State::LineBody;
- pos += config.line_statement.size();
- return make_token(Token::Kind::LineStatementOpen);
- }
- case State::StatementStart: {
- state = State::StatementBody;
- pos += config.statement_open.size();
- return make_token(Token::Kind::StatementOpen);
- }
- case State::StatementStartNoLstrip: {
- state = State::StatementBody;
- pos += config.statement_open_no_lstrip.size();
- return make_token(Token::Kind::StatementOpen);
- }
- case State::StatementStartForceLstrip: {
- state = State::StatementBody;
- pos += config.statement_open_force_lstrip.size();
- return make_token(Token::Kind::StatementOpen);
- }
- case State::CommentStart: {
- state = State::CommentBody;
- pos += config.comment_open.size();
- return make_token(Token::Kind::CommentOpen);
- }
- case State::ExpressionBody:
- return scan_body(config.expression_close, Token::Kind::ExpressionClose, config.expression_close_force_rstrip);
- case State::LineBody:
- return scan_body("\n", Token::Kind::LineStatementClose);
- case State::StatementBody:
- return scan_body(config.statement_close, Token::Kind::StatementClose, config.statement_close_force_rstrip, config.trim_blocks);
- case State::CommentBody: {
- // fast-scan to comment close
- size_t end = m_in.substr(pos).find(config.comment_close);
- if (end == nonstd::string_view::npos) {
- pos = m_in.size();
- return make_token(Token::Kind::Eof);
- }
- // return the entire comment in the close token
- state = State::Text;
- pos += end + config.comment_close.size();
- Token tok = make_token(Token::Kind::CommentClose);
- if (config.trim_blocks) {
- skip_whitespaces_and_first_newline();
- }
- return tok;
- }
- }
- }
-
- const LexerConfig &get_config() const {
- return config;
- }
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_LEXER_HPP_
diff --git a/isis/src/base/apps/topds4/node.h b/isis/src/base/apps/topds4/node.h
deleted file mode 100644
index d7aa441871..0000000000
--- a/isis/src/base/apps/topds4/node.h
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_NODE_HPP_
-#define INCLUDE_INJA_NODE_HPP_
-
-#include
-#include
-
-#include
-
-#include "function_storage.h"
-#include "string_view.h"
-
-
-namespace inja {
-
-class NodeVisitor;
-class BlockNode;
-class TextNode;
-class ExpressionNode;
-class LiteralNode;
-class JsonNode;
-class FunctionNode;
-class ExpressionListNode;
-class StatementNode;
-class ForStatementNode;
-class ForArrayStatementNode;
-class ForObjectStatementNode;
-class IfStatementNode;
-class IncludeStatementNode;
-class SetStatementNode;
-
-
-class NodeVisitor {
-public:
- virtual void visit(const BlockNode& node) = 0;
- virtual void visit(const TextNode& node) = 0;
- virtual void visit(const ExpressionNode& node) = 0;
- virtual void visit(const LiteralNode& node) = 0;
- virtual void visit(const JsonNode& node) = 0;
- virtual void visit(const FunctionNode& node) = 0;
- virtual void visit(const ExpressionListNode& node) = 0;
- virtual void visit(const StatementNode& node) = 0;
- virtual void visit(const ForStatementNode& node) = 0;
- virtual void visit(const ForArrayStatementNode& node) = 0;
- virtual void visit(const ForObjectStatementNode& node) = 0;
- virtual void visit(const IfStatementNode& node) = 0;
- virtual void visit(const IncludeStatementNode& node) = 0;
- virtual void visit(const SetStatementNode& node) = 0;
-};
-
-/*!
- * \brief Base node class for the abstract syntax tree (AST).
- */
-class AstNode {
-public:
- virtual void accept(NodeVisitor& v) const = 0;
-
- size_t pos;
-
- AstNode(size_t pos) : pos(pos) { }
- virtual ~AstNode() { };
-};
-
-
-class BlockNode : public AstNode {
-public:
- std::vector> nodes;
-
- explicit BlockNode() : AstNode(0) {}
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class TextNode : public AstNode {
-public:
- const size_t length;
-
- explicit TextNode(size_t pos, size_t length): AstNode(pos), length(length) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class ExpressionNode : public AstNode {
-public:
- explicit ExpressionNode(size_t pos) : AstNode(pos) {}
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class LiteralNode : public ExpressionNode {
-public:
- const nlohmann::json value;
-
- explicit LiteralNode(const nlohmann::json& value, size_t pos) : ExpressionNode(pos), value(value) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class JsonNode : public ExpressionNode {
-public:
- const std::string name;
- const json::json_pointer ptr;
-
- static std::string convert_dot_to_json_ptr(nonstd::string_view ptr_name) {
- std::string result;
- do {
- nonstd::string_view part;
- std::tie(part, ptr_name) = string_view::split(ptr_name, '.');
- result.push_back('/');
- result.append(part.begin(), part.end());
- } while (!ptr_name.empty());
- return result;
- }
-
- explicit JsonNode(nonstd::string_view ptr_name, size_t pos) : ExpressionNode(pos), name(ptr_name), ptr(json::json_pointer(convert_dot_to_json_ptr(ptr_name))) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class FunctionNode : public ExpressionNode {
- using Op = FunctionStorage::Operation;
-
-public:
- enum class Associativity {
- Left,
- Right,
- };
-
- unsigned int precedence;
- Associativity associativity;
-
- Op operation;
-
- std::string name;
- int number_args; // Should also be negative -> -1 for unknown number
- CallbackFunction callback;
-
- explicit FunctionNode(nonstd::string_view name, size_t pos) : ExpressionNode(pos), precedence(8), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(1) { }
- explicit FunctionNode(Op operation, size_t pos) : ExpressionNode(pos), operation(operation), number_args(1) {
- switch (operation) {
- case Op::Not: {
- precedence = 4;
- associativity = Associativity::Left;
- } break;
- case Op::And: {
- precedence = 1;
- associativity = Associativity::Left;
- } break;
- case Op::Or: {
- precedence = 1;
- associativity = Associativity::Left;
- } break;
- case Op::In: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::Equal: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::NotEqual: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::Greater: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::GreaterEqual: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::Less: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::LessEqual: {
- precedence = 2;
- associativity = Associativity::Left;
- } break;
- case Op::Add: {
- precedence = 3;
- associativity = Associativity::Left;
- } break;
- case Op::Subtract: {
- precedence = 3;
- associativity = Associativity::Left;
- } break;
- case Op::Multiplication: {
- precedence = 4;
- associativity = Associativity::Left;
- } break;
- case Op::Division: {
- precedence = 4;
- associativity = Associativity::Left;
- } break;
- case Op::Power: {
- precedence = 5;
- associativity = Associativity::Right;
- } break;
- case Op::Modulo: {
- precedence = 4;
- associativity = Associativity::Left;
- } break;
- case Op::AtId: {
- precedence = 8;
- associativity = Associativity::Left;
- } break;
- default: {
- precedence = 1;
- associativity = Associativity::Left;
- }
- }
- }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class ExpressionListNode : public AstNode {
-public:
- std::vector> rpn_output;
-
- explicit ExpressionListNode() : AstNode(0) { }
- explicit ExpressionListNode(size_t pos) : AstNode(pos) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class StatementNode : public AstNode {
-public:
- StatementNode(size_t pos) : AstNode(pos) { }
-
- virtual void accept(NodeVisitor& v) const = 0;
-};
-
-class ForStatementNode : public StatementNode {
-public:
- ExpressionListNode condition;
- BlockNode body;
- BlockNode *const parent;
-
- ForStatementNode(BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent) { }
-
- virtual void accept(NodeVisitor& v) const = 0;
-};
-
-class ForArrayStatementNode : public ForStatementNode {
-public:
- const std::string value;
-
- explicit ForArrayStatementNode(const std::string& value, BlockNode *const parent, size_t pos) : ForStatementNode(parent, pos), value(value) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class ForObjectStatementNode : public ForStatementNode {
-public:
- const std::string key;
- const std::string value;
-
- explicit ForObjectStatementNode(const std::string& key, const std::string& value, BlockNode *const parent, size_t pos) : ForStatementNode(parent, pos), key(key), value(value) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class IfStatementNode : public StatementNode {
-public:
- ExpressionListNode condition;
- BlockNode true_statement;
- BlockNode false_statement;
- BlockNode *const parent;
-
- const bool is_nested;
- bool has_false_statement {false};
-
- explicit IfStatementNode(BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent), is_nested(false) { }
- explicit IfStatementNode(bool is_nested, BlockNode *const parent, size_t pos) : StatementNode(pos), parent(parent), is_nested(is_nested) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- }
-};
-
-class IncludeStatementNode : public StatementNode {
-public:
- const std::string file;
-
- explicit IncludeStatementNode(const std::string& file, size_t pos) : StatementNode(pos), file(file) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- };
-};
-
-class SetStatementNode : public StatementNode {
-public:
- const std::string key;
- ExpressionListNode expression;
-
- explicit SetStatementNode(const std::string& key, size_t pos) : StatementNode(pos), key(key) { }
-
- void accept(NodeVisitor& v) const {
- v.visit(*this);
- };
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_NODE_HPP_
diff --git a/isis/src/base/apps/topds4/parser.h b/isis/src/base/apps/topds4/parser.h
deleted file mode 100644
index c333668f2c..0000000000
--- a/isis/src/base/apps/topds4/parser.h
+++ /dev/null
@@ -1,582 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_PARSER_HPP_
-#define INCLUDE_INJA_PARSER_HPP_
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "config.h"
-#include "exceptions.h"
-#include "function_storage.h"
-#include "lexer.h"
-#include "node.h"
-#include "template2.h"
-#include "token.h"
-#include "utils.h"
-
-#include
-
-namespace inja {
-
-/*!
- * \brief Class for parsing an inja Template.
- */
-class Parser {
- const ParserConfig &config;
-
- Lexer lexer;
- TemplateStorage &template_storage;
- const FunctionStorage &function_storage;
-
- Token tok, peek_tok;
- bool have_peek_tok {false};
-
- size_t current_paren_level {0};
- size_t current_bracket_level {0};
- size_t current_brace_level {0};
-
- nonstd::string_view json_literal_start;
-
- BlockNode *current_block {nullptr};
- ExpressionListNode *current_expression_list {nullptr};
- std::stack> function_stack;
-
- std::stack> operator_stack;
- std::stack if_statement_stack;
- std::stack for_statement_stack;
-
- void throw_parser_error(const std::string &message) {
- throw ParserError(message, lexer.current_position());
- }
-
- void get_next_token() {
- if (have_peek_tok) {
- tok = peek_tok;
- have_peek_tok = false;
- } else {
- tok = lexer.scan();
- }
- }
-
- void get_peek_token() {
- if (!have_peek_tok) {
- peek_tok = lexer.scan();
- have_peek_tok = true;
- }
- }
-
- void add_json_literal(const char* content_ptr) {
- nonstd::string_view json_text(json_literal_start.data(), tok.text.data() - json_literal_start.data() + tok.text.size());
- current_expression_list->rpn_output.emplace_back(std::make_shared(json::parse(json_text), json_text.data() - content_ptr));
- }
-
- bool parse_expression(Template &tmpl, Token::Kind closing) {
- while (tok.kind != closing && tok.kind != Token::Kind::Eof) {
- // Literals
- switch (tok.kind) {
- case Token::Kind::String: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- json_literal_start = tok.text;
- add_json_literal(tmpl.content.c_str());
- }
-
- } break;
- case Token::Kind::Number: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- json_literal_start = tok.text;
- add_json_literal(tmpl.content.c_str());
- }
-
- } break;
- case Token::Kind::LeftBracket: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- json_literal_start = tok.text;
- }
- current_bracket_level += 1;
-
- } break;
- case Token::Kind::LeftBrace: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- json_literal_start = tok.text;
- }
- current_brace_level += 1;
-
- } break;
- case Token::Kind::RightBracket: {
- if (current_bracket_level == 0) {
- throw_parser_error("unexpected ']'");
- }
-
- current_bracket_level -= 1;
- if (current_brace_level == 0 && current_bracket_level == 0) {
- add_json_literal(tmpl.content.c_str());
- }
-
- } break;
- case Token::Kind::RightBrace: {
- if (current_brace_level == 0) {
- throw_parser_error("unexpected '}'");
- }
-
- current_brace_level -= 1;
- if (current_brace_level == 0 && current_bracket_level == 0) {
- add_json_literal(tmpl.content.c_str());
- }
-
- } break;
- case Token::Kind::Id: {
- get_peek_token();
-
- // Json Literal
- if (tok.text == static_cast("true") || tok.text == static_cast("false") || tok.text == static_cast("null")) {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- json_literal_start = tok.text;
- add_json_literal(tmpl.content.c_str());
- }
-
- // Operator
- } else if (tok.text == "and" || tok.text == "or" || tok.text == "in" || tok.text == "not") {
- goto parse_operator;
-
- // Functions
- } else if (peek_tok.kind == Token::Kind::LeftParen) {
- operator_stack.emplace(std::make_shared(static_cast(tok.text), tok.text.data() - tmpl.content.c_str()));
- function_stack.emplace(operator_stack.top().get(), current_paren_level);
-
- // Variables
- } else {
- current_expression_list->rpn_output.emplace_back(std::make_shared(static_cast(tok.text), tok.text.data() - tmpl.content.c_str()));
- }
-
- // Operators
- } break;
- case Token::Kind::Equal:
- case Token::Kind::NotEqual:
- case Token::Kind::GreaterThan:
- case Token::Kind::GreaterEqual:
- case Token::Kind::LessThan:
- case Token::Kind::LessEqual:
- case Token::Kind::Plus:
- case Token::Kind::Minus:
- case Token::Kind::Times:
- case Token::Kind::Slash:
- case Token::Kind::Power:
- case Token::Kind::Percent:
- case Token::Kind::Dot: {
-
- parse_operator:
- FunctionStorage::Operation operation;
- switch (tok.kind) {
- case Token::Kind::Id: {
- if (tok.text == "and") {
- operation = FunctionStorage::Operation::And;
- } else if (tok.text == "or") {
- operation = FunctionStorage::Operation::Or;
- } else if (tok.text == "in") {
- operation = FunctionStorage::Operation::In;
- } else if (tok.text == "not") {
- operation = FunctionStorage::Operation::Not;
- } else {
- throw_parser_error("unknown operator in parser.");
- }
- } break;
- case Token::Kind::Equal: {
- operation = FunctionStorage::Operation::Equal;
- } break;
- case Token::Kind::NotEqual: {
- operation = FunctionStorage::Operation::NotEqual;
- } break;
- case Token::Kind::GreaterThan: {
- operation = FunctionStorage::Operation::Greater;
- } break;
- case Token::Kind::GreaterEqual: {
- operation = FunctionStorage::Operation::GreaterEqual;
- } break;
- case Token::Kind::LessThan: {
- operation = FunctionStorage::Operation::Less;
- } break;
- case Token::Kind::LessEqual: {
- operation = FunctionStorage::Operation::LessEqual;
- } break;
- case Token::Kind::Plus: {
- operation = FunctionStorage::Operation::Add;
- } break;
- case Token::Kind::Minus: {
- operation = FunctionStorage::Operation::Subtract;
- } break;
- case Token::Kind::Times: {
- operation = FunctionStorage::Operation::Multiplication;
- } break;
- case Token::Kind::Slash: {
- operation = FunctionStorage::Operation::Division;
- } break;
- case Token::Kind::Power: {
- operation = FunctionStorage::Operation::Power;
- } break;
- case Token::Kind::Percent: {
- operation = FunctionStorage::Operation::Modulo;
- } break;
- case Token::Kind::Dot: {
- operation = FunctionStorage::Operation::AtId;
- } break;
- default: {
- throw_parser_error("unknown operator in parser.");
- }
- }
- auto function_node = std::make_shared(operation, tok.text.data() - tmpl.content.c_str());
-
- while (!operator_stack.empty() && ((operator_stack.top()->precedence > function_node->precedence) || (operator_stack.top()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left)) && (operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft)) {
- current_expression_list->rpn_output.emplace_back(operator_stack.top());
- operator_stack.pop();
- }
-
- operator_stack.emplace(function_node);
-
- } break;
- case Token::Kind::Comma: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- if (function_stack.empty()) {
- throw_parser_error("unexpected ','");
- }
-
- function_stack.top().first->number_args += 1;
- }
-
- } break;
- case Token::Kind::Colon: {
- if (current_brace_level == 0 && current_bracket_level == 0) {
- throw_parser_error("unexpected ':'");
- }
-
- } break;
- case Token::Kind::LeftParen: {
- current_paren_level += 1;
- operator_stack.emplace(std::make_shared(FunctionStorage::Operation::ParenLeft, tok.text.data() - tmpl.content.c_str()));
-
- get_peek_token();
- if (peek_tok.kind == Token::Kind::RightParen) {
- if (!function_stack.empty() && function_stack.top().second == current_paren_level - 1) {
- function_stack.top().first->number_args = 0;
- }
- }
-
- } break;
- case Token::Kind::RightParen: {
- current_paren_level -= 1;
- while (!operator_stack.empty() && operator_stack.top()->operation != FunctionStorage::Operation::ParenLeft) {
- current_expression_list->rpn_output.emplace_back(operator_stack.top());
- operator_stack.pop();
- }
-
- if (!operator_stack.empty() && operator_stack.top()->operation == FunctionStorage::Operation::ParenLeft) {
- operator_stack.pop();
- }
-
- if (!function_stack.empty() && function_stack.top().second == current_paren_level) {
- auto func = function_stack.top().first;
- auto function_data = function_storage.find_function(func->name, func->number_args);
- if (function_data.operation == FunctionStorage::Operation::None) {
- throw_parser_error("unknown function " + func->name);
- }
- func->operation = function_data.operation;
- if (function_data.operation == FunctionStorage::Operation::Callback) {
- func->callback = function_data.callback;
- }
-
- if (operator_stack.empty()) {
- throw_parser_error("internal error at function " + func->name);
- }
-
- current_expression_list->rpn_output.emplace_back(operator_stack.top());
- operator_stack.pop();
- function_stack.pop();
- }
- }
- default:
- break;
- }
-
- get_next_token();
- }
-
- while (!operator_stack.empty()) {
- current_expression_list->rpn_output.emplace_back(operator_stack.top());
- operator_stack.pop();
- }
-
- return true;
- }
-
- bool parse_statement(Template &tmpl, Token::Kind closing, nonstd::string_view path) {
- if (tok.kind != Token::Kind::Id) {
- return false;
- }
-
- if (tok.text == static_cast("if")) {
- get_next_token();
-
- auto if_statement_node = std::make_shared(current_block, tok.text.data() - tmpl.content.c_str());
- current_block->nodes.emplace_back(if_statement_node);
- if_statement_stack.emplace(if_statement_node.get());
- current_block = &if_statement_node->true_statement;
- current_expression_list = &if_statement_node->condition;
-
- if (!parse_expression(tmpl, closing)) {
- return false;
- }
-
- } else if (tok.text == static_cast("else")) {
- if (if_statement_stack.empty()) {
- throw_parser_error("else without matching if");
- }
- auto &if_statement_data = if_statement_stack.top();
- get_next_token();
-
- if_statement_data->has_false_statement = true;
- current_block = &if_statement_data->false_statement;
-
- // Chained else if
- if (tok.kind == Token::Kind::Id && tok.text == static_cast("if")) {
- get_next_token();
-
- auto if_statement_node = std::make_shared(true, current_block, tok.text.data() - tmpl.content.c_str());
- current_block->nodes.emplace_back(if_statement_node);
- if_statement_stack.emplace(if_statement_node.get());
- current_block = &if_statement_node->true_statement;
- current_expression_list = &if_statement_node->condition;
-
- if (!parse_expression(tmpl, closing)) {
- return false;
- }
- }
-
- } else if (tok.text == static_cast("endif")) {
- if (if_statement_stack.empty()) {
- throw_parser_error("endif without matching if");
- }
-
- // Nested if statements
- while (if_statement_stack.top()->is_nested) {
- if_statement_stack.pop();
- }
-
- auto &if_statement_data = if_statement_stack.top();
- get_next_token();
-
- current_block = if_statement_data->parent;
- if_statement_stack.pop();
-
- } else if (tok.text == static_cast("for")) {
- get_next_token();
-
- // options: for a in arr; for a, b in obj
- if (tok.kind != Token::Kind::Id) {
- throw_parser_error("expected id, got '" + tok.describe() + "'");
- }
-
- Token value_token = tok;
- get_next_token();
-
- // Object type
- std::shared_ptr for_statement_node;
- if (tok.kind == Token::Kind::Comma) {
- get_next_token();
- if (tok.kind != Token::Kind::Id) {
- throw_parser_error("expected id, got '" + tok.describe() + "'");
- }
-
- Token key_token = std::move(value_token);
- value_token = tok;
- get_next_token();
-
- for_statement_node = std::make_shared(static_cast(key_token.text), static_cast(value_token.text), current_block, tok.text.data() - tmpl.content.c_str());
-
- // Array type
- } else {
- for_statement_node = std::make_shared(static_cast(value_token.text), current_block, tok.text.data() - tmpl.content.c_str());
- }
-
- current_block->nodes.emplace_back(for_statement_node);
- for_statement_stack.emplace(for_statement_node.get());
- current_block = &for_statement_node->body;
- current_expression_list = &for_statement_node->condition;
-
- if (tok.kind != Token::Kind::Id || tok.text != static_cast("in")) {
- throw_parser_error("expected 'in', got '" + tok.describe() + "'");
- }
- get_next_token();
-
- if (!parse_expression(tmpl, closing)) {
- return false;
- }
-
- } else if (tok.text == static_cast("endfor")) {
- if (for_statement_stack.empty()) {
- throw_parser_error("endfor without matching for");
- }
-
- auto &for_statement_data = for_statement_stack.top();
- get_next_token();
-
- current_block = for_statement_data->parent;
- for_statement_stack.pop();
-
- } else if (tok.text == static_cast("include")) {
- get_next_token();
-
- if (tok.kind != Token::Kind::String) {
- throw_parser_error("expected string, got '" + tok.describe() + "'");
- }
-
- // Build the relative path
- json json_name = json::parse(tok.text);
- std::string pathname = static_cast(path);
- pathname += json_name.get_ref();
- if (pathname.compare(0, 2, "./") == 0) {
- pathname.erase(0, 2);
- }
- // sys::path::remove_dots(pathname, true, sys::path::Style::posix);
-
- if (config.search_included_templates_in_files && template_storage.find(pathname) == template_storage.end()) {
- auto include_template = Template(load_file(pathname));
- template_storage.emplace(pathname, include_template);
- parse_into_template(template_storage[pathname], pathname);
- }
-
- current_block->nodes.emplace_back(std::make_shared(pathname, tok.text.data() - tmpl.content.c_str()));
-
- get_next_token();
-
- } else if (tok.text == static_cast("set")) {
- get_next_token();
-
- if (tok.kind != Token::Kind::Id) {
- throw_parser_error("expected variable name, got '" + tok.describe() + "'");
- }
-
- std::string key = static_cast(tok.text);
- get_next_token();
-
- auto set_statement_node = std::make_shared(key, tok.text.data() - tmpl.content.c_str());
- current_block->nodes.emplace_back(set_statement_node);
- current_expression_list = &set_statement_node->expression;
-
- if (tok.text != static_cast("=")) {
- throw_parser_error("expected '=', got '" + tok.describe() + "'");
- }
- get_next_token();
-
- if (!parse_expression(tmpl, closing)) {
- return false;
- }
-
- } else {
- return false;
- }
- return true;
- }
-
- void parse_into(Template &tmpl, nonstd::string_view path) {
- lexer.start(tmpl.content);
- current_block = &tmpl.root;
-
- for (;;) {
- get_next_token();
- switch (tok.kind) {
- case Token::Kind::Eof: {
- if (!if_statement_stack.empty()) {
- throw_parser_error("unmatched if");
- }
- if (!for_statement_stack.empty()) {
- throw_parser_error("unmatched for");
- }
- } return;
- case Token::Kind::Text: {
- current_block->nodes.emplace_back(std::make_shared(tok.text.data() - tmpl.content.c_str(), tok.text.size()));
- } break;
- case Token::Kind::StatementOpen: {
- get_next_token();
- if (!parse_statement(tmpl, Token::Kind::StatementClose, path)) {
- throw_parser_error("expected statement, got '" + tok.describe() + "'");
- }
- if (tok.kind != Token::Kind::StatementClose) {
- throw_parser_error("expected statement close, got '" + tok.describe() + "'");
- }
- } break;
- case Token::Kind::LineStatementOpen: {
- get_next_token();
- if (!parse_statement(tmpl, Token::Kind::LineStatementClose, path)) {
- throw_parser_error("expected statement, got '" + tok.describe() + "'");
- }
- if (tok.kind != Token::Kind::LineStatementClose && tok.kind != Token::Kind::Eof) {
- throw_parser_error("expected line statement close, got '" + tok.describe() + "'");
- }
- } break;
- case Token::Kind::ExpressionOpen: {
- get_next_token();
-
- auto expression_list_node = std::make_shared(tok.text.data() - tmpl.content.c_str());
- current_block->nodes.emplace_back(expression_list_node);
- current_expression_list = expression_list_node.get();
-
- if (!parse_expression(tmpl, Token::Kind::ExpressionClose)) {
- throw_parser_error("expected expression, got '" + tok.describe() + "'");
- }
-
- if (tok.kind != Token::Kind::ExpressionClose) {
- throw_parser_error("expected expression close, got '" + tok.describe() + "'");
- }
- } break;
- case Token::Kind::CommentOpen: {
- get_next_token();
- if (tok.kind != Token::Kind::CommentClose) {
- throw_parser_error("expected comment close, got '" + tok.describe() + "'");
- }
- } break;
- default: {
- throw_parser_error("unexpected token '" + tok.describe() + "'");
- } break;
- }
- }
- }
-
-
-public:
- explicit Parser(const ParserConfig &parser_config, const LexerConfig &lexer_config,
- TemplateStorage &template_storage, const FunctionStorage &function_storage)
- : config(parser_config), lexer(lexer_config), template_storage(template_storage), function_storage(function_storage) { }
-
- Template parse(nonstd::string_view input, nonstd::string_view path) {
- auto result = Template(static_cast(input));
- parse_into(result, path);
- return result;
- }
-
- Template parse(nonstd::string_view input) {
- return parse(input, "./");
- }
-
- void parse_into_template(Template& tmpl, nonstd::string_view filename) {
- nonstd::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
-
- // StringRef path = sys::path::parent_path(filename);
- auto sub_parser = Parser(config, lexer.get_config(), template_storage, function_storage);
- sub_parser.parse_into(tmpl, path);
- }
-
- std::string load_file(nonstd::string_view filename) {
- std::ifstream file;
- open_file_or_throw(static_cast(filename), file);
- std::string text((std::istreambuf_iterator(file)), std::istreambuf_iterator());
- return text;
- }
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_PARSER_HPP_
diff --git a/isis/src/base/apps/topds4/renderer.h b/isis/src/base/apps/topds4/renderer.h
deleted file mode 100644
index 076bb780af..0000000000
--- a/isis/src/base/apps/topds4/renderer.h
+++ /dev/null
@@ -1,607 +0,0 @@
-// Copyright (c) 2020 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_RENDERER_HPP_
-#define INCLUDE_INJA_RENDERER_HPP_
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "config.h"
-#include "exceptions.h"
-#include "node.h"
-#include "template2.h"
-#include "utils.h"
-
-namespace inja {
-
-/*!
- * \brief Class for rendering a Template with data.
- */
-class Renderer : public NodeVisitor {
- using Op = FunctionStorage::Operation;
-
- const RenderConfig config;
- const Template *current_template;
- const TemplateStorage &template_storage;
- const FunctionStorage &function_storage;
-
- const json *json_input;
- std::ostream *output_stream;
-
- json json_additional_data;
- json* current_loop_data = &json_additional_data["loop"];
-
- std::vector> json_tmp_stack;
- std::stack json_eval_stack;
- std::stack not_found_stack;
-
- bool truthy(const json* data) const {
- if (data->is_boolean()) {
- return data->get();
- } else if (data->is_number()) {
- return (*data != 0);
- } else if (data->is_null()) {
- return false;
- }
- return !data->empty();
- }
-
- void print_json(const std::shared_ptr value) {
- if (value->is_string()) {
- *output_stream << value->get_ref();
- } else if (value->is_number_integer()) {
- *output_stream << value->get();
- } else if (value->is_null()) {
- } else {
- *output_stream << value->dump();
- }
- }
-
- const std::shared_ptr eval_expression_list(const ExpressionListNode& expression_list) {
- for (auto& expression : expression_list.rpn_output) {
- expression->accept(*this);
- }
-
- if (json_eval_stack.empty()) {
- throw_renderer_error("empty expression", expression_list);
- } else if (json_eval_stack.size() != 1) {
- throw_renderer_error("malformed expression", expression_list);
- }
-
- auto result = json_eval_stack.top();
- json_eval_stack.pop();
-
- if (!result) {
- if (not_found_stack.empty()) {
- throw_renderer_error("expression could not be evaluated", expression_list);
- }
-
- auto node = not_found_stack.top();
- not_found_stack.pop();
-
- throw_renderer_error("variable '" + static_cast(node->name) + "' not found", *node);
- }
- return std::make_shared(*result);
- }
-
- void throw_renderer_error(const std::string &message, const AstNode& node) {
- SourceLocation loc = get_source_location(current_template->content, node.pos);
- throw RenderError(message, loc);
- }
-
- template
- std::array get_arguments(const AstNode& node) {
- if (json_eval_stack.size() < N) {
- throw_renderer_error("function needs " + std::to_string(N) + " variables, but has only found " + std::to_string(json_eval_stack.size()), node);
- }
-
- std::array result;
- for (size_t i = 0; i < N; i += 1) {
- result[N - i - 1] = json_eval_stack.top();
- json_eval_stack.pop();
-
- if (!result[N - i - 1]) {
- auto json_node = not_found_stack.top();
- not_found_stack.pop();
-
- if (throw_not_found) {
- throw_renderer_error("variable '" + static_cast(json_node->name) + "' not found", *json_node);
- }
- }
- }
- return result;
- }
-
- template
- Arguments get_argument_vector(size_t N, const AstNode& node) {
- Arguments result {N};
- for (size_t i = 0; i < N; i += 1) {
- result[N - i - 1] = json_eval_stack.top();
- json_eval_stack.pop();
-
- if (!result[N - i - 1]) {
- auto json_node = not_found_stack.top();
- not_found_stack.pop();
-
- if (throw_not_found) {
- throw_renderer_error("variable '" + static_cast(json_node->name) + "' not found", *json_node);
- }
- }
- }
- return result;
- }
-
- void visit(const BlockNode& node) {
- for (auto& n : node.nodes) {
- n->accept(*this);
- }
- }
-
- void visit(const TextNode& node) {
- output_stream->write(current_template->content.c_str() + node.pos, node.length);
- }
-
- void visit(const ExpressionNode&) { }
-
- void visit(const LiteralNode& node) {
- json_eval_stack.push(&node.value);
- }
-
- void visit(const JsonNode& node) {
- if (json_additional_data.contains(node.ptr)) {
- json_eval_stack.push(&(json_additional_data[node.ptr]));
-
- } else if (json_input->contains(node.ptr)) {
- json_eval_stack.push(&(*json_input)[node.ptr]);
-
- } else {
- // Try to evaluate as a no-argument callback
- auto function_data = function_storage.find_function(node.name, 0);
- if (function_data.operation == FunctionStorage::Operation::Callback) {
- Arguments empty_args {};
- auto value = std::make_shared(function_data.callback(empty_args));
- json_tmp_stack.push_back(value);
- json_eval_stack.push(value.get());
-
- } else {
- json_eval_stack.push(nullptr);
- not_found_stack.emplace(&node);
- }
- }
- }
-
- void visit(const FunctionNode& node) {
- std::shared_ptr result_ptr;
-
- switch (node.operation) {
- case Op::Not: {
- auto args = get_arguments<1>(node);
- result_ptr = std::make_shared(!truthy(args[0]));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::And: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(truthy(args[0]) && truthy(args[1]));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Or: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(truthy(args[0]) || truthy(args[1]));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::In: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Equal: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] == *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::NotEqual: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] != *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Greater: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] > *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::GreaterEqual: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] >= *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Less: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] < *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::LessEqual: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(*args[0] <= *args[1]);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Add: {
- auto args = get_arguments<2>(node);
- if (args[0]->is_string() && args[1]->is_string()) {
- result_ptr = std::make_shared(args[0]->get_ref() + args[1]->get_ref());
- json_tmp_stack.push_back(result_ptr);
- } else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
- result_ptr = std::make_shared(args[0]->get() + args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- } else {
- result_ptr = std::make_shared(args[0]->get() + args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- }
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Subtract: {
- auto args = get_arguments<2>(node);
- if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
- result_ptr = std::make_shared(args[0]->get() - args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- } else {
- result_ptr = std::make_shared(args[0]->get() - args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- }
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Multiplication: {
- auto args = get_arguments<2>(node);
- if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
- result_ptr = std::make_shared(args[0]->get() * args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- } else {
- result_ptr = std::make_shared(args[0]->get() * args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- }
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Division: {
- auto args = get_arguments<2>(node);
- if (args[1]->get() == 0) {
- throw_renderer_error("division by zero", node);
- }
- result_ptr = std::make_shared(args[0]->get() / args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Power: {
- auto args = get_arguments<2>(node);
- if (args[0]->is_number_integer() && args[1]->get() >= 0) {
- int result = std::pow(args[0]->get(), args[1]->get());
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- } else {
- double result = std::pow(args[0]->get(), args[1]->get());
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- }
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Modulo: {
- auto args = get_arguments<2>(node);
- result_ptr = std::make_shared(args[0]->get() % args[1]->get());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::AtId: {
- json_eval_stack.pop(); // Pop id nullptr
- auto container = get_arguments<1, false>(node)[0];
- if (not_found_stack.empty()) {
- throw_renderer_error("could not find element with given name", node);
- }
- auto id_node = not_found_stack.top();
- not_found_stack.pop();
- json_eval_stack.push(&container->at(id_node->name));
- } break;
- case Op::At: {
- auto args = get_arguments<2>(node);
- json_eval_stack.push(&args[0]->at(args[1]->get()));
- } break;
- case Op::Default: {
- auto default_arg = get_arguments<1>(node)[0];
- auto test_arg = get_arguments<1, false>(node)[0];
- json_eval_stack.push(test_arg ? test_arg : default_arg);
- } break;
- case Op::DivisibleBy: {
- auto args = get_arguments<2>(node);
- int divisor = args[1]->get();
- result_ptr = std::make_shared((divisor != 0) && (args[0]->get() % divisor == 0));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Even: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->get() % 2 == 0);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Exists: {
- auto &&name = get_arguments<1>(node)[0]->get_ref();
- result_ptr = std::make_shared(json_input->contains(json::json_pointer(JsonNode::convert_dot_to_json_ptr(name))));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::ExistsInObject: {
- auto args = get_arguments<2>(node);
- auto &&name = args[1]->get_ref();
- result_ptr = std::make_shared(args[0]->find(name) != args[0]->end());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::First: {
- auto result = &get_arguments<1>(node)[0]->front();
- json_eval_stack.push(result);
- } break;
- case Op::Float: {
- result_ptr = std::make_shared(std::stod(get_arguments<1>(node)[0]->get_ref()));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Int: {
- result_ptr = std::make_shared(std::stoi(get_arguments<1>(node)[0]->get_ref()));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Last: {
- auto result = &get_arguments<1>(node)[0]->back();
- json_eval_stack.push(result);
- } break;
- case Op::Length: {
- auto val = get_arguments<1>(node)[0];
- if (val->is_string()) {
- result_ptr = std::make_shared(val->get_ref().length());
- } else {
- result_ptr = std::make_shared(val->size());
- }
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Lower: {
- std::string result = get_arguments<1>(node)[0]->get();
- std::transform(result.begin(), result.end(), result.begin(), ::tolower);
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Max: {
- auto args = get_arguments<1>(node);
- auto result = std::max_element(args[0]->begin(), args[0]->end());
- json_eval_stack.push(&(*result));
- } break;
- case Op::Min: {
- auto args = get_arguments<1>(node);
- auto result = std::min_element(args[0]->begin(), args[0]->end());
- json_eval_stack.push(&(*result));
- } break;
- case Op::Odd: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->get() % 2 != 0);
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Range: {
- std::vector result(get_arguments<1>(node)[0]->get());
- std::iota(result.begin(), result.end(), 0);
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Round: {
- auto args = get_arguments<2>(node);
- int precision = args[1]->get();
- double result = std::round(args[0]->get() * std::pow(10.0, precision)) / std::pow(10.0, precision);
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Sort: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->get>());
- std::sort(result_ptr->begin(), result_ptr->end());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Upper: {
- std::string result = get_arguments<1>(node)[0]->get();
- std::transform(result.begin(), result.end(), result.begin(), ::toupper);
- result_ptr = std::make_shared(std::move(result));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsBoolean: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_boolean());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsNumber: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_number());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsInteger: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_number_integer());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsFloat: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_number_float());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsObject: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_object());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsArray: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_array());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::IsString: {
- result_ptr = std::make_shared(get_arguments<1>(node)[0]->is_string());
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::Callback: {
- auto args = get_argument_vector(node.number_args, node);
- result_ptr = std::make_shared(node.callback(args));
- json_tmp_stack.push_back(result_ptr);
- json_eval_stack.push(result_ptr.get());
- } break;
- case Op::ParenLeft:
- case Op::ParenRight:
- case Op::None:
- break;
- }
- }
-
- void visit(const ExpressionListNode& node) {
- print_json(eval_expression_list(node));
- }
-
- void visit(const StatementNode&) { }
-
- void visit(const ForStatementNode&) { }
-
- void visit(const ForArrayStatementNode& node) {
- auto result = eval_expression_list(node.condition);
- if (!result->is_array()) {
- throw_renderer_error("object must be an array", node);
- }
-
- if (!current_loop_data->empty()) {
- auto tmp = *current_loop_data; // Because of clang-3
- (*current_loop_data)["parent"] = std::move(tmp);
- }
-
- size_t index = 0;
- (*current_loop_data)["is_first"] = true;
- (*current_loop_data)["is_last"] = (result->size() <= 1);
- for (auto it = result->begin(); it != result->end(); ++it) {
- json_additional_data[static_cast(node.value)] = *it;
-
- (*current_loop_data)["index"] = index;
- (*current_loop_data)["index1"] = index + 1;
- if (index == 1) {
- (*current_loop_data)["is_first"] = false;
- }
- if (index == result->size() - 1) {
- (*current_loop_data)["is_last"] = true;
- }
-
- node.body.accept(*this);
- ++index;
- }
-
- json_additional_data[static_cast(node.value)].clear();
- if (!(*current_loop_data)["parent"].empty()) {
- auto tmp = (*current_loop_data)["parent"];
- *current_loop_data = std::move(tmp);
- } else {
- current_loop_data = &json_additional_data["loop"];
- }
- }
-
- void visit(const ForObjectStatementNode& node) {
- auto result = eval_expression_list(node.condition);
- if (!result->is_object()) {
- throw_renderer_error("object must be an object", node);
- }
-
- if (!current_loop_data->empty()) {
- (*current_loop_data)["parent"] = std::move(*current_loop_data);
- }
-
- size_t index = 0;
- (*current_loop_data)["is_first"] = true;
- (*current_loop_data)["is_last"] = (result->size() <= 1);
- for (auto it = result->begin(); it != result->end(); ++it) {
- json_additional_data[static_cast(node.key)] = it.key();
- json_additional_data[static_cast(node.value)] = it.value();
-
- (*current_loop_data)["index"] = index;
- (*current_loop_data)["index1"] = index + 1;
- if (index == 1) {
- (*current_loop_data)["is_first"] = false;
- }
- if (index == result->size() - 1) {
- (*current_loop_data)["is_last"] = true;
- }
-
- node.body.accept(*this);
- ++index;
- }
-
- json_additional_data[static_cast(node.key)].clear();
- json_additional_data[static_cast(node.value)].clear();
- if (!(*current_loop_data)["parent"].empty()) {
- *current_loop_data = std::move((*current_loop_data)["parent"]);
- } else {
- current_loop_data = &json_additional_data["loop"];
- }
- }
-
- void visit(const IfStatementNode& node) {
- auto result = eval_expression_list(node.condition);
- if (truthy(result.get())) {
- node.true_statement.accept(*this);
- } else if (node.has_false_statement) {
- node.false_statement.accept(*this);
- }
- }
-
- void visit(const IncludeStatementNode& node) {
- auto sub_renderer = Renderer(config, template_storage, function_storage);
- auto included_template_it = template_storage.find(node.file);
-
- if (included_template_it != template_storage.end()) {
- sub_renderer.render_to(*output_stream, included_template_it->second, *json_input, &json_additional_data);
- } else if (config.throw_at_missing_includes) {
- throw_renderer_error("include '" + node.file + "' not found", node);
- }
- }
-
- void visit(const SetStatementNode& node) {
- json_additional_data[node.key] = *eval_expression_list(node.expression);
- }
-
-public:
- Renderer(const RenderConfig& config, const TemplateStorage &template_storage, const FunctionStorage &function_storage)
- : config(config), template_storage(template_storage), function_storage(function_storage) { }
-
- void render_to(std::ostream &os, const Template &tmpl, const json &data, json *loop_data = nullptr) {
- output_stream = &os;
- current_template = &tmpl;
- json_input = &data;
- if (loop_data) {
- json_additional_data = *loop_data;
- current_loop_data = &json_additional_data["loop"];
- }
-
- current_template->root.accept(*this);
-
- json_tmp_stack.clear();
- }
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_RENDERER_HPP_
diff --git a/isis/src/base/apps/topds4/statistics2.h b/isis/src/base/apps/topds4/statistics2.h
deleted file mode 100644
index be7eefe541..0000000000
--- a/isis/src/base/apps/topds4/statistics2.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2019 Pantor. All rights reserved.
-
-#ifndef INCLUDE_INJA_STATISTICS_HPP_
-#define INCLUDE_INJA_STATISTICS_HPP_
-
-#include "node.h"
-
-
-namespace inja {
-
-/*!
- * \brief A class for counting statistics on a Template.
- */
-class StatisticsVisitor : public NodeVisitor {
- void visit(const BlockNode& node) {
- for (auto& n : node.nodes) {
- n->accept(*this);
- }
- }
-
- void visit(const TextNode&) { }
- void visit(const ExpressionNode&) { }
- void visit(const LiteralNode&) { }
-
- void visit(const JsonNode&) {
- variable_counter += 1;
- }
-
- void visit(const FunctionNode&) { }
-
- void visit(const ExpressionListNode& node) {
- for (auto& n : node.rpn_output) {
- n->accept(*this);
- }
- }
-
- void visit(const StatementNode&) { }
- void visit(const ForStatementNode&) { }
-
- void visit(const ForArrayStatementNode& node) {
- node.condition.accept(*this);
- node.body.accept(*this);
- }
-
- void visit(const ForObjectStatementNode& node) {
- node.condition.accept(*this);
- node.body.accept(*this);
- }
-
- void visit(const IfStatementNode& node) {
- node.condition.accept(*this);
- node.true_statement.accept(*this);
- node.false_statement.accept(*this);
- }
-
- void visit(const IncludeStatementNode&) { }
-
- void visit(const SetStatementNode&) { }
-
-public:
- unsigned int variable_counter;
-
- explicit StatisticsVisitor() : variable_counter(0) { }
-};
-
-} // namespace inja
-
-#endif // INCLUDE_INJA_STATISTICS_HPP_
diff --git a/isis/src/base/apps/topds4/string_view.h b/isis/src/base/apps/topds4/string_view.h
deleted file mode 100644
index 2bb50c91b7..0000000000
--- a/isis/src/base/apps/topds4/string_view.h
+++ /dev/null
@@ -1,1416 +0,0 @@
-// Copyright 2017-2019 by Martin Moene
-//
-// string-view lite, a C++17-like string_view for C++98 and later.
-// For more information see https://github.com/martinmoene/string-view-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#pragma once
-
-#ifndef NONSTD_SV_LITE_H_INCLUDED
-#define NONSTD_SV_LITE_H_INCLUDED
-
-#define string_view_lite_MAJOR 1
-#define string_view_lite_MINOR 4
-#define string_view_lite_PATCH 0
-
-#define string_view_lite_VERSION \
- nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY( \
- string_view_lite_PATCH)
-
-#define nssv_STRINGIFY(x) nssv_STRINGIFY_(x)
-#define nssv_STRINGIFY_(x) #x
-
-// string-view lite configuration:
-
-#define nssv_STRING_VIEW_DEFAULT 0
-#define nssv_STRING_VIEW_NONSTD 1
-#define nssv_STRING_VIEW_STD 2
-
-#if !defined(nssv_CONFIG_SELECT_STRING_VIEW)
-#define nssv_CONFIG_SELECT_STRING_VIEW (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD)
-#endif
-
-#if defined(nssv_CONFIG_SELECT_STD_STRING_VIEW) || defined(nssv_CONFIG_SELECT_NONSTD_STRING_VIEW)
-#error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...
-#endif
-
-#ifndef nssv_CONFIG_STD_SV_OPERATOR
-#define nssv_CONFIG_STD_SV_OPERATOR 0
-#endif
-
-#ifndef nssv_CONFIG_USR_SV_OPERATOR
-#define nssv_CONFIG_USR_SV_OPERATOR 1
-#endif
-
-#ifdef nssv_CONFIG_CONVERSION_STD_STRING
-#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
-#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
-#endif
-
-#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
-#endif
-
-#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
-#endif
-
-// Control presence of exception handling (try and auto discover):
-
-#ifndef nssv_CONFIG_NO_EXCEPTIONS
-#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-#define nssv_CONFIG_NO_EXCEPTIONS 0
-#else
-#define nssv_CONFIG_NO_EXCEPTIONS 1
-#endif
-#endif
-
-// C++ language version detection (C++20 is speculative):
-// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
-
-#ifndef nssv_CPLUSPLUS
-#if defined(_MSVC_LANG) && !defined(__clang__)
-#define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
-#else
-#define nssv_CPLUSPLUS __cplusplus
-#endif
-#endif
-
-#define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L)
-#define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L)
-#define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L)
-#define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L)
-#define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L)
-#define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202000L)
-
-// use C++17 std::string_view if available and requested:
-
-#if nssv_CPP17_OR_GREATER && defined(__has_include)
-#if __has_include( )
-#define nssv_HAVE_STD_STRING_VIEW 1
-#else
-#define nssv_HAVE_STD_STRING_VIEW 0
-#endif
-#else
-#define nssv_HAVE_STD_STRING_VIEW 0
-#endif
-
-#define nssv_USES_STD_STRING_VIEW \
- ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \
- ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW))
-
-#define nssv_HAVE_STARTS_WITH (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW)
-#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
-
-//
-// Use C++17 std::string_view:
-//
-
-#if nssv_USES_STD_STRING_VIEW
-
-#include
-
-// Extensions for std::string:
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-namespace nonstd {
-
-template >
-std::basic_string to_string(std::basic_string_view v,
- Allocator const &a = Allocator()) {
- return std::basic_string(v.begin(), v.end(), a);
-}
-
-template
-std::basic_string_view to_string_view(std::basic_string const &s) {
- return std::basic_string_view(s.data(), s.size());
-}
-
-// Literal operators sv and _sv:
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-
-using namespace std::literals::string_view_literals;
-
-#endif
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-
-inline namespace literals {
-inline namespace string_view_literals {
-
-constexpr std::string_view operator"" _sv(const char *str, size_t len) noexcept // (1)
-{
- return std::string_view {str, len};
-}
-
-constexpr std::u16string_view operator"" _sv(const char16_t *str, size_t len) noexcept // (2)
-{
- return std::u16string_view {str, len};
-}
-
-constexpr std::u32string_view operator"" _sv(const char32_t *str, size_t len) noexcept // (3)
-{
- return std::u32string_view {str, len};
-}
-
-constexpr std::wstring_view operator"" _sv(const wchar_t *str, size_t len) noexcept // (4)
-{
- return std::wstring_view {str, len};
-}
-
-} // namespace string_view_literals
-} // namespace literals
-
-#endif // nssv_CONFIG_USR_SV_OPERATOR
-
-} // namespace nonstd
-
-#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-namespace nonstd {
-
-using std::basic_string_view;
-using std::string_view;
-using std::u16string_view;
-using std::u32string_view;
-using std::wstring_view;
-
-// literal "sv" and "_sv", see above
-
-using std::operator==;
-using std::operator!=;
-using std::operator<;
-using std::operator<=;
-using std::operator>;
-using std::operator>=;
-
-using std::operator<<;
-
-} // namespace nonstd
-
-#else // nssv_HAVE_STD_STRING_VIEW
-
-//
-// Before C++17: use string_view lite:
-//
-
-// Compiler versions:
-//
-// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
-// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
-// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
-// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
-// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
-// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
-// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
-// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
-// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
-// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
-
-#if defined(_MSC_VER) && !defined(__clang__)
-#define nssv_COMPILER_MSVC_VER (_MSC_VER)
-#define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
-#else
-#define nssv_COMPILER_MSVC_VER 0
-#define nssv_COMPILER_MSVC_VERSION 0
-#endif
-
-#define nssv_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch))
-
-#if defined(__clang__)
-#define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
-#else
-#define nssv_COMPILER_CLANG_VERSION 0
-#endif
-
-#if defined(__GNUC__) && !defined(__clang__)
-#define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#else
-#define nssv_COMPILER_GNUC_VERSION 0
-#endif
-
-// half-open range [lo..hi):
-#define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
-
-// Presence of language and library features:
-
-#ifdef _HAS_CPP0X
-#define nssv_HAS_CPP0X _HAS_CPP0X
-#else
-#define nssv_HAS_CPP0X 0
-#endif
-
-// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
-
-#if nssv_COMPILER_MSVC_VER >= 1900
-#undef nssv_CPP11_OR_GREATER
-#define nssv_CPP11_OR_GREATER 1
-#endif
-
-#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
-#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
-#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
-#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
-#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
-#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
-
-#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
-#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
-
-// Presence of C++11 language features:
-
-#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
-#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
-#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
-#define nssv_HAVE_NOEXCEPT nssv_CPP11_140
-#define nssv_HAVE_NULLPTR nssv_CPP11_100
-#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
-#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
-#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
-#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
-#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
-
-#if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400))
-#define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
-#else
-#define nssv_HAVE_STD_DEFINED_LITERALS 0
-#endif
-
-// Presence of C++14 language features:
-
-#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
-
-// Presence of C++17 language features:
-
-#define nssv_HAVE_NODISCARD nssv_CPP17_000
-
-// Presence of C++ library features:
-
-#define nssv_HAVE_STD_HASH nssv_CPP11_120
-
-// C++ feature usage:
-
-#if nssv_HAVE_CONSTEXPR_11
-#define nssv_constexpr constexpr
-#else
-#define nssv_constexpr /*constexpr*/
-#endif
-
-#if nssv_HAVE_CONSTEXPR_14
-#define nssv_constexpr14 constexpr
-#else
-#define nssv_constexpr14 /*constexpr*/
-#endif
-
-#if nssv_HAVE_EXPLICIT_CONVERSION
-#define nssv_explicit explicit
-#else
-#define nssv_explicit /*explicit*/
-#endif
-
-#if nssv_HAVE_INLINE_NAMESPACE
-#define nssv_inline_ns inline
-#else
-#define nssv_inline_ns /*inline*/
-#endif
-
-#if nssv_HAVE_NOEXCEPT
-#define nssv_noexcept noexcept
-#else
-#define nssv_noexcept /*noexcept*/
-#endif
-
-//#if nssv_HAVE_REF_QUALIFIER
-//# define nssv_ref_qual &
-//# define nssv_refref_qual &&
-//#else
-//# define nssv_ref_qual /*&*/
-//# define nssv_refref_qual /*&&*/
-//#endif
-
-#if nssv_HAVE_NULLPTR
-#define nssv_nullptr nullptr
-#else
-#define nssv_nullptr NULL
-#endif
-
-#if nssv_HAVE_NODISCARD
-#define nssv_nodiscard [[nodiscard]]
-#else
-#define nssv_nodiscard /*[[nodiscard]]*/
-#endif
-
-// Additional includes:
-
-#include
-#include
-#include
-#include
-#include
-#include // std::char_traits<>
-
-#if !nssv_CONFIG_NO_EXCEPTIONS
-#include
-#endif
-
-#if nssv_CPP11_OR_GREATER
-#include
-#endif
-
-// Clang, GNUC, MSVC warning suppression macros:
-
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wuser-defined-literals"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wliteral-suffix"
-#endif // __clang__
-
-#if nssv_COMPILER_MSVC_VERSION >= 140
-#define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
-#define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress : code))
-#define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes))
-#else
-#define nssv_SUPPRESS_MSGSL_WARNING(expr)
-#define nssv_SUPPRESS_MSVC_WARNING(code, descr)
-#define nssv_DISABLE_MSVC_WARNINGS(codes)
-#endif
-
-#if defined(__clang__)
-#define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
-#elif defined(__GNUC__)
-#define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
-#elif nssv_COMPILER_MSVC_VERSION >= 140
-#define nssv_RESTORE_WARNINGS() __pragma(warning(pop))
-#else
-#define nssv_RESTORE_WARNINGS()
-#endif
-
-// Suppress the following MSVC (GSL) warnings:
-// - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
-// start with an underscore are reserved
-// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
-// use brace initialization, gsl::narrow_cast or gsl::narow
-// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
-
-nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472)
- // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
- // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
-
- namespace nonstd {
- namespace sv_lite {
-
-#if nssv_CPP11_OR_GREATER
-
- namespace detail {
-
- // Expect tail call optimization to make length() non-recursive:
-
- template inline constexpr std::size_t length(CharT *s, std::size_t result = 0) {
- return *s == '\0' ? result : length(s + 1, result + 1);
- }
-
- } // namespace detail
-
-#endif // nssv_CPP11_OR_GREATER
-
- template > class basic_string_view;
-
- //
- // basic_string_view:
- //
-
- template */
- >
- class basic_string_view {
- public:
- // Member types:
-
- typedef Traits traits_type;
- typedef CharT value_type;
-
- typedef CharT *pointer;
- typedef CharT const *const_pointer;
- typedef CharT &reference;
- typedef CharT const &const_reference;
-
- typedef const_pointer iterator;
- typedef const_pointer const_iterator;
- typedef std::reverse_iterator reverse_iterator;
- typedef std::reverse_iterator const_reverse_iterator;
-
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- // 24.4.2.1 Construction and assignment:
-
- nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr), size_(0) {}
-
-#if nssv_CPP11_OR_GREATER
- nssv_constexpr basic_string_view(basic_string_view const &other) nssv_noexcept = default;
-#else
- nssv_constexpr basic_string_view(basic_string_view const &other) nssv_noexcept : data_(other.data_),
- size_(other.size_) {}
-#endif
-
- nssv_constexpr basic_string_view(CharT const *s, size_type count) nssv_noexcept // non-standard noexcept
- : data_(s),
- size_(count) {}
-
- nssv_constexpr basic_string_view(CharT const *s) nssv_noexcept // non-standard noexcept
- : data_(s)
-#if nssv_CPP17_OR_GREATER
- ,
- size_(Traits::length(s))
-#elif nssv_CPP11_OR_GREATER
- ,
- size_(detail::length(s))
-#else
- ,
- size_(Traits::length(s))
-#endif
- {
- }
-
- // Assignment:
-
-#if nssv_CPP11_OR_GREATER
- nssv_constexpr14 basic_string_view &operator=(basic_string_view const &other) nssv_noexcept = default;
-#else
- nssv_constexpr14 basic_string_view &operator=(basic_string_view const &other) nssv_noexcept {
- data_ = other.data_;
- size_ = other.size_;
- return *this;
- }
-#endif
-
- // 24.4.2.2 Iterator support:
-
- nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
- nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
-
- nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
- nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
-
- nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator(end()); }
- nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator(begin()); }
-
- nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
- nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
-
- // 24.4.2.3 Capacity:
-
- nssv_constexpr size_type size() const nssv_noexcept { return size_; }
- nssv_constexpr size_type length() const nssv_noexcept { return size_; }
- nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits::max)(); }
-
- // since C++20
- nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { return 0 == size_; }
-
- // 24.4.2.4 Element access:
-
- nssv_constexpr const_reference operator[](size_type pos) const { return data_at(pos); }
-
- nssv_constexpr14 const_reference at(size_type pos) const {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert(pos < size());
-#else
- if (pos >= size()) {
- throw std::out_of_range("nonstd::string_view::at()");
- }
-#endif
- return data_at(pos);
- }
-
- nssv_constexpr const_reference front() const { return data_at(0); }
- nssv_constexpr const_reference back() const { return data_at(size() - 1); }
-
- nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
-
- // 24.4.2.5 Modifiers:
-
- nssv_constexpr14 void remove_prefix(size_type n) {
- assert(n <= size());
- data_ += n;
- size_ -= n;
- }
-
- nssv_constexpr14 void remove_suffix(size_type n) {
- assert(n <= size());
- size_ -= n;
- }
-
- nssv_constexpr14 void swap(basic_string_view &other) nssv_noexcept {
- using std::swap;
- swap(data_, other.data_);
- swap(size_, other.size_);
- }
-
- // 24.4.2.6 String operations:
-
- size_type copy(CharT *dest, size_type n, size_type pos = 0) const {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert(pos <= size());
-#else
- if (pos > size()) {
- throw std::out_of_range("nonstd::string_view::copy()");
- }
-#endif
- const size_type rlen = (std::min)(n, size() - pos);
-
- (void)Traits::copy(dest, data() + pos, rlen);
-
- return rlen;
- }
-
- nssv_constexpr14 basic_string_view substr(size_type pos = 0, size_type n = npos) const {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert(pos <= size());
-#else
- if (pos > size()) {
- throw std::out_of_range("nonstd::string_view::substr()");
- }
-#endif
- return basic_string_view(data() + pos, (std::min)(n, size() - pos));
- }
-
- // compare(), 6x:
-
- nssv_constexpr14 int compare(basic_string_view other) const nssv_noexcept // (1)
- {
- if (const int result = Traits::compare(data(), other.data(), (std::min)(size(), other.size()))) {
- return result;
- }
-
- return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
- }
-
- nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other) const // (2)
- {
- return substr(pos1, n1).compare(other);
- }
-
- nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other, size_type pos2,
- size_type n2) const // (3)
- {
- return substr(pos1, n1).compare(other.substr(pos2, n2));
- }
-
- nssv_constexpr int compare(CharT const *s) const // (4)
- {
- return compare(basic_string_view(s));
- }
-
- nssv_constexpr int compare(size_type pos1, size_type n1, CharT const *s) const // (5)
- {
- return substr(pos1, n1).compare(basic_string_view(s));
- }
-
- nssv_constexpr int compare(size_type pos1, size_type n1, CharT const *s, size_type n2) const // (6)
- {
- return substr(pos1, n1).compare(basic_string_view(s, n2));
- }
-
- // 24.4.2.7 Searching:
-
- // starts_with(), 3x, since C++20:
-
- nssv_constexpr bool starts_with(basic_string_view v) const nssv_noexcept // (1)
- {
- return size() >= v.size() && compare(0, v.size(), v) == 0;
- }
-
- nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2)
- {
- return starts_with(basic_string_view(&c, 1));
- }
-
- nssv_constexpr bool starts_with(CharT const *s) const // (3)
- {
- return starts_with(basic_string_view(s));
- }
-
- // ends_with(), 3x, since C++20:
-
- nssv_constexpr bool ends_with(basic_string_view v) const nssv_noexcept // (1)
- {
- return size() >= v.size() && compare(size() - v.size(), npos, v) == 0;
- }
-
- nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2)
- {
- return ends_with(basic_string_view(&c, 1));
- }
-
- nssv_constexpr bool ends_with(CharT const *s) const // (3)
- {
- return ends_with(basic_string_view(s));
- }
-
- // find(), 4x:
-
- nssv_constexpr14 size_type find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
- {
- return assert(v.size() == 0 || v.data() != nssv_nullptr),
- pos >= size() ? npos : to_pos(std::search(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq));
- }
-
- nssv_constexpr14 size_type find(CharT c, size_type pos = 0) const nssv_noexcept // (2)
- {
- return find(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr14 size_type find(CharT const *s, size_type pos, size_type n) const // (3)
- {
- return find(basic_string_view(s, n), pos);
- }
-
- nssv_constexpr14 size_type find(CharT const *s, size_type pos = 0) const // (4)
- {
- return find(basic_string_view(s), pos);
- }
-
- // rfind(), 4x:
-
- nssv_constexpr14 size_type rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
- {
- if (size() < v.size()) {
- return npos;
- }
-
- if (v.empty()) {
- return (std::min)(size(), pos);
- }
-
- const_iterator last = cbegin() + (std::min)(size() - v.size(), pos) + v.size();
- const_iterator result = std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq);
-
- return result != last ? size_type(result - cbegin()) : npos;
- }
-
- nssv_constexpr14 size_type rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2)
- {
- return rfind(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr14 size_type rfind(CharT const *s, size_type pos, size_type n) const // (3)
- {
- return rfind(basic_string_view(s, n), pos);
- }
-
- nssv_constexpr14 size_type rfind(CharT const *s, size_type pos = npos) const // (4)
- {
- return rfind(basic_string_view(s), pos);
- }
-
- // find_first_of(), 4x:
-
- nssv_constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
- {
- return pos >= size() ? npos
- : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq));
- }
-
- nssv_constexpr size_type find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
- {
- return find_first_of(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr size_type find_first_of(CharT const *s, size_type pos, size_type n) const // (3)
- {
- return find_first_of(basic_string_view(s, n), pos);
- }
-
- nssv_constexpr size_type find_first_of(CharT const *s, size_type pos = 0) const // (4)
- {
- return find_first_of(basic_string_view(s), pos);
- }
-
- // find_last_of(), 4x:
-
- nssv_constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
- {
- return empty() ? npos
- : pos >= size() ? find_last_of(v, size() - 1)
- : to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1), crend(),
- v.cbegin(), v.cend(), Traits::eq));
- }
-
- nssv_constexpr size_type find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2)
- {
- return find_last_of(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr size_type find_last_of(CharT const *s, size_type pos, size_type count) const // (3)
- {
- return find_last_of(basic_string_view(s, count), pos);
- }
-
- nssv_constexpr size_type find_last_of(CharT const *s, size_type pos = npos) const // (4)
- {
- return find_last_of(basic_string_view(s), pos);
- }
-
- // find_first_not_of(), 4x:
-
- nssv_constexpr size_type find_first_not_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
- {
- return pos >= size() ? npos : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v)));
- }
-
- nssv_constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
- {
- return find_first_not_of(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr size_type find_first_not_of(CharT const *s, size_type pos, size_type count) const // (3)
- {
- return find_first_not_of(basic_string_view(s, count), pos);
- }
-
- nssv_constexpr size_type find_first_not_of(CharT const *s, size_type pos = 0) const // (4)
- {
- return find_first_not_of(basic_string_view(s), pos);
- }
-
- // find_last_not_of(), 4x:
-
- nssv_constexpr size_type find_last_not_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1)
- {
- return empty() ? npos
- : pos >= size()
- ? find_last_not_of(v, size() - 1)
- : to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1), crend(), not_in_view(v)));
- }
-
- nssv_constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2)
- {
- return find_last_not_of(basic_string_view(&c, 1), pos);
- }
-
- nssv_constexpr size_type find_last_not_of(CharT const *s, size_type pos, size_type count) const // (3)
- {
- return find_last_not_of(basic_string_view(s, count), pos);
- }
-
- nssv_constexpr size_type find_last_not_of(CharT const *s, size_type pos = npos) const // (4)
- {
- return find_last_not_of(basic_string_view(s), pos);
- }
-
- // Constants:
-
-#if nssv_CPP17_OR_GREATER
- static nssv_constexpr size_type npos = size_type(-1);
-#elif nssv_CPP11_OR_GREATER
- enum : size_type { npos = size_type(-1) };
-#else
- enum { npos = size_type(-1) };
-#endif
-
- private:
- struct not_in_view {
- const basic_string_view v;
-
- nssv_constexpr explicit not_in_view(basic_string_view v) : v(v) {}
-
- nssv_constexpr bool operator()(CharT c) const { return npos == v.find_first_of(c); }
- };
-
- nssv_constexpr size_type to_pos(const_iterator it) const { return it == cend() ? npos : size_type(it - cbegin()); }
-
- nssv_constexpr size_type to_pos(const_reverse_iterator it) const {
- return it == crend() ? npos : size_type(crend() - it - 1);
- }
-
- nssv_constexpr const_reference data_at(size_type pos) const {
-#if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500)
- return data_[pos];
-#else
- return assert(pos < size()), data_[pos];
-#endif
- }
-
- private:
- const_pointer data_;
- size_type size_;
-
- public:
-#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-
- template
- basic_string_view(std::basic_string const &s) nssv_noexcept : data_(s.data()),
- size_(s.size()) {}
-
-#if nssv_HAVE_EXPLICIT_CONVERSION
-
- template explicit operator std::basic_string() const {
- return to_string(Allocator());
- }
-
-#endif // nssv_HAVE_EXPLICIT_CONVERSION
-
-#if nssv_CPP11_OR_GREATER
-
- template >
- std::basic_string to_string(Allocator const &a = Allocator()) const {
- return std::basic_string(begin(), end(), a);
- }
-
-#else
-
- std::basic_string to_string() const { return std::basic_string(begin(), end()); }
-
- template std::basic_string to_string(Allocator const &a) const {
- return std::basic_string(begin(), end(), a);
- }
-
-#endif // nssv_CPP11_OR_GREATER
-
-#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
- };
-
- //
- // Non-member functions:
- //
-
- // 24.4.3 Non-member comparison functions:
- // lexicographically compare two string views (function template):
-
- template
- nssv_constexpr bool operator==(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) == 0;
- }
-
- template
- nssv_constexpr bool operator!=(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) != 0;
- }
-
- template
- nssv_constexpr bool operator<(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) < 0;
- }
-
- template
- nssv_constexpr bool operator<=(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) <= 0;
- }
-
- template
- nssv_constexpr bool operator>(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) > 0;
- }
-
- template
- nssv_constexpr bool operator>=(basic_string_view lhs,
- basic_string_view rhs) nssv_noexcept {
- return lhs.compare(rhs) >= 0;
- }
-
- // Let S be basic_string_view, and sv be an instance of S.
- // Implementations shall provide sufficient additional overloads marked
- // constexpr and noexcept so that an object t with an implicit conversion
- // to S can be compared according to Table 67.
-
-#if !nssv_CPP11_OR_GREATER || nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141)
-
- // accomodate for older compilers:
-
- // ==
-
- template
- nssv_constexpr bool operator==(basic_string_view lhs, char const *rhs) nssv_noexcept {
- return lhs.compare(rhs) == 0;
- }
-
- template
- nssv_constexpr bool operator==(char const *lhs, basic_string_view rhs) nssv_noexcept {
- return rhs.compare(lhs) == 0;
- }
-
- template
- nssv_constexpr bool operator==(basic_string_view