aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Kummerlaender2014-08-16 23:30:36 +0200
committerAdrian Kummerlaender2014-08-16 23:30:36 +0200
commitf6ff54c492df81018cf48da039ee681508f88e46 (patch)
tree0659e0f5bf4529b8c83bebc87119607638f98b7f /src
parent7f6611cded8c1591f1aa1a4c7d70505cb21e7967 (diff)
downloadInputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar.gz
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar.bz2
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar.lz
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar.xz
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.tar.zst
InputXSLT-f6ff54c492df81018cf48da039ee681508f88e46.zip
Implemented primitive optional parameter support for external functions
* renamed FunctionExternalTextFormatter into FunctionExternalCommand ** the goal is to provide a general interface to a variety of external commands *** e.g. not just text formatters but system utilities for file management and so on ** this requires the stdin parameter to be optional as not all external commands require stdin input * implemented "filter_derived" helper template to determine amount of optional parameters ** optional parameters are defined as "boost::optional" specializations *** they in turn can be detected by checking if "boost::optional_detail::optional_tag" is a base class * "callConstructDocument" member method of "FunctionBase" performs additional bounds checking of parameter vector * "boost::optional<std::string>" specific member overload was added to "XObjectValue" helper class ** we will have to provide full specializations for all optional types as C++ prohibits partial member function template specialization * renamed the external function in "PlattformGuard" * changed README.md and test cases accordingly
Diffstat (limited to 'src')
-rw-r--r--src/function/base.h27
-rw-r--r--src/function/external_command.cc (renamed from src/function/external_text_formatter.cc)30
-rw-r--r--src/function/external_command.h31
-rw-r--r--src/function/external_text_formatter.h30
-rw-r--r--src/platform_guard.cc6
-rw-r--r--src/support/filesystem_context.h2
-rw-r--r--src/support/include_entity_resolver.cc2
-rw-r--r--src/support/include_entity_resolver.h2
-rw-r--r--src/support/type/filter.h24
-rw-r--r--src/support/type/xobject_value.cc13
10 files changed, 108 insertions, 59 deletions
diff --git a/src/function/base.h b/src/function/base.h
index 2d1e4c4..a8f93b9 100644
--- a/src/function/base.h
+++ b/src/function/base.h
@@ -5,6 +5,8 @@
#include <xalanc/XPath/Function.hpp>
#include <xalanc/XPath/XObject.hpp>
+#include <boost/optional.hpp>
+
#include <memory>
#include <tuple>
@@ -14,6 +16,7 @@
#include "support/include_entity_resolver.h"
#include "support/dom/document_cache.h"
#include "support/type/sequence.h"
+#include "support/type/filter.h"
#include "support/type/xobject_value.h"
namespace InputXSLT {
@@ -23,7 +26,13 @@ template <
typename... Types
>
class FunctionBase : public xalan::Function {
- static const std::size_t parameter_count = sizeof...(Types);
+ static const std::size_t parameter_count = sizeof...(Types);
+ static const std::size_t optional_parameter_count = std::tuple_size<
+ typename filter_derived<
+ boost::optional_detail::optional_tag,
+ Types...
+ >::type
+ >::value;
public:
FunctionBase(IncludeEntityResolver* resolver):
@@ -108,16 +117,20 @@ class FunctionBase : public xalan::Function {
valueGetter.get<typename std::tuple_element<
Index,
std::tuple<Types...>
- >::type>(parameters[Index])...
+ >::type>(
+ Index < parameters.size()
+ ? parameters[Index]
+ : xalan::XObjectPtr()
+ )...
)
);
}
inline void validateParameters(
- const XObjectArgVectorType& parameters,
+ const XObjectArgVectorType& parameters,
xalan::XPathExecutionContext& executionContext,
- xalan::XalanNode* context,
- const xalan::Locator* locator
+ xalan::XalanNode* context,
+ const xalan::Locator* locator
) const {
const bool anyNull = std::any_of(
parameters.begin(),
@@ -127,7 +140,9 @@ class FunctionBase : public xalan::Function {
}
);
- if ( parameters.size() != parameter_count || anyNull ) {
+ if ( parameters.size() > parameter_count ||
+ parameters.size() < optional_parameter_count ||
+ anyNull ) {
xalan::XPathExecutionContext::GetAndReleaseCachedString guard(
executionContext
);
diff --git a/src/function/external_text_formatter.cc b/src/function/external_command.cc
index 03902e9..bd2bf84 100644
--- a/src/function/external_text_formatter.cc
+++ b/src/function/external_command.cc
@@ -1,4 +1,4 @@
-#include "external_text_formatter.h"
+#include "external_command.h"
#include <xalanc/XSLT/XSLTInputSource.hpp>
@@ -39,9 +39,9 @@ inline xercesc::DOMNode* importDocumentElement(
namespace InputXSLT {
-DomDocumentCache::document_ptr FunctionExternalTextFormatter::constructDocument(
- std::string formatterCommand,
- std::string stdinText
+DomDocumentCache::document_ptr FunctionExternalCommand::constructDocument(
+ std::string command,
+ boost::optional<std::string> stdinText
) const {
DomDocumentCache::document_ptr domDocument(
DomDocumentCache::createDocument("content")
@@ -52,23 +52,21 @@ DomDocumentCache::document_ptr FunctionExternalTextFormatter::constructDocument(
context.stdout_behavior = boost::process::capture_stream();
context.stdin_behavior = boost::process::capture_stream();
- boost::process::child formatterProcess(
- boost::process::launch_shell(
- formatterCommand,
- context
- )
+ boost::process::child commandProcess(
+ boost::process::launch_shell(command, context)
);
- boost::process::postream& inputStream = formatterProcess.get_stdin();
- boost::process::pistream& outputStream = formatterProcess.get_stdout();
-
- inputStream << stdinText;
- inputStream.close();
+ if ( stdinText ) {
+ boost::process::postream& inputStream = commandProcess.get_stdin();
+ inputStream << *stdinText;
+ inputStream.close();
+ }
- boost::process::status status = formatterProcess.wait();
+ boost::process::pistream& outputStream = commandProcess.get_stdout();
+ boost::process::status status = commandProcess.wait();
ResultNodeFacade result(domDocument.get(), "output");
- result.setAttribute("formatter", formatterCommand);
+ result.setAttribute("command", command);
result.setAttribute("code", std::to_string(status.exit_status()));
if ( status.exited() ) {
diff --git a/src/function/external_command.h b/src/function/external_command.h
new file mode 100644
index 0000000..8af5079
--- /dev/null
+++ b/src/function/external_command.h
@@ -0,0 +1,31 @@
+#ifndef INPUTXSLT_SRC_FUNCTION_EXTERNAL_COMMAND_H_
+#define INPUTXSLT_SRC_FUNCTION_EXTERNAL_COMMAND_H_
+
+#include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
+
+#include "base.h"
+
+namespace InputXSLT {
+
+class FunctionExternalCommand : public FunctionBase<
+ FunctionExternalCommand,
+ std::string,
+ boost::optional<std::string>
+> {
+ public:
+ using FunctionBase::FunctionBase;
+
+ protected:
+ friend FunctionBase;
+
+ DomDocumentCache::document_ptr constructDocument(
+ std::string,
+ boost::optional<std::string>
+ ) const;
+
+};
+
+}
+
+#endif // INPUTXSLT_SRC_FUNCTION_EXTERNAL_COMMAND_H_
diff --git a/src/function/external_text_formatter.h b/src/function/external_text_formatter.h
deleted file mode 100644
index 4788784..0000000
--- a/src/function/external_text_formatter.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef INPUTXSLT_SRC_FUNCTION_EXTERNAL_TEXT_FORMATTER_H_
-#define INPUTXSLT_SRC_FUNCTION_EXTERNAL_TEXT_FORMATTER_H_
-
-#include <boost/filesystem.hpp>
-
-#include "base.h"
-
-namespace InputXSLT {
-
-class FunctionExternalTextFormatter : public FunctionBase<
- FunctionExternalTextFormatter,
- std::string,
- std::string
-> {
- public:
- using FunctionBase::FunctionBase;
-
- protected:
- friend FunctionBase;
-
- DomDocumentCache::document_ptr constructDocument(
- std::string,
- std::string
- ) const;
-
-};
-
-}
-
-#endif // INPUTXSLT_SRC_FUNCTION_EXTERNAL_TEXT_FORMATTER_H_
diff --git a/src/platform_guard.cc b/src/platform_guard.cc
index 6be5b4a..f50d976 100644
--- a/src/platform_guard.cc
+++ b/src/platform_guard.cc
@@ -11,7 +11,7 @@
#include "function/read_directory.h"
#include "function/transform.h"
#include "function/generate.h"
-#include "function/external_text_formatter.h"
+#include "function/external_command.h"
namespace InputXSLT {
@@ -56,8 +56,8 @@ PlatformGuard::PlatformGuard(const std::vector<std::string>& path):
xalan::XalanTransformer::installExternalFunctionGlobal(
customNamespace,
- xalan::XalanDOMString("external-text-formatter"),
- InputXSLT::FunctionExternalTextFormatter(&this->include_resolver_)
+ xalan::XalanDOMString("external-command"),
+ InputXSLT::FunctionExternalCommand(&this->include_resolver_)
);
}
diff --git a/src/support/filesystem_context.h b/src/support/filesystem_context.h
index f3875a3..c00fe29 100644
--- a/src/support/filesystem_context.h
+++ b/src/support/filesystem_context.h
@@ -4,7 +4,7 @@
#include <xalanc/XalanDOM/XalanDOMString.hpp>
#include <xalanc/XPath/Function.hpp>
-#include "boost/filesystem.hpp"
+#include <boost/filesystem.hpp>
#include <string>
#include <functional>
diff --git a/src/support/include_entity_resolver.cc b/src/support/include_entity_resolver.cc
index deac1d5..197b217 100644
--- a/src/support/include_entity_resolver.cc
+++ b/src/support/include_entity_resolver.cc
@@ -2,7 +2,7 @@
#include <xercesc/framework/LocalFileInputSource.hpp>
-#include "boost/filesystem.hpp"
+#include <boost/filesystem.hpp>
#include "support/xalan_string.h"
#include "support/xerces_string_guard.h"
diff --git a/src/support/include_entity_resolver.h b/src/support/include_entity_resolver.h
index ea5fb7a..e7c5542 100644
--- a/src/support/include_entity_resolver.h
+++ b/src/support/include_entity_resolver.h
@@ -4,7 +4,7 @@
#include <xercesc/sax/EntityResolver.hpp>
#include <xercesc/sax/InputSource.hpp>
-#include "boost/optional.hpp"
+#include <boost/optional.hpp>
#include <string>
#include <vector>
diff --git a/src/support/type/filter.h b/src/support/type/filter.h
new file mode 100644
index 0000000..4a0e19f
--- /dev/null
+++ b/src/support/type/filter.h
@@ -0,0 +1,24 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_TYPE_FILTER_H_
+#define INPUTXSLT_SRC_SUPPORT_TYPE_FILTER_H_
+
+#include <tuple>
+#include <type_traits>
+
+namespace InputXSLT {
+
+template <
+ typename BaseReference,
+ typename Head,
+ typename... Tail
+>
+struct filter_derived {
+ typedef typename std::conditional<
+ std::is_base_of<BaseReference, Head>::value,
+ std::tuple<Head, Tail...>,
+ std::tuple<Tail...>
+ >::type type;
+};
+
+}
+
+#endif // INPUTXSLT_SRC_SUPPORT_TYPE_FILTER_H_
diff --git a/src/support/type/xobject_value.cc b/src/support/type/xobject_value.cc
index 9bb6648..e457a69 100644
--- a/src/support/type/xobject_value.cc
+++ b/src/support/type/xobject_value.cc
@@ -4,7 +4,8 @@
#include <xalanc/XalanDOM/XalanDocumentFragment.hpp>
#include <boost/algorithm/string.hpp>
-#include "boost/filesystem.hpp"
+#include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
#include <string>
@@ -27,6 +28,16 @@ std::string XObjectValue::get<std::string>(
}
template <>
+boost::optional<std::string> XObjectValue::get<boost::optional<std::string>>(
+ const xalan::XObjectPtr& ptr) const {
+ if ( ptr.null() ) {
+ return boost::optional<std::string>();
+ } else {
+ return this->get<std::string>(ptr);
+ }
+}
+
+template <>
boost::filesystem::path XObjectValue::get<boost::filesystem::path>(
const xalan::XObjectPtr& ptr) const {
const std::string rawPath(