diff options
40 files changed, 1041 insertions, 999 deletions
diff --git a/Jamroot.jam b/Jamroot.jam index 84c2b18..5a29d9a 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -9,7 +9,7 @@ variant coverage : debug ; project icespider : requirements <define>ICE_CPP11_MAPPING - <cxxstd>20 + <cxxstd>23 <visibility>hidden <linkflags>"-Wl,-z,defs,--warn-once,--gc-sections" <variant>release:<lto>on diff --git a/icespider/common/formatters.cpp b/icespider/common/formatters.cpp deleted file mode 100644 index 6bf31c0..0000000 --- a/icespider/common/formatters.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "formatters.h" diff --git a/icespider/common/maybeString.cpp b/icespider/common/maybeString.cpp deleted file mode 100644 index 8dab2cc..0000000 --- a/icespider/common/maybeString.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "maybeString.h" diff --git a/icespider/common/maybeString.h b/icespider/common/maybeString.h index 50928f5..b76da2f 100644 --- a/icespider/common/maybeString.h +++ b/icespider/common/maybeString.h @@ -1,10 +1,8 @@ #pragma once -#include <compare> #include <iosfwd> #include <string> #include <string_view> -#include <type_traits> #include <utility> #include <variant> @@ -14,54 +12,54 @@ namespace IceSpider { MaybeString() = default; // cppcheck-suppress noExplicitConstructor; NOLINTNEXTLINE(hicpp-explicit-conversions) - inline MaybeString(std::string s) : value_ {std::move(s)} { } + MaybeString(std::string str) : valueContainer {std::move(str)} { } // cppcheck-suppress noExplicitConstructor; NOLINTNEXTLINE(hicpp-explicit-conversions) - inline MaybeString(std::string_view s) : value_ {s} { } + MaybeString(std::string_view str) : valueContainer {str} { } // NOLINTNEXTLINE(hicpp-explicit-conversions) - [[nodiscard]] inline operator std::string_view() const + [[nodiscard]] operator std::string_view() const { - if (value_.index() == 0) { - return std::get<0>(value_); + if (valueContainer.index() == 0) { + return std::get<0>(valueContainer); } - return std::get<1>(value_); + return std::get<1>(valueContainer); } - [[nodiscard]] inline std::string_view + [[nodiscard]] std::string_view value() const { return *this; } - [[nodiscard]] inline bool + [[nodiscard]] bool isString() const { - return value_.index() > 0; + return valueContainer.index() > 0; } - [[nodiscard]] inline bool - operator<(const MaybeString & o) const + [[nodiscard]] bool + operator<(const MaybeString & other) const { - return value() < o.value(); + return value() < other.value(); } - [[nodiscard]] inline bool - operator<(const std::string_view o) const + [[nodiscard]] bool + operator<(const std::string_view other) const { - return value() < o; + return value() < other; } private: - using value_type = std::variant<std::string_view, std::string>; - value_type value_; + using ValueType = std::variant<std::string_view, std::string>; + ValueType valueContainer; }; }; namespace std { inline std::ostream & - operator<<(std::ostream & s, const IceSpider::MaybeString & ms) + operator<<(std::ostream & strm, const IceSpider::MaybeString & value) { - return s << ms.value(); + return strm << value.value(); } } diff --git a/icespider/common/pathparts.cpp b/icespider/common/pathparts.cpp index cebfde0..feeab1c 100644 --- a/icespider/common/pathparts.cpp +++ b/icespider/common/pathparts.cpp @@ -2,26 +2,25 @@ #include <boost/algorithm/string/compare.hpp> #include <boost/algorithm/string/find_iterator.hpp> #include <boost/algorithm/string/finder.hpp> -#include <string> namespace ba = boost::algorithm; namespace IceSpider { - const auto slash = ba::first_finder("/", ba::is_equal()); + const auto SLASH = ba::first_finder("/", ba::is_equal()); - Path::Path(const std::string_view p) : path(p) + Path::Path(const std::string_view path) : path(path) { - auto relp = p.substr(1); + auto relp = path.substr(1); if (relp.empty()) { return; } - for (auto pi = ba::make_split_iterator(relp, slash); pi != decltype(pi)(); ++pi) { - std::string_view pp {pi->begin(), pi->end()}; - if (pp.front() == '{' && pp.back() == '}') { - parts.push_back(std::make_unique<PathParameter>(pp)); + for (auto pi = ba::make_split_iterator(relp, SLASH); pi != decltype(pi)(); ++pi) { + std::string_view pathPart {pi->begin(), pi->end()}; + if (pathPart.front() == '{' && pathPart.back() == '}') { + parts.push_back(std::make_unique<PathParameter>(pathPart)); } else { - parts.push_back(std::make_unique<PathLiteral>(pp)); + parts.push_back(std::make_unique<PathLiteral>(pathPart)); } } } @@ -43,15 +42,15 @@ namespace IceSpider { == pathparts.end(); } - PathLiteral::PathLiteral(const std::string_view p) : value(p) { } + PathLiteral::PathLiteral(const std::string_view value) : value(value) { } bool - PathLiteral::matches(const std::string_view v) const + PathLiteral::matches(const std::string_view candidate) const { - return value == v; + return value == candidate; } - PathParameter::PathParameter(const std::string_view s) : name(s.substr(1, s.length() - 2)) { } + PathParameter::PathParameter(const std::string_view fmt) : name(fmt.substr(1, fmt.length() - 2)) { } bool PathParameter::matches(const std::string_view) const diff --git a/icespider/common/pathparts.h b/icespider/common/pathparts.h index e972a6f..76491a3 100644 --- a/icespider/common/pathparts.h +++ b/icespider/common/pathparts.h @@ -16,25 +16,25 @@ namespace IceSpider { virtual ~PathPart() = default; SPECIAL_MEMBERS_DEFAULT(PathPart); - [[nodiscard]] virtual bool matches(const std::string_view) const = 0; + [[nodiscard]] virtual bool matches(std::string_view) const = 0; }; using PathPartPtr = std::unique_ptr<PathPart>; class DLL_PUBLIC PathLiteral : public PathPart { public: - explicit PathLiteral(const std::string_view v); + explicit PathLiteral(std::string_view value); - [[nodiscard]] bool matches(const std::string_view) const override; + [[nodiscard]] bool matches(std::string_view) const override; const std::string_view value; }; class DLL_PUBLIC PathParameter : public PathPart { public: - explicit PathParameter(const std::string_view); + explicit PathParameter(std::string_view fmt); - [[nodiscard]] bool matches(const std::string_view) const override; + [[nodiscard]] bool matches(std::string_view) const override; const std::string_view name; }; @@ -43,7 +43,7 @@ namespace IceSpider { public: using PathParts = std::vector<PathPartPtr>; - explicit Path(const std::string_view); + explicit Path(std::string_view path); std::string_view path; diff --git a/icespider/compile/main.cpp b/icespider/compile/main.cpp index fa679f9..848c2a2 100644 --- a/icespider/compile/main.cpp +++ b/icespider/compile/main.cpp @@ -9,6 +9,7 @@ #include <cstdlib> #include <filesystem> #include <iostream> +#include <ranges> #include <string> #include <string_view> #include <utility> @@ -21,14 +22,13 @@ namespace { std::string defaultPostProcessor() { - constexpr std::array<const std::pair<std::string_view, std::string_view>, 1> pps {{ + constexpr std::array<const std::pair<std::string_view, std::string_view>, 1> POST_PROCESSORS {{ {"clang-format", "-i"}, }}; - const std::string_view path {getenv("PATH") ?: "/usr/bin"}; - const auto pathBegin = make_split_iterator(path, first_finder(":", boost::is_equal())); - for (const auto & [cmd, opts] : pps) { - for (auto p = pathBegin; p != decltype(pathBegin) {}; ++p) { - if (std::filesystem::exists(std::filesystem::path(p->begin(), p->end()) / cmd)) { + const std::string_view pathEnv {getenv("PATH") ?: "/usr/bin"}; + for (const auto & [cmd, opts] : POST_PROCESSORS) { + for (const auto & path : std::ranges::split_view(pathEnv, ':')) { + if (std::filesystem::exists(std::filesystem::path(path.begin(), path.end()) / cmd)) { return "%? %?"_fmt(cmd, opts); } } @@ -38,10 +38,10 @@ namespace { } int -main(int c, char ** v) +main(int argc, char ** argv) { bool showHelp = false; - IceSpider::Compile::RouteCompiler rc; + IceSpider::Compile::RouteCompiler routeCompiler; std::filesystem::path input, output; std::string post; po::options_description opts("IceSpider compile options"); @@ -49,26 +49,26 @@ main(int c, char ** v) opts.add_options() ("input", po::value(&input), "Input .json file") ("output", po::value(&output), "Output .cpp file") - ("include,I", po::value(&rc.searchPath)->composing(), "Search path") + ("include,I", po::value(&routeCompiler.searchPath)->composing(), "Search path") ("post,p", po::value(&post)->default_value(defaultPostProcessor()), "Post-process command") ("help,h", po::value(&showHelp)->default_value(false)->zero_tokens(), "Help") ; // clang-format on po::positional_options_description pod; pod.add("input", 1).add("output", 2); - po::variables_map vm; - po::store(po::command_line_parser(c, v).options(opts).positional(pod).run(), vm); - po::notify(vm); + po::variables_map varMap; + po::store(po::command_line_parser(argc, argv).options(opts).positional(pod).run(), varMap); + po::notify(varMap); if (showHelp || input.empty() || output.empty()) { // LCOV_EXCL_START - std::cout << opts << std::endl; + std::cout << opts << '\n'; return 1; // LCOV_EXCL_STOP } - rc.searchPath.push_back(input.parent_path()); - rc.compile(input, output); + routeCompiler.searchPath.push_back(input.parent_path()); + routeCompiler.compile(input, output); if (!post.empty()) { auto outputh = std::filesystem::path {output}.replace_extension(".h"); diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index cc8a960..564d067 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -15,7 +15,6 @@ #include <fprintbf.h> #include <http.h> #include <initializer_list> -#include <list> #include <memory> #include <pathparts.h> #include <scopeExit.h> @@ -27,6 +26,15 @@ #include <utility> namespace IceSpider::Compile { + namespace { + Ice::StringSeq + operator+(Ice::StringSeq target, std::string value) + { + target.emplace_back(std::move(value)); + return target; + } + } + using namespace AdHoc::literals; RouteCompiler::RouteCompiler() @@ -35,35 +43,29 @@ namespace IceSpider::Compile { } RouteConfigurationPtr - RouteCompiler::loadConfiguration(const std::filesystem::path & input) const + RouteCompiler::loadConfiguration(const std::filesystem::path & input) { auto deserializer = Slicer::DeserializerPtr( Slicer::FileDeserializerFactory::createNew(input.extension().string(), input)); return Slicer::DeserializeAnyWith<RouteConfigurationPtr>(deserializer); } - Ice::StringSeq - operator+(Ice::StringSeq ss, const std::string & s) - { - ss.push_back(s); - return ss; - } - Slice::OperationPtr // NOLINTNEXTLINE(misc-no-recursion) - RouteCompiler::findOperation(const std::string & on, const Slice::ContainerPtr & c, const Ice::StringSeq & ns) + RouteCompiler::findOperation( + const std::string & operationName, const Slice::ContainerPtr & container, const Ice::StringSeq & nameSpace) { - for (const auto & cls : c->classes()) { - auto fqcn = ns + cls->name(); - for (const auto & op : cls->allOperations()) { - if (boost::algorithm::join(fqcn + op->name(), ".") == on) { - return op; + for (const auto & cls : container->classes()) { + auto fqcn = nameSpace + cls->name(); + for (const auto & operation : cls->allOperations()) { + if (boost::algorithm::join(fqcn + operation->name(), ".") == operationName) { + return operation; } } } - for (const auto & m : c->modules()) { - if (auto op = findOperation(on, m, ns + m->name())) { - return op; + for (const auto & module : container->modules()) { + if (auto operation = findOperation(operationName, module, nameSpace + module->name())) { + return operation; } } return nullptr; @@ -71,109 +73,116 @@ namespace IceSpider::Compile { Slice::OperationPtr // NOLINTNEXTLINE(misc-no-recursion) - RouteCompiler::findOperation(const std::string & on, const Units & us) + RouteCompiler::findOperation(const std::string & operationName, const Units & units) { - for (const auto & u : us) { - if (auto op = findOperation(on, u.second)) { - return op; + for (const auto & unit : units) { + if (auto operation = findOperation(operationName, unit.second)) { + return operation; } } - throw std::runtime_error("Find operation " + on + " failed."); + throw std::runtime_error("Find operation " + operationName + " failed."); } std::optional<RouteCompiler::Type> // NOLINTNEXTLINE(misc-no-recursion) - RouteCompiler::findType(const std::string & tn, const Slice::ContainerPtr & c, const Ice::StringSeq & ns) + RouteCompiler::findType( + const std::string & typeName, const Slice::ContainerPtr & container, const Ice::StringSeq & nameSpace) { - for (const auto & strct : c->structs()) { - auto fqon = boost::algorithm::join(ns + strct->name(), "."); - if (fqon == tn) { - return {{Slice::typeToString(strct), {}, strct->dataMembers()}}; + for (const auto & strct : container->structs()) { + auto fqon = boost::algorithm::join(nameSpace + strct->name(), "."); + if (fqon == typeName) { + return {{.type = Slice::typeToString(strct), .scoped = {}, .members = strct->dataMembers()}}; } - auto t = findType(tn, strct, ns + strct->name()); - } - for (const auto & cls : c->classes()) { - auto fqon = boost::algorithm::join(ns + cls->name(), "."); - if (fqon == tn) { - return {{Slice::typeToString(cls->declaration()), cls->scoped(), cls->dataMembers()}}; + // auto t = findType(typeName, strct, nameSpace + strct->name()); + } + for (const auto & cls : container->classes()) { + auto fqon = boost::algorithm::join(nameSpace + cls->name(), "."); + if (fqon == typeName) { + return {{.type = Slice::typeToString(cls->declaration()), + .scoped = cls->scoped(), + .members = cls->dataMembers()}}; } - if (auto t = findType(tn, cls, ns + cls->name())) { - return t; + if (auto type = findType(typeName, cls, nameSpace + cls->name())) { + return type; } } - for (const auto & m : c->modules()) { - if (auto t = findType(tn, m, ns + m->name())) { - return t; + for (const auto & module : container->modules()) { + if (auto type = findType(typeName, module, nameSpace + module->name())) { + return type; } } return {}; } RouteCompiler::Type - RouteCompiler::findType(const std::string & tn, const Units & us) + RouteCompiler::findType(const std::string & typeName, const Units & units) { - for (const auto & u : us) { - if (auto t = findType(tn, u.second)) { - return *t; + for (const auto & unit : units) { + if (auto type = findType(typeName, unit.second)) { + return *type; } } - throw std::runtime_error("Find type " + tn + " failed."); + throw std::runtime_error("Find type " + typeName + " failed."); } RouteCompiler::ParameterMap - RouteCompiler::findParameters(const RoutePtr & r, const Units & us) + RouteCompiler::findParameters(const RoutePtr & route, const Units & units) { - RouteCompiler::ParameterMap pm; - for (const auto & o : r->operations) { - auto op = findOperation(o.second->operation, us); - if (!op) { - throw std::runtime_error("Find operator failed for " + r->path); - } - for (const auto & p : op->parameters()) { - auto po = o.second->paramOverrides.find(p->name()); - if (po != o.second->paramOverrides.end()) { - pm[po->second] = p; + RouteCompiler::ParameterMap parameters; + for (const auto & operationName : route->operations) { + auto operation = findOperation(operationName.second->operation, units); + if (!operation) { + throw std::runtime_error("Find operation failed for " + route->path); + } + for (const auto & parameter : operation->parameters()) { + auto parameterOverride = operationName.second->paramOverrides.find(parameter->name()); + if (parameterOverride != operationName.second->paramOverrides.end()) { + parameters[parameterOverride->second] = parameter; } else { - pm[p->name()] = p; + parameters[parameter->name()] = parameter; } } } - return pm; + return parameters; } void - RouteCompiler::applyDefaults(const RouteConfigurationPtr & c, const Units & u) const + RouteCompiler::applyDefaults(const RouteConfigurationPtr & routeConfig, const Units & units) { - for (const auto & r : c->routes) { - if (r.second->operation) { - r.second->operations[std::string()] = std::make_shared<Operation>(*r.second->operation, StringMap()); - } - auto ps = findParameters(r.second, u); - for (const auto & p : ps) { - auto defined = r.second->params.find(p.first); - if (defined != r.second->params.end()) { + for (const auto & route : routeConfig->routes) { + if (route.second->operation) { + route.second->operations[std::string()] + = std::make_shared<Operation>(*route.second->operation, StringMap()); + } + const auto parameters = findParameters(route.second, units); + for (const auto & parameter : parameters) { + auto defined = route.second->params.find(parameter.first); + if (defined != route.second->params.end()) { if (!defined->second->key && defined->second->source != ParameterSource::Body) { defined->second->key = defined->first; } } else { - defined = r.second->params - .insert({p.first, - std::make_shared<Parameter>(ParameterSource::URL, p.first, false, + defined = route.second->params + .insert({parameter.first, + std::make_shared<Parameter>(ParameterSource::URL, parameter.first, false, Ice::optional<std::string>(), Ice::optional<std::string>(), false)}) .first; } - auto d = defined->second; - if (d->source == ParameterSource::URL) { - Path path(r.second->path); - d->hasUserSource = std::find_if(path.parts.begin(), path.parts.end(), [d](const auto & pp) { - if (auto par = dynamic_cast<PathParameter *>(pp.get())) { - return par->name == *d->key; - } - return false; - }) != path.parts.end(); + auto definition = defined->second; + if (definition->source == ParameterSource::URL) { + Path path(route.second->path); + definition->hasUserSource + = std::find_if(path.parts.begin(), path.parts.end(), + [definition](const auto & paramPtr) { + if (auto pathParam = dynamic_cast<PathParameter *>(paramPtr.get())) { + return pathParam->name == *definition->key; + } + return false; + }) + != path.parts.end(); } } } @@ -193,8 +202,8 @@ namespace IceSpider::Compile { applyDefaults(configuration, units); AdHoc::ScopeExit uDestroy([&units]() { - for (auto & u : units) { - u.second->destroy(); + for (auto & unit : units) { + unit.second->destroy(); } }); @@ -212,15 +221,15 @@ namespace IceSpider::Compile { } RouteCompiler::Units - RouteCompiler::loadUnits(const RouteConfigurationPtr & c) const + RouteCompiler::loadUnits(const RouteConfigurationPtr & routeConfig) const { RouteCompiler::Units units; AdHoc::ScopeExit uDestroy; - for (const auto & slice : c->slices) { + for (const auto & slice : routeConfig->slices) { std::filesystem::path realSlice; - for (const auto & p : searchPath) { - if (std::filesystem::exists(p / slice)) { - realSlice = p / slice; + for (const auto & path : searchPath) { + if (std::filesystem::exists(path / slice)) { + realSlice = path / slice; break; } } @@ -228,9 +237,9 @@ namespace IceSpider::Compile { throw std::runtime_error("Could not find slice file"); } std::vector<std::string> cppArgs; - for (const auto & p : searchPath) { + for (const auto & path : searchPath) { cppArgs.emplace_back("-I"); - cppArgs.emplace_back(p.string()); + cppArgs.emplace_back(path.string()); } Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("IceSpider", realSlice.string(), cppArgs); FILE * cppHandle = icecpp->preprocess(false); @@ -239,12 +248,12 @@ namespace IceSpider::Compile { throw std::runtime_error("Preprocess failed"); } - Slice::UnitPtr u = Slice::Unit::createUnit(false, false, false, false); - uDestroy.onFailure.emplace_back([u]() { - u->destroy(); + Slice::UnitPtr unit = Slice::Unit::createUnit(false, false, false, false); + uDestroy.onFailure.emplace_back([unit]() { + unit->destroy(); }); - int parseStatus = u->parse(realSlice.string(), cppHandle, false); + int parseStatus = unit->parse(realSlice.string(), cppHandle, false); if (!icecpp->close()) { throw std::runtime_error("Preprocess close failed"); @@ -254,57 +263,85 @@ namespace IceSpider::Compile { throw std::runtime_error("Unit parse failed"); } - units[slice] = u; + units[slice] = unit; } return units; } - template<typename... X> - void - fprintbf(unsigned int indent, FILE * output, const X &... x) - { - for (; indent > 0; --indent) { - fputc('\t', output); + namespace { + template<typename... Params> + void + fprintbf(unsigned int indent, FILE * output, Params &&... params) + { + for (; indent > 0; --indent) { + fputc('\t', output); + } + // NOLINTNEXTLINE(hicpp-no-array-decay) + fprintbf(output, std::forward<Params>(params)...); } - // NOLINTNEXTLINE(hicpp-no-array-decay) - fprintbf(output, x...); - } - template<typename Enum> - std::string - getEnumString(Enum & e) - { - return Slicer::ModelPartForEnum<Enum>::lookup(e); - } + template<typename Enum> + std::string + getEnumString(Enum & enumValue) + { + return Slicer::ModelPartForEnum<Enum>::lookup(enumValue); + } - namespace { std::string - outputSerializerClass(const IceSpider::OutputSerializers::value_type & os) + outputSerializerClass(const IceSpider::OutputSerializers::value_type & outputSerializer) { - return boost::algorithm::replace_all_copy(os.second->serializer, ".", "::"); + return boost::algorithm::replace_all_copy(outputSerializer.second->serializer, ".", "::"); } AdHocFormatter(MimePair, R"C({ "%?", "%?" })C"); std::string - outputSerializerMime(const IceSpider::OutputSerializers::value_type & os) + outputSerializerMime(const IceSpider::OutputSerializers::value_type & outputSerializer) + { + auto slash = outputSerializer.first.find('/'); + return MimePair::get(outputSerializer.first.substr(0, slash), outputSerializer.first.substr(slash + 1)); + } + + void + processParameterSourceBody( + FILE * output, const Parameters::value_type & param, bool & doneBody, std::string_view paramType) { - auto slash = os.first.find('/'); - return MimePair::get(os.first.substr(0, slash), os.first.substr(slash + 1)); + if (param.second->key) { + if (!doneBody) { + if (param.second->type) { + fprintbf(4, output, "const auto _pbody(request->getBody<%s>());\n", *param.second->type); + } + else { + fprintbf(4, output, "const auto _pbody(request->getBody<IceSpider::StringMap>());\n"); + } + doneBody = true; + } + if (param.second->type) { + fprintbf(4, output, "const auto _p_%s(_pbody->%s", param.first, param.first); + } + else { + fprintbf(4, output, "const auto _p_%s(request->getBodyParam<%s>(_pbody, _pn_%s)", param.first, + paramType, param.first); + } + } + else { + fprintbf(4, output, "const auto _p_%s(request->getBody<%s>()", param.first, paramType); + } } } void - RouteCompiler::registerOutputSerializers(FILE * output, const RoutePtr & r) const + RouteCompiler::registerOutputSerializers(FILE * output, const RoutePtr & route) { - for (const auto & os : r->outputSerializers) { - fprintbf(4, output, "addRouteSerializer(%s,\n", outputSerializerMime(os)); - fprintbf(6, output, "std::make_shared<%s::IceSpiderFactory>(", outputSerializerClass(os)); - for (auto p = os.second->params.begin(); p != os.second->params.end(); ++p) { - if (p != os.second->params.begin()) { + for (const auto & outputSerializer : route->outputSerializers) { + fprintbf(4, output, "addRouteSerializer(%s,\n", outputSerializerMime(outputSerializer)); + fprintbf(6, output, "std::make_shared<%s::IceSpiderFactory>(", outputSerializerClass(outputSerializer)); + for (auto parameter = outputSerializer.second->params.begin(); + parameter != outputSerializer.second->params.end(); ++parameter) { + if (parameter != outputSerializer.second->params.begin()) { fputs(", ", output); } - fputs(p->c_str(), output); + fputs(parameter->c_str(), output); } fputs("));\n", output); } @@ -312,22 +349,22 @@ namespace IceSpider::Compile { void RouteCompiler::processConfiguration(FILE * output, FILE * outputh, const std::string & name, - const RouteConfigurationPtr & c, const Units & units) const + const RouteConfigurationPtr & routeConfig, const Units & units) { fputs("// This source files was generated by IceSpider.\n", output); - fprintbf(output, "// Configuration name: %s\n\n", c->name); + fprintbf(output, "// Configuration name: %s\n\n", routeConfig->name); fputs("#pragma once\n", outputh); fputs("// This source files was generated by IceSpider.\n", outputh); - fprintbf(outputh, "// Configuration name: %s\n\n", c->name); + fprintbf(outputh, "// Configuration name: %s\n\n", routeConfig->name); fputs("// Configuration headers.\n", output); fprintbf(output, "#include \"%s.h\"\n", name); fputs("\n// Interface headers.\n", output); fputs("\n// Interface headers.\n", outputh); - for (const auto & s : c->slices) { - std::filesystem::path slicePath(s); + for (const auto & slice : routeConfig->slices) { + std::filesystem::path slicePath(slice); slicePath.replace_extension(".h"); fprintbf(output, "#include <%s>\n", slicePath.string()); fprintbf(outputh, "#include <%s>\n", slicePath.string()); @@ -359,246 +396,230 @@ namespace IceSpider::Compile { fprintbf(output, "#include <%s>\n", header); } - if (!c->headers.empty()) { + if (!routeConfig->headers.empty()) { fputs("\n// Extra headers.\n", output); fputs("\n// Extra headers.\n", outputh); - for (const auto & h : c->headers) { - fprintbf(output, "#include <%s> // IWYU pragma: keep\n", h); - fprintbf(outputh, "#include <%s> // IWYU pragma: keep\n", h); + for (const auto & header : routeConfig->headers) { + fprintbf(output, "#include <%s> // IWYU pragma: keep\n", header); + fprintbf(outputh, "#include <%s> // IWYU pragma: keep\n", header); } } - processBases(output, outputh, c, units); - processRoutes(output, c, units); + processBases(output, outputh, routeConfig, units); + processRoutes(output, routeConfig, units); fputs("\n// End generated code.\n", output); } void - RouteCompiler::processBases(FILE * output, FILE * outputh, const RouteConfigurationPtr & c, const Units & u) const + RouteCompiler::processBases( + FILE * output, FILE * outputh, const RouteConfigurationPtr & routeConfig, const Units & units) { fputs("\n", outputh); - fprintbf(outputh, "namespace %s {\n", c->name); + fprintbf(outputh, "namespace %s {\n", routeConfig->name); fprintbf(1, outputh, "// Base classes.\n\n"); fputs("\n", output); - fprintbf(output, "namespace %s {\n", c->name); + fprintbf(output, "namespace %s {\n", routeConfig->name); fprintbf(1, output, "// Base classes.\n\n"); - for (const auto & r : c->routeBases) { - processBase(output, outputh, r, u); + for (const auto & route : routeConfig->routeBases) { + processBase(output, outputh, route, units); } - fprintbf(output, "} // namespace %s\n\n", c->name); - fprintbf(outputh, "} // namespace %s\n\n", c->name); + fprintbf(output, "} // namespace %s\n\n", routeConfig->name); + fprintbf(outputh, "} // namespace %s\n\n", routeConfig->name); } void - RouteCompiler::processBase(FILE * output, FILE * outputh, const RouteBases::value_type & b, const Units &) const + RouteCompiler::processBase(FILE * output, FILE * outputh, const RouteBases::value_type & route, const Units &) { - fprintbf(1, outputh, "class %s {\n", b.first); + fprintbf(1, outputh, "class %s {\n", route.first); fprintbf(2, outputh, "protected:\n"); - fprintbf(3, outputh, "explicit %s(const IceSpider::Core * core);\n\n", b.first); - for (const auto & f : b.second->functions) { - fprintbf(3, outputh, "%s;\n", f); + fprintbf(3, outputh, "explicit %s(const IceSpider::Core * core);\n\n", route.first); + for (const auto & function : route.second->functions) { + fprintbf(3, outputh, "%s;\n", function); } - fprintbf(1, output, "%s::%s(const IceSpider::Core * core)", b.first, b.first); - if (!b.second->proxies.empty()) { + fprintbf(1, output, "%s::%s(const IceSpider::Core * core)", route.first, route.first); + if (!route.second->proxies.empty()) { fputs(" :", output); } fputs("\n", output); - unsigned int pn = 0; - for (const auto & p : b.second->proxies) { - fprintbf(3, outputh, "const %sPrxPtr prx%u;\n", boost::algorithm::replace_all_copy(p, ".", "::"), pn); - fprintbf(3, output, "prx%u(core->getProxy<%s>())", pn, boost::algorithm::replace_all_copy(p, ".", "::")); - if (++pn < b.second->proxies.size()) { + unsigned int proxyNum = 0; + for (const auto & proxy : route.second->proxies) { + fprintbf(3, outputh, "const %sPrxPtr prx%u;\n", boost::algorithm::replace_all_copy(proxy, ".", "::"), + proxyNum); + fprintbf(3, output, "prx%u(core->getProxy<%s>())", proxyNum, + boost::algorithm::replace_all_copy(proxy, ".", "::")); + if (++proxyNum < route.second->proxies.size()) { fputs(",", output); } fputs("\n", output); } - fprintbf(1, outputh, "}; // %s\n", b.first); + fprintbf(1, outputh, "}; // %s\n", route.first); fprintbf(1, output, "{ }\n"); } void - RouteCompiler::processRoutes(FILE * output, const RouteConfigurationPtr & c, const Units & u) const + RouteCompiler::processRoutes(FILE * output, const RouteConfigurationPtr & routeConfig, const Units & units) { fputs("\n", output); - fprintbf(output, "namespace %s {\n", c->name); + fprintbf(output, "namespace %s {\n", routeConfig->name); fprintbf(1, output, "// Implementation classes.\n\n"); - for (const auto & r : c->routes) { - processRoute(output, r, u); + for (const auto & route : routeConfig->routes) { + processRoute(output, route, units); } - fprintbf(output, "} // namespace %s\n\n", c->name); + fprintbf(output, "} // namespace %s\n\n", routeConfig->name); fputs("// Register route handlers.\n", output); - for (const auto & r : c->routes) { - fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", c->name, r.first); + for (const auto & route : routeConfig->routes) { + fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", routeConfig->name, route.first); } } void - RouteCompiler::processRoute(FILE * output, const Routes::value_type & r, const Units & units) const + RouteCompiler::processRoute(FILE * output, const Routes::value_type & route, const Units & units) { - std::string methodName = getEnumString(r.second->method); + std::string methodName = getEnumString(route.second->method); - fprintbf(1, output, "// Route name: %s\n", r.first); - fprintbf(1, output, "// path: %s\n", r.second->path); - fprintbf(1, output, "class %s : public IceSpider::IRouteHandler", r.first); - for (const auto & b : r.second->bases) { + fprintbf(1, output, "// Route name: %s\n", route.first); + fprintbf(1, output, "// path: %s\n", route.second->path); + fprintbf(1, output, "class %s : public IceSpider::IRouteHandler", route.first); + for (const auto & base : route.second->bases) { fputs(",\n", output); - fprintbf(3, output, "public %s", b); + fprintbf(3, output, "public %s", base); } fputs(" {\n", output); fprintbf(2, output, "public:\n"); - fprintbf(3, output, "explicit %s(const IceSpider::Core * core) :\n", r.first); - fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, r.second->path); - for (const auto & b : r.second->bases) { + fprintbf(3, output, "explicit %s(const IceSpider::Core * core) :\n", route.first); + fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, + route.second->path); + for (const auto & base : route.second->bases) { fputs(",\n", output); - fprintbf(4, output, "%s(core)", b); + fprintbf(4, output, "%s(core)", base); } - auto proxies = initializeProxies(output, r.second); + auto proxies = initializeProxies(output, route.second); fputs("\n", output); fprintbf(3, output, "{\n"); - registerOutputSerializers(output, r.second); + registerOutputSerializers(output, route.second); fprintbf(3, output, "}\n\n"); fprintbf(3, output, "void execute(IceSpider::IHttpRequest * request) const override\n"); fprintbf(3, output, "{\n"); - auto ps = findParameters(r.second, units); + auto parameters = findParameters(route.second, units); bool doneBody = false; - for (const auto & p : r.second->params) { - if (p.second->hasUserSource) { - auto ip = ps.find(p.first)->second; - const auto paramType = Slice::typeToString(ip->type(), false, "", ip->getMetaData()); - // This shouldn't be needed... the warning is ignored elsewhere to no effect - if (p.second->source == ParameterSource::Body) { - if (p.second->key) { - if (!doneBody) { - if (p.second->type) { - fprintbf(4, output, "const auto _pbody(request->getBody<%s>());\n", *p.second->type); - } - else { - fprintbf(4, output, "const auto _pbody(request->getBody<IceSpider::StringMap>());\n"); - } - doneBody = true; - } - if (p.second->type) { - fprintbf(4, output, "const auto _p_%s(_pbody->%s", p.first, p.first); - } - else { - fprintbf(4, output, "const auto _p_%s(request->getBodyParam<%s>(_pbody, _pn_%s)", p.first, - paramType, p.first); - } - } - else { - fprintbf(4, output, "const auto _p_%s(request->getBody<%s>()", p.first, paramType); - } + for (const auto & param : route.second->params) { + if (param.second->hasUserSource) { + auto iceParamDecl = parameters.find(param.first)->second; + const auto paramType + = Slice::typeToString(iceParamDecl->type(), false, "", iceParamDecl->getMetaData()); + if (param.second->source == ParameterSource::Body) { + processParameterSourceBody(output, param, doneBody, paramType); } else { - fprintbf(4, output, "const auto _p_%s(request->get%sParam<%s>(_p%c_%s)", p.first, - getEnumString(p.second->source), paramType, - p.second->source == ParameterSource::URL ? 'i' : 'n', p.first); + fprintbf(4, output, "const auto _p_%s(request->get%sParam<%s>(_p%c_%s)", param.first, + getEnumString(param.second->source), paramType, + param.second->source == ParameterSource::URL ? 'i' : 'n', param.first); } - if (!p.second->isOptional && p.second->source != ParameterSource::URL) { + if (!param.second->isOptional && param.second->source != ParameterSource::URL) { fprintbf(0, output, " /\n"); - if (p.second->defaultExpr) { - fprintbf(5, output, " [this]() { return _pd_%s; }", p.first); + if (param.second->defaultExpr) { + fprintbf(5, output, " [this]() { return _pd_%s; }", param.first); } else { fprintbf(5, output, " [this]() { return requiredParameterNotFound<%s>(\"%s\", _pn_%s); }", - paramType, getEnumString(p.second->source), p.first); + paramType, getEnumString(param.second->source), param.first); } } fprintbf(0, output, ");\n"); } } - if (r.second->operation) { - addSingleOperation(output, r.second, findOperation(*r.second->operation, units)); + if (route.second->operation) { + addSingleOperation(output, route.second, findOperation(*route.second->operation, units)); } else { - addMashupOperations(output, r.second, proxies, units); + addMashupOperations(output, route.second, proxies, units); } fprintbf(3, output, "}\n\n"); fprintbf(2, output, "private:\n"); declareProxies(output, proxies); - for (const auto & p : r.second->params) { - if (p.second->hasUserSource) { - if (p.second->source == ParameterSource::URL) { - Path path(r.second->path); + for (const auto & param : route.second->params) { + if (param.second->hasUserSource) { + if (param.second->source == ParameterSource::URL) { + Path path(route.second->path); long idx = -1; - for (const auto & pp : path.parts) { - if (auto par = dynamic_cast<PathParameter *>(pp.get())) { - if (par->name == *p.second->key) { - idx = &pp - &path.parts.front(); + for (const auto & pathPart : path.parts) { + if (auto par = dynamic_cast<PathParameter *>(pathPart.get())) { + if (par->name == *param.second->key) { + idx = &pathPart - &path.parts.front(); } } } - fprintbf(3, output, "static constexpr unsigned int _pi_%s{%ld};\n", p.first, idx); + fprintbf(3, output, "static constexpr unsigned int _pi_%s{%ld};\n", param.first, idx); } else { - fprintbf(3, output, "static constexpr std::string_view _pn_%s{", p.first); - if (p.second->key) { - fprintbf(output, "\"%s\"", *p.second->key); + fprintbf(3, output, "static constexpr std::string_view _pn_%s{", param.first); + if (param.second->key) { + fprintbf(output, "\"%s\"", *param.second->key); } fputs("};\n", output); } } - if (p.second->defaultExpr) { - auto ip = ps.find(p.first)->second; - fprintbf(3, output, "static const %s _pd_%s{%s};\n", Slice::typeToString(ip->type()), p.first, - *p.second->defaultExpr); + if (param.second->defaultExpr) { + auto iceParamDecl = parameters.find(param.first)->second; + fprintbf(3, output, "static const %s _pd_%s{%s};\n", Slice::typeToString(iceParamDecl->type()), + param.first, *param.second->defaultExpr); } } fprintbf(1, output, "};\n\n"); } RouteCompiler::Proxies - RouteCompiler::initializeProxies(FILE * output, const RoutePtr & r) const + RouteCompiler::initializeProxies(FILE * output, const RoutePtr & route) { Proxies proxies; - int n = 0; - for (const auto & o : r->operations) { - auto proxyName = o.second->operation.substr(0, o.second->operation.find_last_of('.')); - if (proxies.find(proxyName) == proxies.end()) { - proxies[proxyName] = n; + int proxyNum = 0; + for (const auto & operation : route->operations) { + auto proxyName = operation.second->operation.substr(0, operation.second->operation.find_last_of('.')); + if (!proxies.contains(proxyName)) { + proxies[proxyName] = proxyNum; fputs(",\n", output); - fprintbf(4, output, "prx%d(core->getProxy<%s>())", n, + fprintbf(4, output, "prx%d(core->getProxy<%s>())", proxyNum, boost::algorithm::replace_all_copy(proxyName, ".", "::")); - n += 1; + proxyNum += 1; } } return proxies; } void - RouteCompiler::declareProxies(FILE * output, const Proxies & proxies) const + RouteCompiler::declareProxies(FILE * output, const Proxies & proxies) { - for (const auto & p : proxies) { - fprintbf(3, output, "const %sPrxPtr prx%d;\n", boost::algorithm::replace_all_copy(p.first, ".", "::"), - p.second); + for (const auto & proxy : proxies) { + fprintbf(3, output, "const %sPrxPtr prx%d;\n", boost::algorithm::replace_all_copy(proxy.first, ".", "::"), + proxy.second); } } void - RouteCompiler::addSingleOperation(FILE * output, const RoutePtr & r, const Slice::OperationPtr & o) const + RouteCompiler::addSingleOperation(FILE * output, const RoutePtr & route, const Slice::OperationPtr & operation) { - auto operation = r->operation->substr(r->operation->find_last_of('.') + 1); - if (o->returnType()) { - fprintbf(4, output, "auto _responseModel = prx0->%s(", operation); + if (auto operationName = route->operation->substr(route->operation->find_last_of('.') + 1); + operation->returnType()) { + fprintbf(4, output, "auto _responseModel = prx0->%s(", operationName); } else { - fprintbf(4, output, "prx0->%s(", operation); + fprintbf(4, output, "prx0->%s(", operationName); } - for (const auto & p : o->parameters()) { - auto rp = *r->params.find(p->name()); - if (rp.second->hasUserSource) { - fprintbf(output, "_p_%s, ", p->name()); + for (const auto & parameter : operation->parameters()) { + auto routeParam = *route->params.find(parameter->name()); + if (routeParam.second->hasUserSource) { + fprintbf(output, "_p_%s, ", parameter->name()); } else { - fprintbf(output, "_pd_%s, ", p->name()); + fprintbf(output, "_pd_%s, ", parameter->name()); } } fprintbf(output, "request->getContext());\n"); - for (const auto & mutator : r->mutators) { + for (const auto & mutator : route->mutators) { fprintbf(4, output, "%s(request, _responseModel);\n", mutator); } - if (o->returnType()) { + if (operation->returnType()) { fprintbf(4, output, "request->response(this, _responseModel);\n"); } else { @@ -608,49 +629,50 @@ namespace IceSpider::Compile { void RouteCompiler::addMashupOperations( - FILE * output, const RoutePtr & r, const Proxies & proxies, const Units & us) const + FILE * output, const RoutePtr & route, const Proxies & proxies, const Units & units) { - for (const auto & o : r->operations) { - auto proxyName = o.second->operation.substr(0, o.second->operation.find_last_of('.')); - auto operation = o.second->operation.substr(o.second->operation.find_last_of('.') + 1); - fprintbf(4, output, "auto _ar_%s = prx%s->%sAsync(", o.first, proxies.find(proxyName)->second, operation); - auto so = findOperation(o.second->operation, us); - for (const auto & p : so->parameters()) { - auto po = o.second->paramOverrides.find(p->name()); - auto rp = *r->params.find(po != o.second->paramOverrides.end() ? po->second : p->name()); - if (rp.second->hasUserSource) { - fprintbf(output, "_p_%s, ", p->name()); + for (const auto & operation : route->operations) { + auto proxyName = operation.second->operation.substr(0, operation.second->operation.find_last_of('.')); + auto operationName = operation.second->operation.substr(operation.second->operation.find_last_of('.') + 1); + fprintbf(4, output, "auto _ar_%s = prx%s->%sAsync(", operation.first, proxies.find(proxyName)->second, + operationName); + for (const auto & parameter : findOperation(operation.second->operation, units)->parameters()) { + auto parameterOverride = operation.second->paramOverrides.find(parameter->name()); + if (route->params + .find(parameterOverride != operation.second->paramOverrides.end() + ? parameterOverride->second + : parameter->name()) + ->second->hasUserSource) { + fprintbf(output, "_p_%s, ", parameter->name()); } else { - fprintbf(output, "_pd_%s, ", p->name()); + fprintbf(output, "_pd_%s, ", parameter->name()); } } fprintbf(output, "request->getContext());\n"); } - auto t = findType(r->type, us); - fprintbf(4, output, "%s _responseModel", t.type); - if (t.scoped) { - fprintbf(4, output, " = std::make_shared<%s>()", *t.scoped); + const auto type = findType(route->type, units); + fprintbf(4, output, "%s _responseModel", type.type); + if (type.scoped) { + fprintbf(4, output, " = std::make_shared<%s>()", *type.scoped); } fprintbf(4, output, ";\n"); - for (const auto & mi : t.members) { + for (const auto & member : type.members) { bool isOp = false; - fprintbf(4, output, "_responseModel%s%s = ", t.scoped ? "->" : ".", mi->name()); - for (const auto & o : r->operations) { - auto proxyName = o.second->operation.substr(0, o.second->operation.find_last_of('.')); - auto operation = o.second->operation.substr(o.second->operation.find_last_of('.') + 1); - if (mi->name() == o.first) { - fprintbf(output, "_ar_%s.get()", o.first); + fprintbf(4, output, "_responseModel%s%s = ", type.scoped ? "->" : ".", member->name()); + for (const auto & operation : route->operations) { + if (member->name() == operation.first) { + fprintbf(output, "_ar_%s.get()", operation.first); isOp = true; break; } } if (!isOp) { - fprintbf(output, "_p_%s", mi->name()); + fprintbf(output, "_p_%s", member->name()); } fputs(";\n", output); } - for (const auto & mutator : r->mutators) { + for (const auto & mutator : route->mutators) { fprintbf(4, output, "%s(request, _responseModel);\n", mutator); } fprintbf(4, output, "request->response(this, _responseModel);\n"); diff --git a/icespider/compile/routeCompiler.h b/icespider/compile/routeCompiler.h index 99da2ac..cc12bea 100644 --- a/icespider/compile/routeCompiler.h +++ b/icespider/compile/routeCompiler.h @@ -18,10 +18,10 @@ namespace IceSpider::Compile { RouteCompiler(); - [[nodiscard]] RouteConfigurationPtr loadConfiguration(const std::filesystem::path &) const; + [[nodiscard]] static RouteConfigurationPtr loadConfiguration(const std::filesystem::path &); [[nodiscard]] Units loadUnits(const RouteConfigurationPtr &) const; - void applyDefaults(const RouteConfigurationPtr &, const Units & u) const; + static void applyDefaults(const RouteConfigurationPtr &, const Units & units); void compile(const std::filesystem::path & input, const std::filesystem::path & output) const; std::vector<std::filesystem::path> searchPath; @@ -30,17 +30,17 @@ namespace IceSpider::Compile { using Proxies = std::map<std::string, int>; #pragma GCC visibility push(hidden) - void processConfiguration(FILE * output, FILE * outputh, const std::string & name, - const RouteConfigurationPtr &, const Units &) const; - void processBases(FILE * output, FILE * outputh, const RouteConfigurationPtr &, const Units &) const; - void processBase(FILE * output, FILE * outputh, const RouteBases::value_type &, const Units &) const; - void processRoutes(FILE * output, const RouteConfigurationPtr &, const Units &) const; - void processRoute(FILE * output, const Routes::value_type &, const Units &) const; - void registerOutputSerializers(FILE * output, const RoutePtr &) const; - [[nodiscard]] Proxies initializeProxies(FILE * output, const RoutePtr &) const; - void declareProxies(FILE * output, const Proxies &) const; - void addSingleOperation(FILE * output, const RoutePtr &, const Slice::OperationPtr &) const; - void addMashupOperations(FILE * output, const RoutePtr &, const Proxies &, const Units &) const; + static void processConfiguration( + FILE * output, FILE * outputh, const std::string & name, const RouteConfigurationPtr &, const Units &); + static void processBases(FILE * output, FILE * outputh, const RouteConfigurationPtr &, const Units &); + static void processBase(FILE * output, FILE * outputh, const RouteBases::value_type &, const Units &); + static void processRoutes(FILE * output, const RouteConfigurationPtr &, const Units &); + static void processRoute(FILE * output, const Routes::value_type &, const Units &); + static void registerOutputSerializers(FILE * output, const RoutePtr &); + [[nodiscard]] static Proxies initializeProxies(FILE * output, const RoutePtr &); + static void declareProxies(FILE * output, const Proxies &); + static void addSingleOperation(FILE * output, const RoutePtr &, const Slice::OperationPtr &); + static void addMashupOperations(FILE * output, const RoutePtr &, const Proxies &, const Units &); using ParameterMap = std::map<std::string, Slice::ParamDeclPtr>; static ParameterMap findParameters(const RoutePtr &, const Units &); static Slice::OperationPtr findOperation(const std::string &, const Units &); diff --git a/icespider/core/core.cpp b/icespider/core/core.cpp index 4b4d087..09e1aa7 100644 --- a/icespider/core/core.cpp +++ b/icespider/core/core.cpp @@ -5,7 +5,6 @@ #include <Ice/ObjectAdapter.h> #include <Ice/PropertiesF.h> #include <algorithm> -#include <compare> #include <compileTimeFormatter.h> #include <cstdlib> #include <cxxabi.h> @@ -22,33 +21,31 @@ INSTANTIATEFACTORY(IceSpider::Plugin, Ice::CommunicatorPtr, Ice::PropertiesPtr); INSTANTIATEPLUGINOF(IceSpider::ErrorHandler); namespace IceSpider { - const std::filesystem::path Core::defaultConfig("config/ice.properties"); + const std::filesystem::path Core::DEFAULT_CONFIG("config/ice.properties"); Core::Core(const Ice::StringSeq & args) { - Ice::InitializationData id; - id.properties = Ice::createProperties(); - id.properties->parseCommandLineOptions("", args); - auto config = id.properties->getPropertyWithDefault("IceSpider.Config", defaultConfig.string()); + Ice::InitializationData initData; + initData.properties = Ice::createProperties(); + initData.properties->parseCommandLineOptions("", args); + auto config = initData.properties->getPropertyWithDefault("IceSpider.Config", DEFAULT_CONFIG.string()); if (std::filesystem::exists(config)) { - id.properties->load(config); + initData.properties->load(config); } - communicator = Ice::initialize(id); + communicator = Ice::initialize(initData); // Initialize routes - for (const auto & rp : AdHoc::PluginManager::getDefault()->getAll<RouteHandlerFactory>()) { - allRoutes.push_back(rp->implementation()->create(this)); + for (const auto & routeHandleFactory : AdHoc::PluginManager::getDefault()->getAll<RouteHandlerFactory>()) { + allRoutes.push_back(routeHandleFactory->implementation()->create(this)); } - std::sort(allRoutes.begin(), allRoutes.end(), [](const auto & a, const auto & b) { - return a->path < b->path; - }); + std::ranges::sort(allRoutes, {}, &IRouteHandler::path); // Load plugins auto plugins = AdHoc::PluginManager::getDefault()->getAll<PluginFactory>(); if (!plugins.empty()) { pluginAdapter = communicator->createObjectAdapterWithEndpoints("plugins", "default"); - for (const auto & pf : plugins) { - auto p = pf->implementation()->create(communicator, communicator->getProperties()); - pluginAdapter->add(p, Ice::stringToIdentity(pf->name)); + for (const auto & plugin : plugins) { + pluginAdapter->add(plugin->implementation()->create(communicator, communicator->getProperties()), + Ice::stringToIdentity(plugin->name)); } pluginAdapter->activate(); } @@ -59,8 +56,8 @@ namespace IceSpider { // Unload plugins auto plugins = AdHoc::PluginManager::getDefault()->getAll<PluginFactory>(); if (!plugins.empty()) { - for (const auto & pf : plugins) { - pluginAdapter->remove(Ice::stringToIdentity(pf->name)); + for (const auto & plugin : plugins) { + pluginAdapter->remove(Ice::stringToIdentity(plugin->name)); } pluginAdapter->deactivate(); pluginAdapter->destroy(); @@ -85,7 +82,7 @@ namespace IceSpider { handleError(request, e); } catch (...) { - request->response(Http500_InternalServerError::CODE, Http500_InternalServerError::MESSAGE); + request->response(Http500InternalServerError::CODE, Http500InternalServerError::MESSAGE); request->dump(std::cerr); } } @@ -95,14 +92,14 @@ namespace IceSpider { Core::handleError(IHttpRequest * request, const std::exception & exception) const { auto errorHandlers = AdHoc::PluginManager::getDefault()->getAll<ErrorHandler>(); - for (const auto & eh : errorHandlers) { + for (const auto & errorHandler : errorHandlers) { try { - switch (eh->implementation()->handleError(request, exception)) { - case ErrorHandlerResult_Handled: + switch (errorHandler->implementation()->handleError(request, exception)) { + case ErrorHandlerResult::Handled: return; - case ErrorHandlerResult_Unhandled: + case ErrorHandlerResult::Unhandled: continue; - case ErrorHandlerResult_Modified: + case ErrorHandlerResult::Modified: process(request, nullptr); return; } @@ -112,7 +109,7 @@ namespace IceSpider { return; } catch (...) { - std::cerr << "Error handler failed" << std::endl; + std::cerr << "Error handler failed\n"; } } defaultErrorReport(request, exception); @@ -130,11 +127,11 @@ namespace IceSpider { AdHocFormatter(LogExp, "Exception type: %?\nDetail: %?\n"); void - Core::defaultErrorReport(IHttpRequest * request, const std::exception & exception) const + Core::defaultErrorReport(IHttpRequest * request, const std::exception & exception) { auto buf = demangle(typeid(exception).name()); request->setHeader(H::CONTENT_TYPE, MIME::TEXT_PLAIN); - request->response(Http500_InternalServerError::CODE, buf.get()); + request->response(Http500InternalServerError::CODE, buf.get()); LogExp::write(request->getOutputStream(), buf.get(), exception.what()); request->dump(std::cerr); LogExp::write(std::cerr, buf.get(), exception.what()); @@ -148,12 +145,12 @@ namespace IceSpider { CoreWithDefaultRouter::CoreWithDefaultRouter(const Ice::StringSeq & opts) : Core(opts) { - for (const auto & r : allRoutes) { - if (routes.size() <= r->pathElementCount()) { - routes.resize(r->pathElementCount() + 1); + for (const auto & route : allRoutes) { + if (routes.size() <= route->pathElementCount()) { + routes.resize(route->pathElementCount() + 1); } - auto & lroutes = routes[r->pathElementCount()]; - lroutes.push_back(r); + auto & lroutes = routes[route->pathElementCount()]; + lroutes.push_back(route); } } @@ -163,22 +160,22 @@ namespace IceSpider { const auto & pathparts = request->getRequestPath(); const auto method = request->getRequestMethod(); if (pathparts.size() >= routes.size()) { - throw Http404_NotFound(); + throw Http404NotFound(); } const auto & routeSet = routes[pathparts.size()]; bool match = false; - for (const auto & r : routeSet) { - if (r->matches(pathparts)) { - if (r->method == method) { - return r.get(); + for (const auto & route : routeSet) { + if (route->matches(pathparts)) { + if (route->method == method) { + return route.get(); } match = true; } } if (!match) { - throw Http404_NotFound(); + throw Http404NotFound(); } - throw Http405_MethodNotAllowed(); + throw Http405MethodNotAllowed(); } } diff --git a/icespider/core/core.h b/icespider/core/core.h index e4c5d0e..e24ca09 100644 --- a/icespider/core/core.h +++ b/icespider/core/core.h @@ -13,7 +13,6 @@ #include <exception> #include <factory.h> // IWYU pragma: keep #include <filesystem> -#include <memory> #include <plugins.h> // IWYU pragma: keep #include <string_view> #include <vector> @@ -49,10 +48,10 @@ namespace IceSpider { Ice::CommunicatorPtr communicator; Ice::ObjectAdapterPtr pluginAdapter; - static const std::filesystem::path defaultConfig; + static const std::filesystem::path DEFAULT_CONFIG; private: - void defaultErrorReport(IHttpRequest * request, const std::exception & ex) const; + static void defaultErrorReport(IHttpRequest * request, const std::exception & exception); }; class DLL_PUBLIC CoreWithDefaultRouter : public Core { @@ -71,15 +70,15 @@ namespace IceSpider { using PluginFactory = AdHoc::Factory<Plugin, Ice::CommunicatorPtr, Ice::PropertiesPtr>; - enum ErrorHandlerResult { - ErrorHandlerResult_Unhandled, - ErrorHandlerResult_Handled, - ErrorHandlerResult_Modified, + enum class ErrorHandlerResult : uint8_t { + Unhandled, + Handled, + Modified, }; class DLL_PUBLIC ErrorHandler : public AdHoc::AbstractPluginImplementation { public: - virtual ErrorHandlerResult handleError(IHttpRequest * IHttpRequest, const std::exception &) const = 0; + virtual ErrorHandlerResult handleError(IHttpRequest * iHttpRequest, const std::exception &) const = 0; }; using ErrorHandlerPlugin = AdHoc::PluginOf<ErrorHandler>; diff --git a/icespider/core/exceptions.cpp b/icespider/core/exceptions.cpp index b440c2a..19fc92c 100644 --- a/icespider/core/exceptions.cpp +++ b/icespider/core/exceptions.cpp @@ -1,4 +1,5 @@ #include "exceptions.h" +#include "http.h" #define DefineHttpEx(Name, Code, Message) \ Name::Name() : ::IceSpider::HttpException(__FILE__, __LINE__, CODE, MESSAGE) { } \ @@ -6,10 +7,10 @@ const std::string Name::MESSAGE(Message); namespace IceSpider { - DefineHttpEx(Http400_BadRequest, 400, "Bad Request"); - DefineHttpEx(Http404_NotFound, 404, "Not found"); - DefineHttpEx(Http405_MethodNotAllowed, 405, "Method Not Allowed"); - DefineHttpEx(Http406_NotAcceptable, 406, "Not Acceptable"); - DefineHttpEx(Http415_UnsupportedMediaType, 415, "Unsupported Media Type"); - DefineHttpEx(Http500_InternalServerError, 500, "Internal Server Error"); + DefineHttpEx(Http400BadRequest, 400, "Bad Request"); + DefineHttpEx(Http404NotFound, 404, "Not found"); + DefineHttpEx(Http405MethodNotAllowed, 405, "Method Not Allowed"); + DefineHttpEx(Http406NotAcceptable, 406, "Not Acceptable"); + DefineHttpEx(Http415UnsupportedMediaType, 415, "Unsupported Media Type"); + DefineHttpEx(Http500InternalServerError, 500, "Internal Server Error"); } diff --git a/icespider/core/exceptions.h b/icespider/core/exceptions.h index 0de3f70..ae97f5f 100644 --- a/icespider/core/exceptions.h +++ b/icespider/core/exceptions.h @@ -14,12 +14,12 @@ } namespace IceSpider { - DeclareHttpEx(Http400_BadRequest); - DeclareHttpEx(Http404_NotFound); - DeclareHttpEx(Http405_MethodNotAllowed); - DeclareHttpEx(Http406_NotAcceptable); - DeclareHttpEx(Http415_UnsupportedMediaType); - DeclareHttpEx(Http500_InternalServerError); + DeclareHttpEx(Http400BadRequest); + DeclareHttpEx(Http404NotFound); + DeclareHttpEx(Http405MethodNotAllowed); + DeclareHttpEx(Http406NotAcceptable); + DeclareHttpEx(Http415UnsupportedMediaType); + DeclareHttpEx(Http500InternalServerError); } #undef DeclareHttpEx diff --git a/icespider/core/flatMap.cpp b/icespider/core/flatMap.cpp deleted file mode 100644 index b6ad3a6..0000000 --- a/icespider/core/flatMap.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "flatMap.h" diff --git a/icespider/core/flatMap.h b/icespider/core/flatMap.h index a2506d9..4473a4e 100644 --- a/icespider/core/flatMap.h +++ b/icespider/core/flatMap.h @@ -3,14 +3,13 @@ #include <algorithm> #include <cstddef> #include <functional> -#include <iterator> #include <stdexcept> #include <string> #include <utility> #include <vector> namespace IceSpider { - template<typename K, typename M, typename Comp = std::less<>> class flatmap : std::vector<std::pair<K, M>> { + template<typename K, typename M, typename Comp = std::less<>> class FlatMap : std::vector<std::pair<K, M>> { public: using V = std::pair<K, M>; using S = std::vector<V>; @@ -18,37 +17,44 @@ namespace IceSpider { private: template<typename N> struct KeyComp { bool - operator()(const V & v, const N & n) const + operator()(const V & value, const N & name) const { - return c(v.first, n); + return comparator(value.first, name); } bool - operator()(const N & n, const V & v) const + operator()(const N & name, const V & value) const { - return c(n, v.first); + return comparator(name, value.first); } - Comp c; + Comp comparator; }; public: - flatmap() = default; + FlatMap() = default; - explicit flatmap(std::size_t n) + explicit FlatMap(std::size_t n) { reserve(n); } auto - insert(V v) + insert(V value) { - return S::insert(lower_bound(v.first), std::move(v)); + return S::insert(lower_bound(value.first), std::move(value)); + } + + auto + emplace(K key, M mapped) + { + auto pos = lower_bound(key); + return S::emplace(pos, std::move(key), std::move(mapped)); } template<typename N> [[nodiscard]] auto - lower_bound(const N & n) const + lower_bound(const N & n) const // NOLINT(readability-identifier-naming) - STL like { return std::lower_bound(begin(), end(), n, KeyComp<N> {}); } @@ -64,22 +70,22 @@ namespace IceSpider { [[nodiscard]] auto find(const N & n) const { - const auto lb = lower_bound(n); - if (lb == end()) { - return lb; + const auto lower = lower_bound(n); + if (lower == end()) { + return lower; } - if (Comp {}(n, lb->first)) { + if (Comp {}(n, lower->first)) { return end(); } - return lb; + return lower; } template<typename Ex = std::out_of_range, typename N> [[nodiscard]] const auto & at(const N & n) const { - if (const auto i = find(n); i != end()) { - return i->second; + if (const auto iter = find(n); iter != end()) { + return iter->second; } if constexpr (std::is_constructible_v<Ex, N>) { // NOLINTNEXTLINE(hicpp-no-array-decay) @@ -107,7 +113,7 @@ namespace IceSpider { using S::empty; using S::reserve; using S::size; - using iterator = typename S::iterator; - using const_iterator = typename S::const_iterator; + using iterator = typename S::iterator; // NOLINT(readability-identifier-naming) - STL like + using const_iterator = typename S::const_iterator; // NOLINT(readability-identifier-naming) - STL like }; } diff --git a/icespider/core/ihttpRequest.cpp b/icespider/core/ihttpRequest.cpp index 205fa6e..75db2f1 100644 --- a/icespider/core/ihttpRequest.cpp +++ b/icespider/core/ihttpRequest.cpp @@ -9,7 +9,6 @@ #include <ctime> #include <formatters.h> #include <http.h> -#include <memory> #include <plugins.h> #include <slicer/modelParts.h> #include <slicer/serializer.h> @@ -18,10 +17,10 @@ namespace IceSpider { using namespace AdHoc::literals; - IHttpRequest::IHttpRequest(const Core * c) : core(c) { } + IHttpRequest::IHttpRequest(const Core * core) : core(core) { } Ice::Context - IHttpRequest::getContext() const + IHttpRequest::getContext() { return {}; } @@ -32,12 +31,12 @@ namespace IceSpider { try { return Slicer::StreamDeserializerFactory::createNew( getEnvStr(E::CONTENT_TYPE) / []() -> std::string_view { - throw Http400_BadRequest(); + throw Http400BadRequest(); }, getInputStream()); } catch (const AdHoc::NoSuchPluginException &) { - throw Http415_UnsupportedMediaType(); + throw Http415UnsupportedMediaType(); } } @@ -46,89 +45,82 @@ namespace IceSpider { { remove_leading(acceptHdr, ' '); if (acceptHdr.empty()) { - throw Http400_BadRequest(); + throw Http400BadRequest(); } Accepted accepts; accepts.reserve(static_cast<std::size_t>(std::count(acceptHdr.begin(), acceptHdr.end(), ',') + 1)); - auto upto = [](std::string_view & in, const std::string_view term, bool req) { - remove_leading(in, ' '); - const auto end = in.find_first_of(term); + auto upto = [](std::string_view & input, const std::string_view term, bool req) { + remove_leading(input, ' '); + const auto end = input.find_first_of(term); if (req && end == std::string_view::npos) { - throw Http400_BadRequest(); + throw Http400BadRequest(); } - auto val = in.substr(0, end); + auto val = input.substr(0, end); remove_trailing(val, ' '); if (val.empty()) { - throw Http400_BadRequest(); + throw Http400BadRequest(); } if (end != std::string_view::npos) { - const auto tc = in[end]; - in.remove_prefix(end + 1); - return std::make_pair(val, tc); - } - else { - in.remove_prefix(in.length()); - return std::make_pair(val, '\n'); + const auto terminatorChar = input[end]; + input.remove_prefix(end + 1); + return std::make_pair(val, terminatorChar); } + input.remove_prefix(input.length()); + return std::make_pair(val, '\n'); }; while (!acceptHdr.empty()) { const auto group = upto(acceptHdr, "/", true).first; - auto [type, tc] = upto(acceptHdr, ";,", false); - Accept a; + auto [type, terminatorChar] = upto(acceptHdr, ";,", false); + Accept accept; if (type != "*") { - a.type.emplace(type); + accept.type.emplace(type); } if (group != "*") { - a.group.emplace(group); + accept.group.emplace(group); } - else if (a.type) { - throw Http400_BadRequest(); + else if (accept.type) { + throw Http400BadRequest(); } - while (tc == ';') { + while (terminatorChar == ';') { const auto paramName = upto(acceptHdr, "=", true); const auto paramValue = upto(acceptHdr, ",;", false); if (paramName.first == "q") { - if (convert(paramValue.first, a.q); a.q <= 0.0F || a.q > 1.0F) { - throw Http400_BadRequest(); + if (convert(paramValue.first, accept.q); accept.q <= 0.0F || accept.q > 1.0F) { + throw Http400BadRequest(); } } - tc = paramValue.second; + terminatorChar = paramValue.second; } - accepts.emplace_back(a); + accepts.emplace_back(accept); } - std::stable_sort(accepts.begin(), accepts.end(), [](const auto & a, const auto & b) { - return a.q > b.q; - }); + std::ranges::stable_sort(accepts, std::greater<float> {}, &Accept::q); return accepts; } ContentTypeSerializer IHttpRequest::getSerializer(const IRouteHandler * handler) const { - auto acceptHdr = getHeaderParamStr(H::ACCEPT); - if (acceptHdr) { + if (auto acceptHdr = getHeaderParamStr(H::ACCEPT)) { auto accepts = parseAccept(*acceptHdr); auto & strm = getOutputStream(); if (accepts.empty()) { - throw Http400_BadRequest(); + throw Http400BadRequest(); } if (!accepts.front().group && !accepts.front().type) { return handler->defaultSerializer(strm); } - for (auto & a : accepts) { - ContentTypeSerializer serializer = handler->getSerializer(a, strm); + for (const auto & accept : accepts) { + ContentTypeSerializer serializer = handler->getSerializer(accept, strm); if (serializer.second) { return serializer; } } - throw Http406_NotAcceptable(); - } - else { - return handler->defaultSerializer(getOutputStream()); + throw Http406NotAcceptable(); } + return handler->defaultSerializer(getOutputStream()); } std::string_view @@ -143,33 +135,35 @@ namespace IceSpider { // Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure] void - IHttpRequest::setCookie(const std::string_view name, const std::string_view value, const OptionalString & d, - const OptionalString & p, bool s, std::optional<time_t> e) + IHttpRequest::setCookie(const std::string_view name, const std::string_view value, const OptionalString & domain, + const OptionalString & path, bool secure, std::optional<time_t> expiry) const { - std::stringstream o; - XWwwFormUrlEncoded::urlencodeto(o, name.begin(), name.end()); - o << '='; - XWwwFormUrlEncoded::urlencodeto(o, value.begin(), value.end()); - if (e) { - static constexpr auto dateLength = std::string_view {"Sat, 02 May 2009 23:38:25 GMT"}.length() + 1; - std::array<char, dateLength> buf {}; - tm tm {}; + std::stringstream cookieString; + XWwwFormUrlEncoded::urlencodeto(cookieString, name.begin(), name.end()); + cookieString << '='; + XWwwFormUrlEncoded::urlencodeto(cookieString, value.begin(), value.end()); + if (expiry) { + static constexpr auto DATE_LENGTH = sizeof("Sat, 02 May 2009 23:38:25 GMT"); + tm timeParts {}; - gmtime_r(&*e, &tm); - const auto len = strftime(buf.data(), buf.size(), "%a, %d %b %Y %T %Z", &tm); - o << "; expires=" << std::string_view {buf.data(), len}; + gmtime_r(&*expiry, &timeParts); + std::string buf; + buf.resize_and_overwrite(DATE_LENGTH, [&timeParts](char * out, size_t len) { + return strftime(out, len, "%a, %d %b %Y %T %Z", &timeParts); + }); + cookieString << "; expires=" << buf; } - if (d) { - "; domain=%?"_fmt(o, *d); + if (domain) { + "; domain=%?"_fmt(cookieString, *domain); } - if (p) { - "; path=%?"_fmt(o, *p); + if (path) { + "; path=%?"_fmt(cookieString, *path); } - if (s) { - "; secure"_fmt(o); + if (secure) { + "; secure"_fmt(cookieString); } - "; samesite=strict"_fmt(o); - setHeader(H::SET_COOKIE, o.str()); + "; samesite=strict"_fmt(cookieString); + setHeader(H::SET_COOKIE, std::move(cookieString).str()); } void @@ -180,15 +174,15 @@ namespace IceSpider { } void - IHttpRequest::modelPartResponse(const IRouteHandler * route, const Slicer::ModelPartForRootParam mp) const + IHttpRequest::modelPartResponse(const IRouteHandler * route, const Slicer::ModelPartForRootParam modelPart) const { - auto s = getSerializer(route); - setHeader(H::CONTENT_TYPE, MimeTypeFmt::get(s.first.group, s.first.type)); + const auto serializer = getSerializer(route); + setHeader(H::CONTENT_TYPE, MimeTypeFmt::get(serializer.first.group, serializer.first.type)); response(200, S::OK); - s.second->Serialize(mp); + serializer.second->Serialize(modelPart); } - static_assert(std::is_convertible<OptionalString::value_type, std::string_view>::value); - static_assert(!std::is_convertible<OptionalString::value_type, std::string>::value); - static_assert(std::is_constructible<OptionalString::value_type, std::string>::value); + static_assert(std::is_convertible_v<OptionalString::value_type, std::string_view>); + static_assert(!std::is_convertible_v<OptionalString::value_type, std::string>); + static_assert(std::is_constructible_v<OptionalString::value_type, std::string>); } diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 9d95069..79bf6aa 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -1,11 +1,9 @@ #pragma once -#include "exceptions.h" #include "util.h" #include <Ice/Current.h> #include <boost/lexical_cast.hpp> #include <c++11Helpers.h> -#include <charconv> #include <ctime> #include <http.h> #include <iosfwd> @@ -41,36 +39,34 @@ namespace IceSpider { virtual ~IHttpRequest() = default; SPECIAL_MEMBERS_DEFAULT_MOVE_NO_COPY(IHttpRequest); - [[nodiscard]] Ice::Context getContext() const; + [[nodiscard]] static Ice::Context getContext(); [[nodiscard]] virtual const PathElements & getRequestPath() const = 0; [[nodiscard]] virtual PathElements & getRequestPath() = 0; [[nodiscard]] virtual HttpMethod getRequestMethod() const = 0; - [[nodiscard]] std::string_view getURLParamStr(const unsigned int) const; - [[nodiscard]] virtual OptionalString getQueryStringParamStr(const std::string_view) const = 0; - [[nodiscard]] virtual OptionalString getHeaderParamStr(const std::string_view) const = 0; - [[nodiscard]] virtual OptionalString getCookieParamStr(const std::string_view) const = 0; - [[nodiscard]] virtual OptionalString getEnvStr(const std::string_view) const = 0; + [[nodiscard]] std::string_view getURLParamStr(unsigned int) const; + [[nodiscard]] virtual OptionalString getQueryStringParamStr(std::string_view) const = 0; + [[nodiscard]] virtual OptionalString getHeaderParamStr(std::string_view) const = 0; + [[nodiscard]] virtual OptionalString getCookieParamStr(std::string_view) const = 0; + [[nodiscard]] virtual OptionalString getEnvStr(std::string_view) const = 0; [[nodiscard]] virtual bool isSecure() const = 0; [[nodiscard]] static Accepted parseAccept(std::string_view); [[nodiscard]] virtual Slicer::DeserializerPtr getDeserializer() const; [[nodiscard]] virtual ContentTypeSerializer getSerializer(const IRouteHandler *) const; [[nodiscard]] virtual std::istream & getInputStream() const = 0; [[nodiscard]] virtual std::ostream & getOutputStream() const = 0; - virtual void setHeader(const std::string_view, const std::string_view) const = 0; + virtual void setHeader(std::string_view, std::string_view) const = 0; - virtual std::ostream & dump(std::ostream & s) const = 0; + virtual std::ostream & dump(std::ostream & strm) const = 0; template<typename T, typename K> - [[nodiscard]] inline std::optional<T> + [[nodiscard]] std::optional<T> getFrom(const K key, OptionalString (IHttpRequest::*src)(const K) const) const { - if (auto v = (this->*src)(key)) { - return convert<T>(*v); - } - else { - return std::nullopt; + if (auto value = (this->*src)(key)) { + return convert<T>(*value); } + return std::nullopt; } template<typename T> @@ -95,29 +91,30 @@ namespace IceSpider { return {}; } - if (const auto i = map->find(key); i != map->end()) { - return convert<T>(i->second); + if (const auto iter = map->find(key); iter != map->end()) { + return convert<T>(iter->second); } return {}; } - void responseRedirect(const std::string_view url, const OptionalString & = {}) const; - void setCookie(const std::string_view, const std::string_view, const OptionalString & = {}, - const OptionalString & = {}, bool = false, std::optional<time_t> = {}); + void responseRedirect(std::string_view url, const OptionalString & = {}) const; + void setCookie(std::string_view, std::string_view, const OptionalString & = {}, const OptionalString & = {}, + bool = false, std::optional<time_t> = {}) const; template<typename T> + requires(!std::same_as<T, std::string_view>) void - setCookie(const std::string_view n, const T & v, const OptionalString & d, const OptionalString & p, bool s, - std::optional<time_t> e) + setCookie(const std::string_view n, const T & value, const OptionalString & domain, const OptionalString & path, + bool secure, std::optional<time_t> expiry) { if constexpr (std::is_constructible_v<std::string_view, T>) { - setCookie(n, std::string_view(v), d, p, s, e); + setCookie(n, std::string_view(value), domain, path, secure, expiry); } - else if constexpr (requires { std::to_string(v); }) { - setCookie(n, std::to_string(v), d, p, s, e); + else if constexpr (requires { std::to_string(value); }) { + setCookie(n, std::to_string(value), domain, path, secure, expiry); } else { - setCookie(n, boost::lexical_cast<std::string>(v), d, p, s, e); + setCookie(n, boost::lexical_cast<std::string>(value), domain, path, secure, expiry); } } @@ -142,18 +139,18 @@ namespace IceSpider { return getFrom<T, std::string_view>(key, &IHttpRequest::getCookieParamStr); } - virtual void response(short, const std::string_view) const = 0; + virtual void response(short, std::string_view) const = 0; template<typename T> void - response(const IRouteHandler * route, const T & t) const + response(const IRouteHandler * route, const T & value) const { - Slicer::ModelPart::OnRootFor(t, [this, route](Slicer::ModelPartForRootParam root) { + Slicer::ModelPart::OnRootFor(value, [this, route](Slicer::ModelPartForRootParam root) { modelPartResponse(route, root); }); } - void modelPartResponse(const IRouteHandler * route, const Slicer::ModelPartForRootParam) const; + void modelPartResponse(const IRouteHandler * route, Slicer::ModelPartForRootParam) const; const Core * core; }; diff --git a/icespider/core/irouteHandler.cpp b/icespider/core/irouteHandler.cpp index cb2f216..3f7617c 100644 --- a/icespider/core/irouteHandler.cpp +++ b/icespider/core/irouteHandler.cpp @@ -5,8 +5,6 @@ #include <formatters.h> #include <optional> #include <pathparts.h> -#include <set> -#include <sstream> #include <string> #include <utility> @@ -17,29 +15,34 @@ namespace IceSpider { static const std::string JSON = "json"; static const std::string APPLICATION_JSON = MimeTypeFmt::get(APPLICATION, JSON); - const RouteOptions IRouteHandler::defaultRouteOptions {}; + const RouteOptions IRouteHandler::DEFAULT_ROUTE_OPTIONS {}; - IRouteHandler::IRouteHandler(HttpMethod m, const std::string_view p) : - IRouteHandler(m, p, defaultRouteOptions) { } + IRouteHandler::IRouteHandler(HttpMethod method, const std::string_view path) : + IRouteHandler(method, path, DEFAULT_ROUTE_OPTIONS) + { + } - IRouteHandler::IRouteHandler(HttpMethod m, const std::string_view p, const RouteOptions & ro) : Path(p), method(m) + IRouteHandler::IRouteHandler(HttpMethod method, const std::string_view path, const RouteOptions & routeOpts) : + Path(path), method(method) { - if (ro.addDefaultSerializers) { + if (routeOpts.addDefaultSerializers) { auto globalSerializers = AdHoc::PluginManager::getDefault()->getAll<Slicer::StreamSerializerFactory>(); - for (const auto & gs : globalSerializers) { - auto slash = gs->name.find('/'); + for (const auto & serializer : globalSerializers) { + auto slash = serializer->name.find('/'); routeSerializers.insert( - {{gs->name.substr(0, slash), gs->name.substr(slash + 1)}, gs->implementation()}); + {{.group = serializer->name.substr(0, slash), .type = serializer->name.substr(slash + 1)}, + serializer->implementation()}); } } } ContentTypeSerializer - IRouteHandler::getSerializer(const Accept & a, std::ostream & strm) const + IRouteHandler::getSerializer(const Accept & accept, std::ostream & strm) const { - for (const auto & rs : routeSerializers) { - if ((!a.group || rs.first.group == a.group) && (!a.type || rs.first.type == a.type)) { - return {rs.first, rs.second->create(strm)}; + for (const auto & serializer : routeSerializers) { + if ((!accept.group || serializer.first.group == accept.group) + && (!accept.type || serializer.first.type == accept.type)) { + return {serializer.first, serializer.second->create(strm)}; } } return {}; @@ -48,19 +51,20 @@ namespace IceSpider { ContentTypeSerializer IRouteHandler::defaultSerializer(std::ostream & strm) const { - return {{APPLICATION, JSON}, Slicer::StreamSerializerFactory::createNew(APPLICATION_JSON, strm)}; + return {{.group = APPLICATION, .type = JSON}, + Slicer::StreamSerializerFactory::createNew(APPLICATION_JSON, strm)}; } void - IRouteHandler::requiredParameterNotFound(const char *, const std::string_view) const + IRouteHandler::requiredParameterNotFound(const char *, const std::string_view) { - throw Http400_BadRequest(); + throw Http400BadRequest(); } void - IRouteHandler::addRouteSerializer(const MimeType & ct, const StreamSerializerFactoryPtr & ssfp) + IRouteHandler::addRouteSerializer(const MimeType & contentType, const StreamSerializerFactoryPtr & ssfp) { - routeSerializers.erase(ct); - routeSerializers.insert({ct, ssfp}); + routeSerializers.erase(contentType); + routeSerializers.emplace(contentType, ssfp); } } diff --git a/icespider/core/irouteHandler.h b/icespider/core/irouteHandler.h index adea779..cd34053 100644 --- a/icespider/core/irouteHandler.h +++ b/icespider/core/irouteHandler.h @@ -22,10 +22,10 @@ namespace IceSpider { class DLL_PUBLIC IRouteHandler : public Path { public: - const static RouteOptions defaultRouteOptions; + const static RouteOptions DEFAULT_ROUTE_OPTIONS; - IRouteHandler(HttpMethod, const std::string_view path); - IRouteHandler(HttpMethod, const std::string_view path, const RouteOptions &); + IRouteHandler(HttpMethod, std::string_view path); + IRouteHandler(HttpMethod, std::string_view path, const RouteOptions &); SPECIAL_MEMBERS_MOVE_RO(IRouteHandler); virtual ~IRouteHandler() = default; @@ -40,13 +40,13 @@ namespace IceSpider { using RouteSerializers = std::map<MimeType, StreamSerializerFactoryPtr>; RouteSerializers routeSerializers; - [[noreturn]] void requiredParameterNotFound(const char *, const std::string_view key) const; + [[noreturn]] static void requiredParameterNotFound(const char *, std::string_view key); template<typename T, typename K> - inline T - requiredParameterNotFound(const char * s, const K & key) const + static T + requiredParameterNotFound(const char * source, const K & key) { - requiredParameterNotFound(s, key); + requiredParameterNotFound(source, key); } void addRouteSerializer(const MimeType &, const StreamSerializerFactoryPtr &); diff --git a/icespider/core/util-test.cpp b/icespider/core/util-test.cpp index df79fb2..8966804 100644 --- a/icespider/core/util-test.cpp +++ b/icespider/core/util-test.cpp @@ -5,9 +5,9 @@ namespace foo ::bar { class really; } -static_assert(type_names<int>::name() == "int"); -static_assert(type_names<int>::namespaces() == 0); +static_assert(TypeNames<int>::name() == "int"); +static_assert(TypeNames<int>::namespaces() == 0); static_assert(TypeName<int>::str() == "int"); -static_assert(type_names<foo::bar::really>::name() == "foo::bar::really"); -static_assert(type_names<foo::bar::really>::namespaces() == 2); +static_assert(TypeNames<foo::bar::really>::name() == "foo::bar::really"); +static_assert(TypeNames<foo::bar::really>::namespaces() == 2); static_assert(TypeName<foo::bar::really>::str() == "foo.bar.really"); diff --git a/icespider/core/util.cpp b/icespider/core/util.cpp index 5e51b8b..f808d6b 100644 --- a/icespider/core/util.cpp +++ b/icespider/core/util.cpp @@ -3,8 +3,8 @@ namespace IceSpider { void - conversion_failure() + conversionFailure() { - throw Http400_BadRequest(); + throw Http400BadRequest(); } } diff --git a/icespider/core/util.h b/icespider/core/util.h index cbbd318..ae7316c 100644 --- a/icespider/core/util.h +++ b/icespider/core/util.h @@ -12,48 +12,48 @@ namespace std::experimental::Ice { template<typename T, typename TF> inline const T & - operator/(const Ice::optional<T> & o, const TF & tf) + operator/(const Ice::optional<T> & value, const TF & whenNullOpt) { - if (o) { - return *o; + if (value) { + return *value; } - return tf(); + return whenNullOpt(); } template<typename T, typename TF> inline T - operator/(Ice::optional<T> && o, const TF & tf) + operator/(Ice::optional<T> && value, const TF & whenNullOpt) { - if (o) { - return std::move(*o); + if (value) { + return *std::move(value); } - return tf(); + return whenNullOpt(); } } namespace std { template<typename T, typename TF> inline const T & - operator/(const std::optional<T> & o, const TF & tf) + operator/(const std::optional<T> & value, const TF & whenNullOpt) { - if (o) { - return *o; + if (value) { + return *value; } - return tf(); + return whenNullOpt(); } template<typename T, typename TF> inline T - operator/(std::optional<T> && o, const TF & tf) + operator/(std::optional<T> && value, const TF & whenNullOpt) { - if (o) { - return std::move(*o); + if (value) { + return *std::move(value); } - return tf(); + return whenNullOpt(); } } -template<typename T> struct type_names { +template<typename T> struct TypeNames { static constexpr auto pf() { @@ -63,46 +63,46 @@ template<typename T> struct type_names { static constexpr auto name() { - constexpr std::string_view with_T {"T = "}; - constexpr auto start {pf().find(with_T) + with_T.length()}; - constexpr auto end {pf().find(']', start)}; - constexpr auto name {pf().substr(start, end - start)}; - static_assert(name.find('<') == std::string_view::npos, "Templates not supported"); - return name; + constexpr std::string_view WITH_T {"T = "}; + constexpr auto START {pf().find(WITH_T) + WITH_T.length()}; + constexpr auto END {pf().find(']', START)}; + constexpr auto NAME {pf().substr(START, END - START)}; + static_assert(NAME.find('<') == std::string_view::npos, "Templates not supported"); + return NAME; } static constexpr auto namespaces() { - return std::count(name().begin(), name().end(), ':') / 2; + return std::ranges::count(name(), ':') / 2; } - using char_type = typename decltype(name())::value_type; + using CharType = typename decltype(name())::value_type; }; -template<typename T> class TypeName : type_names<T> { +template<typename T> class TypeName : TypeNames<T> { public: - constexpr static inline auto + constexpr static auto str() { - return std::string_view {buf.data(), buf.size() - 1}; + return std::string_view {BUF.data(), BUF.size() - 1}; } - constexpr static inline auto - c_str() + constexpr static auto + c_str() // NOLINT(readability-identifier-naming) - STL like { - return buf.data(); + return BUF.data(); } private: - using tn = type_names<T>; + using Tn = TypeNames<T>; - constexpr static auto buf {[]() { - std::array<typename tn::char_type, tn::name().length() - tn::namespaces() + 1> buf {}; + constexpr static auto BUF {[]() { + std::array<typename Tn::CharType, Tn::name().length() - Tn::namespaces() + 1> buf {}; auto out {buf.begin()}; auto cln = false; - for (const auto & in : tn::name()) { - if (in == ':') { + for (const auto & input : Tn::name()) { + if (input == ':') { if (cln) { *out++ = '.'; } @@ -111,7 +111,7 @@ private: } } else { - *out++ = in; + *out++ = input; cln = false; } } @@ -120,7 +120,7 @@ private: }; namespace IceSpider { - [[noreturn]] DLL_PUBLIC void conversion_failure(); + [[noreturn]] DLL_PUBLIC void conversionFailure(); static_assert(std::is_assignable_v<std::string, std::string_view>); static_assert(std::is_assignable_v<std::string_view, std::string_view>); @@ -128,20 +128,20 @@ namespace IceSpider { namespace { template<typename T> inline T - from_chars(const std::string_view v, T && out) + from_chars(const std::string_view chars, T && out) // NOLINT(readability-identifier-naming) - STL like { - if (std::from_chars(v.begin(), v.end(), out).ec != std::errc {}) { - conversion_failure(); + if (std::from_chars(chars.begin(), chars.end(), std::forward<T>(out)).ec != std::errc {}) { + conversionFailure(); } return out; } template<typename T> inline T - lexical_cast(const std::string_view v, T && out) + lexical_cast(const std::string_view value, T && out) // NOLINT(readability-identifier-naming) - Boost like { - if (!boost::conversion::try_lexical_convert(v, out)) { - conversion_failure(); + if (!boost::conversion::try_lexical_convert(value, std::forward<T>(out))) { + conversionFailure(); } return out; } @@ -149,32 +149,40 @@ namespace IceSpider { template<typename T> inline T - convert(const std::string_view v, T && out = {}) + convert(const std::string_view value, T && out) { if constexpr (std::is_assignable_v<T, std::string_view>) { - return (out = v); + return (out = value); } - else if constexpr (requires { std::from_chars(v.begin(), v.end(), out); }) { - return from_chars(v, out); + else if constexpr (requires { std::from_chars(value.begin(), value.end(), out); }) { + return from_chars(value, std::forward<T>(out)); } else { - return lexical_cast(v, out); + return lexical_cast(value, std::forward<T>(out)); } } + template<typename T> + inline T + convert(const std::string_view value) + { + T tmp; + return convert(value, tmp); + } + inline void - remove_trailing(std::string_view & in, const char c) + remove_trailing(std::string_view & input, const char chr) // NOLINT(readability-identifier-naming) - STL like { - if (const auto n = in.find_last_not_of(c); n != std::string_view::npos) { - in.remove_suffix(in.length() - n - 1); + if (const auto pos = input.find_last_not_of(chr); pos != std::string_view::npos) { + input.remove_suffix(input.length() - pos - 1); } } inline void - remove_leading(std::string_view & in, const char c) + remove_leading(std::string_view & input, const char chr) // NOLINT(readability-identifier-naming) - STL like { - if (const auto n = in.find_first_not_of(c); n != std::string_view::npos) { - in.remove_prefix(n); + if (const auto pos = input.find_first_not_of(chr); pos != std::string_view::npos) { + input.remove_prefix(pos); } } } diff --git a/icespider/core/xwwwFormUrlEncoded.cpp b/icespider/core/xwwwFormUrlEncoded.cpp index 3cb0ece..40b42c6 100644 --- a/icespider/core/xwwwFormUrlEncoded.cpp +++ b/icespider/core/xwwwFormUrlEncoded.cpp @@ -13,7 +13,6 @@ #include <iterator> #include <limits> #include <maybeString.h> -#include <memory> #include <optional> #include <slicer/modelParts.h> #include <slicer/serializer.h> @@ -22,100 +21,124 @@ namespace ba = boost::algorithm; using namespace std::literals; -constexpr auto CHARMAX = std::numeric_limits<unsigned char>::max(); +namespace { + constexpr auto CHARMAX = std::numeric_limits<unsigned char>::max(); -using HexPair = std::pair<char, char>; -using HexOut = std::array<HexPair, CHARMAX>; -constexpr auto hexout = []() { - auto hexchar = [](auto c) { - return static_cast<char>(c < 10 ? '0' + c : 'a' - 10 + c); - }; - HexOut out {}; - for (unsigned int n = 0; n < CHARMAX; n++) { - switch (n) { - case ' ': - out[n].first = '+'; - break; - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case '-': - case '.': - case '_': - case '~': - // No special encoding - break; - default: - out[n].first = hexchar(n >> 4U); - out[n].second = hexchar(n & 0xfU); - break; + // NOLINTBEGIN(readability-magic-numbers) + using HexPair = std::pair<char, char>; + using HexOut = std::array<HexPair, CHARMAX>; + constexpr auto HEXOUT = []() { + auto hexchar = [](auto chr) { + return static_cast<char>(chr < 10 ? '0' + chr : 'a' - 10 + chr); + }; + HexOut out {}; + for (unsigned int chr = 0; chr < CHARMAX; chr++) { + switch (chr) { + case ' ': + out[chr].first = '+'; + break; + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': + case '-': + case '.': + case '_': + case '~': + // No special encoding + break; + default: + out[chr].first = hexchar(chr >> 4U); + out[chr].second = hexchar(chr & 0xfU); + break; + } } - } - return out; -}(); + return out; + }(); -static_assert(hexout['a'].first == 0); -static_assert(hexout['a'].second == 0); -static_assert(hexout['z'].first == 0); -static_assert(hexout['z'].second == 0); -static_assert(hexout['A'].first == 0); -static_assert(hexout['A'].second == 0); -static_assert(hexout['Z'].first == 0); -static_assert(hexout['Z'].second == 0); -static_assert(hexout['0'].first == 0); -static_assert(hexout['9'].second == 0); -static_assert(hexout['~'].first == 0); -static_assert(hexout['~'].second == 0); -static_assert(hexout[' '].first == '+'); -static_assert(hexout[' '].second == 0); -static_assert(hexout['?'].first == '3'); -static_assert(hexout['?'].second == 'f'); + static_assert(HEXOUT['a'].first == 0); + static_assert(HEXOUT['a'].second == 0); + static_assert(HEXOUT['z'].first == 0); + static_assert(HEXOUT['z'].second == 0); + static_assert(HEXOUT['A'].first == 0); + static_assert(HEXOUT['A'].second == 0); + static_assert(HEXOUT['Z'].first == 0); + static_assert(HEXOUT['Z'].second == 0); + static_assert(HEXOUT['0'].first == 0); + static_assert(HEXOUT['9'].second == 0); + static_assert(HEXOUT['~'].first == 0); + static_assert(HEXOUT['~'].second == 0); + static_assert(HEXOUT[' '].first == '+'); + static_assert(HEXOUT[' '].second == 0); + static_assert(HEXOUT['?'].first == '3'); + static_assert(HEXOUT['?'].second == 'f'); -constexpr std::array<std::optional<unsigned char>, CHARMAX> hextable = []() { - std::array<std::optional<unsigned char>, CHARMAX> hextable {}; - for (size_t n = '0'; n <= '9'; n++) { - hextable[n] = {n - '0'}; - } - for (size_t n = 'a'; n <= 'f'; n++) { - hextable[n] = hextable[n - 32] = {n - 'a' + 10}; - } - return hextable; -}(); + constexpr std::array<std::optional<unsigned char>, CHARMAX> HEXTABLE = []() { + std::array<std::optional<unsigned char>, CHARMAX> hextable {}; + for (size_t chr = '0'; chr <= '9'; chr++) { + hextable[chr] = {chr - '0'}; + } + for (size_t chr = 'a'; chr <= 'f'; chr++) { + hextable[chr] = hextable[chr - 32] = {chr - 'a' + 10}; + } + return hextable; + }(); -static_assert(!hextable['~'].has_value()); -static_assert(!hextable[' '].has_value()); -static_assert(hextable['0'] == 0); -static_assert(hextable['9'] == 9); -static_assert(hextable['a'] == 10); -static_assert(hextable['A'] == 10); -static_assert(hextable['f'] == 15); -static_assert(hextable['F'] == 15); -static_assert(!hextable['g'].has_value()); -static_assert(!hextable['G'].has_value()); + static_assert(!HEXTABLE['~'].has_value()); + static_assert(!HEXTABLE[' '].has_value()); + static_assert(HEXTABLE['0'] == 0); + static_assert(HEXTABLE['9'] == 9); + static_assert(HEXTABLE['a'] == 10); + static_assert(HEXTABLE['A'] == 10); + static_assert(HEXTABLE['f'] == 15); + static_assert(HEXTABLE['F'] == 15); + static_assert(!HEXTABLE['g'].has_value()); + static_assert(!HEXTABLE['G'].has_value()); + // NOLINTEND(readability-magic-numbers) -using HexIn = std::array<std::array<char, CHARMAX>, CHARMAX>; -constexpr HexIn hexin = []() { - HexIn hexin {}; - size_t firstHex = std::min({'0', 'a', 'A'}); - size_t lastHex = std::max({'9', 'f', 'F'}); - for (auto first = firstHex; first <= lastHex; first++) { - if (const auto & ch1 = hextable[first]) { - for (auto second = firstHex; second <= lastHex; second++) { - if (const auto & ch2 = hextable[second]) { - hexin[first][second] = static_cast<char>((*ch1 << 4U) + *ch2); + using HexIn = std::array<std::array<char, CHARMAX>, CHARMAX>; + constexpr HexIn HEXIN = []() { + HexIn hexin {}; + size_t firstHex = std::min({'0', 'a', 'A'}); + size_t lastHex = std::max({'9', 'f', 'F'}); + for (auto first = firstHex; first <= lastHex; first++) { + if (const auto & ch1 = HEXTABLE[first]) { + for (auto second = firstHex; second <= lastHex; second++) { + if (const auto & ch2 = HEXTABLE[second]) { + hexin[first][second] = static_cast<char>((*ch1 << 4U) + *ch2); + } } } } - } - hexin['+'][0] = ' '; - return hexin; -}(); + hexin['+'][0] = ' '; + return hexin; + }(); -static_assert(hexin[' '][' '] == 0); -static_assert(hexin['0']['a'] == '\n'); -static_assert(hexin['+'][0] == ' '); -static_assert(hexin['3']['f'] == '?'); -static_assert(hexin['3']['F'] == '?'); + static_assert(HEXIN[' '][' '] == 0); + static_assert(HEXIN['0']['a'] == '\n'); + static_assert(HEXIN['+'][0] == ' '); + static_assert(HEXIN['3']['f'] == '?'); + static_assert(HEXIN['3']['F'] == '?'); + + constexpr auto + urlEncodeRange(auto && outIter, auto input, auto end) + { + while (input != end) { + const auto & out = HEXOUT[static_cast<uint8_t>(*input)]; + if (out.second) { + outIter = '%'; + outIter = out.first; + outIter = out.second; + } + else if (out.first) { + outIter = (out.first); + } + else { + outIter = (*input); + } + ++input; + } + } +} namespace IceSpider { static constexpr const std::string_view AMP = "&"; @@ -125,63 +148,63 @@ namespace IceSpider { static constexpr const std::string_view VALUE = "value"; static constexpr const std::string_view URL_ESCAPES = "%+"; - XWwwFormUrlEncoded::XWwwFormUrlEncoded(std::istream & in) : - input(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>()) + XWwwFormUrlEncoded::XWwwFormUrlEncoded(std::istream & input) : + input(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()) { } void - XWwwFormUrlEncoded::Deserialize(Slicer::ModelPartForRootParam mp) + XWwwFormUrlEncoded::Deserialize(Slicer::ModelPartForRootParam modelPart) { - mp->Create(); - mp->OnEachChild([this](auto, auto mp, auto) { - switch (mp->GetType()) { + modelPart->Create(); + modelPart->OnEachChild([this](const auto &, auto child, auto) { + switch (child->GetType()) { case Slicer::ModelPartType::Simple: - this->DeserializeSimple(mp); + this->deserializeSimple(child); break; case Slicer::ModelPartType::Complex: - this->DeserializeComplex(mp); + this->deserializeComplex(child); break; case Slicer::ModelPartType::Dictionary: - this->DeserializeDictionary(mp); + this->deserializeDictionary(child); break; default: - throw IceSpider::Http400_BadRequest(); + throw IceSpider::Http400BadRequest(); break; } }); - mp->Complete(); + modelPart->Complete(); } class SetFromString : public Slicer::ValueSource { public: - explicit SetFromString(const MaybeString & v) : s(v) { } + explicit SetFromString(const MaybeString & value) : s(value) { } void - set(bool & t) const override + set(bool & target) const override { if (s == TRUE) { - t = true; + target = true; } else if (s == FALSE) { - t = false; + target = false; } else { - throw Http400_BadRequest(); + throw Http400BadRequest(); } } void - set(std::string & t) const override + set(std::string & target) const override { - t = s; + target = s; } #define SET(T) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \ - void set(T & t) const override \ + void set(T & target) const override \ { \ - convert(s, t); \ + convert(s, target); \ } SET(Ice::Byte); @@ -196,149 +219,134 @@ namespace IceSpider { }; std::string - XWwwFormUrlEncoded::urlencode(const std::string_view s) + XWwwFormUrlEncoded::urlencode(const std::string_view str) { - return urlencode(s.begin(), s.end()); + return urlencode(str.begin(), str.end()); } - constexpr auto urlencoderange = [](auto && o, auto i, auto e) { - while (i != e) { - const auto & out = hexout[static_cast<uint8_t>(*i)]; - if (out.second) { - o = '%'; - o = out.first; - o = out.second; - } - else if (out.first) { - o = (out.first); - } - else { - o = (*i); - } - ++i; - } - }; - std::string - XWwwFormUrlEncoded::urlencode(std::string_view::const_iterator i, std::string_view::const_iterator e) + XWwwFormUrlEncoded::urlencode(std::string_view::const_iterator input, std::string_view::const_iterator end) { - std::string o; - o.reserve(static_cast<std::string::size_type>(std::distance(i, e))); - urlencoderange(std::back_inserter(o), i, e); - return o; + std::string out; + out.reserve(static_cast<std::string::size_type>(std::distance(input, end))); + urlEncodeRange(std::back_inserter(out), input, end); + return out; } void XWwwFormUrlEncoded::urlencodeto( - std::ostream & o, std::string_view::const_iterator i, std::string_view::const_iterator e) + std::ostream & outStrm, std::string_view::const_iterator input, std::string_view::const_iterator end) { - urlencoderange(std::ostream_iterator<decltype(*i)>(o), i, e); + urlEncodeRange(std::ostream_iterator<decltype(*input)>(outStrm), input, end); } MaybeString - XWwwFormUrlEncoded::urldecode(std::string_view::const_iterator i, std::string_view::const_iterator e) + XWwwFormUrlEncoded::urlDecode(std::string_view::const_iterator input, std::string_view::const_iterator end) { - const auto getNext = [e, &i] { - return std::find_first_of(i, e, URL_ESCAPES.begin(), URL_ESCAPES.end()); + const auto getNext = [end, &input] { + return std::find_first_of(input, end, URL_ESCAPES.begin(), URL_ESCAPES.end()); }; auto next = getNext(); - if (next == e) { - return std::string_view {i, e}; + if (next == end) { + return std::string_view {input, end}; } - std::string t; - t.reserve(static_cast<std::string::size_type>(std::distance(i, e))); - for (; i != e; next = getNext()) { - if (next != i) { - t.append(i, next); - i = next; + std::string target; + target.reserve(static_cast<std::string::size_type>(std::distance(input, end))); + for (; input != end; next = getNext()) { + if (next != input) { + target.append(input, next); + input = next; } else { - switch (*i) { + switch (*input) { case '+': - t += ' '; - ++i; + target += ' '; + ++input; break; case '%': - if (const auto ch = hexin[static_cast<uint8_t>(*(i + 1))][static_cast<uint8_t>(*(i + 2))]) { - t += ch; + if (const auto chr + = HEXIN[static_cast<uint8_t>(*(input + 1))][static_cast<uint8_t>(*(input + 2))]) { + target += chr; } else { - throw Http400_BadRequest(); + throw Http400BadRequest(); } - i += 3; + input += 3; break; + default: + std::unreachable(); } } } - return t; + return target; } void - XWwwFormUrlEncoded::iterateVars(const KVh & h, ba::split_iterator<std::string_view::const_iterator> pi) + XWwwFormUrlEncoded::iterateVars(const KVh & handler, ba::split_iterator<std::string_view::const_iterator> pi) { for (; pi != decltype(pi)(); ++pi) { - auto eq = std::find(pi->begin(), pi->end(), '='); - if (eq == pi->end()) { - h(urldecode(pi->begin(), pi->end()), {}); + auto equalPos = std::find(pi->begin(), pi->end(), '='); + if (equalPos == pi->end()) { + handler(urlDecode(pi->begin(), pi->end()), {}); } else { - h(urldecode(pi->begin(), eq), urldecode(eq + 1, pi->end())); + handler(urlDecode(pi->begin(), equalPos), urlDecode(equalPos + 1, pi->end())); } } } void - XWwwFormUrlEncoded::iterateVars(const std::string_view input, const KVh & h, const std::string_view split) + XWwwFormUrlEncoded::iterateVars(const std::string_view input, const KVh & handler, const std::string_view split) { if (!input.empty()) { - iterateVars(h, ba::make_split_iterator(input, ba::first_finder(split, ba::is_equal()))); + iterateVars(handler, ba::make_split_iterator(input, ba::first_finder(split, ba::is_equal()))); } } void - XWwwFormUrlEncoded::iterateVars(const KVh & h) + XWwwFormUrlEncoded::iterateVars(const KVh & handler) { - iterateVars(input, h, AMP); + iterateVars(input, handler, AMP); } void - XWwwFormUrlEncoded::DeserializeSimple(const Slicer::ModelPartParam mp) + XWwwFormUrlEncoded::deserializeSimple(const Slicer::ModelPartParam modelPart) { - iterateVars([mp](auto &&, const auto && v) { - mp->SetValue(SetFromString(std::forward<decltype(v)>(v))); + iterateVars([modelPart](auto &&, const auto && value) { + modelPart->SetValue(SetFromString(std::forward<decltype(value)>(value))); }); } void - XWwwFormUrlEncoded::DeserializeComplex(const Slicer::ModelPartParam mp) + XWwwFormUrlEncoded::deserializeComplex(const Slicer::ModelPartParam modelPart) { - mp->Create(); - iterateVars([mp](auto && k, const auto && v) { - mp->OnChild( - [&v](Slicer::ModelPartParam m, const Slicer::Metadata &) { - m->SetValue(SetFromString(std::forward<decltype(v)>(v))); + modelPart->Create(); + iterateVars([modelPart](auto && key, const auto && value) { + modelPart->OnChild( + [&value](Slicer::ModelPartParam child, const Slicer::Metadata &) { + child->SetValue(SetFromString(std::forward<decltype(value)>(value))); }, - k); + key); }); - mp->Complete(); + modelPart->Complete(); } void - XWwwFormUrlEncoded::DeserializeDictionary(const Slicer::ModelPartParam mp) + XWwwFormUrlEncoded::deserializeDictionary(const Slicer::ModelPartParam modelPart) { - iterateVars([mp](auto && k, const auto && v) { - mp->OnAnonChild([&k, &v](Slicer::ModelPartParam p, const Slicer::Metadata &) { - p->OnChild( - [&k](Slicer::ModelPartParam kp, const Slicer::Metadata &) { - kp->SetValue(SetFromString(std::forward<decltype(k)>(k))); + iterateVars([modelPart](auto && key, const auto && value) { + modelPart->OnAnonChild([&key, &value](Slicer::ModelPartParam child, const Slicer::Metadata &) { + child->OnChild( + [&key](Slicer::ModelPartParam keyPart, const Slicer::Metadata &) { + keyPart->SetValue(SetFromString(std::forward<decltype(key)>(key))); }, KEY); - p->OnChild( - [&v](Slicer::ModelPartParam vp, const Slicer::Metadata &) { - vp->SetValue(SetFromString(std::forward<decltype(v)>(v))); + child->OnChild( + [&value](Slicer::ModelPartParam valuePart, const Slicer::Metadata &) { + valuePart->SetValue(SetFromString(std::forward<decltype(value)>(value))); }, VALUE); - p->Complete(); + child->Complete(); }); }); } diff --git a/icespider/core/xwwwFormUrlEncoded.h b/icespider/core/xwwwFormUrlEncoded.h index 89cf9bc..8182d19 100644 --- a/icespider/core/xwwwFormUrlEncoded.h +++ b/icespider/core/xwwwFormUrlEncoded.h @@ -17,16 +17,16 @@ namespace IceSpider { public: using KVh = std::function<void(MaybeString &&, MaybeString &&)>; - explicit XWwwFormUrlEncoded(std::istream & in); + explicit XWwwFormUrlEncoded(std::istream & input); - void Deserialize(Slicer::ModelPartForRootParam mp) override; - DLL_PUBLIC static void iterateVars(const std::string_view input, const KVh & h, const std::string_view split); + void Deserialize(Slicer::ModelPartForRootParam modelPart) override; + DLL_PUBLIC static void iterateVars(std::string_view input, const KVh & h, std::string_view split); - DLL_PUBLIC static MaybeString urldecode(std::string_view::const_iterator s, std::string_view::const_iterator); - DLL_PUBLIC static std::string urlencode(std::string_view::const_iterator s, std::string_view::const_iterator); + DLL_PUBLIC static MaybeString urlDecode(std::string_view::const_iterator, std::string_view::const_iterator); + DLL_PUBLIC static std::string urlencode(std::string_view::const_iterator, std::string_view::const_iterator); DLL_PUBLIC static void urlencodeto( - std::ostream &, std::string_view::const_iterator s, std::string_view::const_iterator); - DLL_PUBLIC static std::string urlencode(const std::string_view s); + std::ostream &, std::string_view::const_iterator, std::string_view::const_iterator); + DLL_PUBLIC static std::string urlencode(std::string_view); private: static inline void iterateVars( @@ -34,9 +34,9 @@ namespace IceSpider { void iterateVars(const KVh & h); - void DeserializeSimple(const Slicer::ModelPartParam mp); - void DeserializeComplex(const Slicer::ModelPartParam mp); - void DeserializeDictionary(const Slicer::ModelPartParam mp); + void deserializeSimple(Slicer::ModelPartParam modelPart); + void deserializeComplex(Slicer::ModelPartParam modelPart); + void deserializeDictionary(Slicer::ModelPartParam modelPart); const std::string input; }; diff --git a/icespider/fcgi/cgiRequest.cpp b/icespider/fcgi/cgiRequest.cpp index 2692d07..5079813 100644 --- a/icespider/fcgi/cgiRequest.cpp +++ b/icespider/fcgi/cgiRequest.cpp @@ -1,10 +1,9 @@ #include "cgiRequest.h" #include <iostream> -#include <span> namespace IceSpider { - CgiRequest::CgiRequest(Core * c, int argc, char ** argv, char ** env) : - CgiRequestBase(c, EnvNTL {env}, EnvArray {argv, static_cast<size_t>(argc)}) + CgiRequest::CgiRequest(Core * core, int argc, char ** argv, char ** env) : + CgiRequestBase(core, EnvNTL {env}, EnvArray {argv, static_cast<size_t>(argc)}) { } diff --git a/icespider/fcgi/cgiRequest.h b/icespider/fcgi/cgiRequest.h index 2282334..8614254 100644 --- a/icespider/fcgi/cgiRequest.h +++ b/icespider/fcgi/cgiRequest.h @@ -8,7 +8,7 @@ namespace IceSpider { class CgiRequest : public CgiRequestBase { public: - CgiRequest(Core * c, int argc, char ** argv, char ** env); + CgiRequest(Core * core, int argc, char ** argv, char ** env); [[nodiscard]] std::istream & getInputStream() const override; [[nodiscard]] std::ostream & getOutputStream() const override; diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp index 33fdd7b..5a07b92 100644 --- a/icespider/fcgi/cgiRequestBase.cpp +++ b/icespider/fcgi/cgiRequestBase.cpp @@ -14,7 +14,6 @@ #include <slicer/common.h> #include <slicer/modelPartsTypes.h> #include <utility> -#include <vector> namespace ba = boost::algorithm; using namespace std::literals; @@ -22,63 +21,75 @@ using namespace std::literals; #define CGI_CONST(NAME) static constexpr std::string_view NAME(#NAME) namespace IceSpider { - static const auto slash_pred = boost::algorithm::is_any_of("/"); - constexpr std::string_view amp("&"); - constexpr std::string_view semi("; "); - constexpr std::string_view HEADER_PREFIX("HTTP_"); - CGI_CONST(HTTPS); - CGI_CONST(REDIRECT_URL); - CGI_CONST(SCRIPT_NAME); - CGI_CONST(QUERY_STRING); - CGI_CONST(HTTP_COOKIE); - CGI_CONST(REQUEST_METHOD); - - template<typename in, typename out> - inline void - mapVars(const std::string_view vn, const in & envmap, out & map, const std::string_view sp) - { - auto qs = envmap.find(vn); - if (qs != envmap.end()) { - XWwwFormUrlEncoded::iterateVars( - qs->second, - [&map](auto && k, auto && v) { - map.insert({std::forward<decltype(k)>(k), std::forward<decltype(v)>(v)}); - }, - sp); + namespace { + const auto SLASH_PRED = boost::algorithm::is_any_of("/"); + constexpr std::string_view AMP("&"); + constexpr std::string_view SEMI("; "); + constexpr std::string_view HEADER_PREFIX("HTTP_"); + CGI_CONST(HTTPS); + CGI_CONST(REDIRECT_URL); + CGI_CONST(SCRIPT_NAME); + CGI_CONST(QUERY_STRING); + CGI_CONST(HTTP_COOKIE); + CGI_CONST(REQUEST_METHOD); + + template<typename In, typename Out> + inline void + mapVars(const std::string_view key, const In & envmap, Out & map, const std::string_view separators) + { + auto qs = envmap.find(key); + if (qs != envmap.end()) { + XWwwFormUrlEncoded::iterateVars( + qs->second, + [&map](auto && key, auto && value) { + map.insert({std::forward<decltype(key)>(key), std::forward<decltype(value)>(value)}); + }, + separators); + } } - } - template<typename Ex, typename Map, typename... Ks> - const std::string_view - findFirstOrElse(const Map & map, const std::string_view k, const Ks &... ks) - { - if (const auto i = map.find(k); i != map.end()) { - return i->second; + template<typename Ex, typename Map, typename... Ks> + std::string_view + findFirstOrElse(const Map & map, const std::string_view key, const Ks &... ks) + { + if (const auto iter = map.find(key); iter != map.end()) { + return iter->second; + } + if constexpr (sizeof...(ks)) { + return findFirstOrElse<Ex>(map, ks...); + } + throw Ex(); } - if constexpr (sizeof...(ks)) { - return findFirstOrElse<Ex>(map, ks...); + + template<typename Fmt, typename Map> + void + dumpMap(std::ostream & strm, const std::string_view name, const Map & map) + { + strm << name << '\n'; + for (const auto & [key, value] : map) { + Fmt::write(strm, key, value); + } } - throw Ex(); } - CgiRequestBase::CgiRequestBase(Core * c, const EnvArray envs, const EnvArray extra) : IHttpRequest(c) + CgiRequestBase::CgiRequestBase(Core * core, const EnvArray envs, const EnvArray extra) : IHttpRequest(core) { for (const auto & envdata : {envs, extra}) { - for (const std::string_view e : envdata) { - if (const auto eq = e.find('='); eq != std::string_view::npos) { - envmap.insert({e.substr(0, eq), e.substr(eq + 1)}); + for (const std::string_view env : envdata) { + if (const auto equalPos = env.find('='); equalPos != std::string_view::npos) { + envmap.emplace(env.substr(0, equalPos), env.substr(equalPos + 1)); } } } - if (auto path = findFirstOrElse<Http400_BadRequest>(envmap, REDIRECT_URL, SCRIPT_NAME).substr(1); + if (auto path = findFirstOrElse<Http400BadRequest>(envmap, REDIRECT_URL, SCRIPT_NAME).substr(1); // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) !path.empty()) { - ba::split(pathElements, path, slash_pred, ba::token_compress_off); + ba::split(pathElements, path, SLASH_PRED, ba::token_compress_off); } - mapVars(QUERY_STRING, envmap, qsmap, amp); - mapVars(HTTP_COOKIE, envmap, cookiemap, semi); + mapVars(QUERY_STRING, envmap, qsmap, AMP); + mapVars(HTTP_COOKIE, envmap, cookiemap, SEMI); for (auto header = envmap.lower_bound(HEADER_PREFIX); header != envmap.end() && ba::starts_with(header->first, HEADER_PREFIX); header++) { hdrmap.insert({header->first.substr(HEADER_PREFIX.length()), header->second}); @@ -88,38 +99,28 @@ namespace IceSpider { AdHocFormatter(VarFmt, "\t%?: [%?]\n"); AdHocFormatter(PathFmt, "\t[%?]\n"); - template<typename Fmt, typename Map> - void - dumpMap(std::ostream & s, const std::string_view n, const Map & map) - { - s << n << std::endl; - for (const auto & p : map) { - Fmt::write(s, p.first, p.second); - } - } - std::ostream & - CgiRequestBase::dump(std::ostream & s) const + CgiRequestBase::dump(std::ostream & strm) const { - dumpMap<VarFmt>(s, "Environment dump"sv, envmap); - s << "Path dump" << std::endl; - for (const auto & e : pathElements) { - PathFmt::write(s, e); + dumpMap<VarFmt>(strm, "Environment dump"sv, envmap); + strm << "Path dump" << '\n'; + for (const auto & element : pathElements) { + PathFmt::write(strm, element); } - dumpMap<VarFmt>(s, "Query string dump"sv, qsmap); - dumpMap<VarFmt>(s, "Cookie dump"sv, cookiemap); - return s; + dumpMap<VarFmt>(strm, "Query string dump"sv, qsmap); + dumpMap<VarFmt>(strm, "Cookie dump"sv, cookiemap); + return strm; } template<typename MapType> OptionalString - CgiRequestBase::optionalLookup(const std::string_view key, const MapType & vm) + CgiRequestBase::optionalLookup(const std::string_view key, const MapType & map) { - auto i = vm.find(key); - if (i == vm.end()) { + auto iter = map.find(key); + if (iter == map.end()) { return {}; } - return i->second; + return iter->second; } const PathElements & @@ -138,14 +139,14 @@ namespace IceSpider { CgiRequestBase::getRequestMethod() const { try { - auto i = envmap.find(REQUEST_METHOD); - if (i == envmap.end()) { - throw IceSpider::Http400_BadRequest(); + auto iter = envmap.find(REQUEST_METHOD); + if (iter == envmap.end()) { + throw IceSpider::Http400BadRequest(); } - return Slicer::ModelPartForEnum<HttpMethod>::lookup(i->second); + return Slicer::ModelPartForEnum<HttpMethod>::lookup(iter->second); } catch (const Slicer::InvalidEnumerationSymbol &) { - throw IceSpider::Http405_MethodNotAllowed(); + throw IceSpider::Http405MethodNotAllowed(); } } diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index e5a0d32..75f0f90 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -20,29 +20,29 @@ namespace IceSpider { // Null terminated list, bsv will handle this and is convertible to span using EnvNTL = std::basic_string_view<const char * const>; - CgiRequestBase(Core * c, const EnvArray envs, const EnvArray extra = {}); + CgiRequestBase(Core * core, EnvArray envs, EnvArray extra = {}); public: - using VarMap = flatmap<std::string_view, std::string_view>; - using HdrMap = flatmap<std::string_view, std::string_view, AdHoc::case_less>; - using StrMap = flatmap<MaybeString, MaybeString>; + using VarMap = FlatMap<std::string_view, std::string_view>; + using HdrMap = FlatMap<std::string_view, std::string_view, AdHoc::case_less>; + using StrMap = FlatMap<MaybeString, MaybeString>; [[nodiscard]] const PathElements & getRequestPath() const override; [[nodiscard]] PathElements & getRequestPath() override; [[nodiscard]] HttpMethod getRequestMethod() const override; - [[nodiscard]] OptionalString getQueryStringParamStr(const std::string_view key) const override; - [[nodiscard]] OptionalString getHeaderParamStr(const std::string_view key) const override; - [[nodiscard]] OptionalString getCookieParamStr(const std::string_view key) const override; - [[nodiscard]] OptionalString getEnvStr(const std::string_view key) const override; + [[nodiscard]] OptionalString getQueryStringParamStr(std::string_view key) const override; + [[nodiscard]] OptionalString getHeaderParamStr(std::string_view key) const override; + [[nodiscard]] OptionalString getCookieParamStr(std::string_view key) const override; + [[nodiscard]] OptionalString getEnvStr(std::string_view key) const override; [[nodiscard]] bool isSecure() const override; - void response(short, const std::string_view) const override; - void setHeader(const std::string_view, const std::string_view) const override; + void response(short, std::string_view) const override; + void setHeader(std::string_view, std::string_view) const override; - std::ostream & dump(std::ostream & s) const override; + std::ostream & dump(std::ostream & strm) const override; private: - template<typename MapType> static OptionalString optionalLookup(const std::string_view key, const MapType &); + template<typename MapType> static OptionalString optionalLookup(std::string_view key, const MapType &); VarMap envmap {40}; StrMap qsmap; diff --git a/icespider/fcgi/fcgiRequest.cpp b/icespider/fcgi/fcgiRequest.cpp index fb56728..0c8af2d 100644 --- a/icespider/fcgi/fcgiRequest.cpp +++ b/icespider/fcgi/fcgiRequest.cpp @@ -1,8 +1,9 @@ #include "fcgiRequest.h" namespace IceSpider { - FcgiRequest::FcgiRequest(Core * c, FCGX_Request * r) : - CgiRequestBase(c, EnvNTL {r->envp}), inputbuf(r->in), input(&inputbuf), outputbuf(r->out), output(&outputbuf) + FcgiRequest::FcgiRequest(Core * core, FCGX_Request * req) : + CgiRequestBase(core, EnvNTL {req->envp}), inputbuf(req->in), input(&inputbuf), outputbuf(req->out), + output(&outputbuf) { } diff --git a/icespider/fcgi/fcgiRequest.h b/icespider/fcgi/fcgiRequest.h index a85d21f..cf9c9a5 100644 --- a/icespider/fcgi/fcgiRequest.h +++ b/icespider/fcgi/fcgiRequest.h @@ -10,11 +10,12 @@ namespace IceSpider { class FcgiRequest : public CgiRequestBase { public: - FcgiRequest(Core * c, FCGX_Request * r); + FcgiRequest(Core * core, FCGX_Request * req); std::istream & getInputStream() const override; std::ostream & getOutputStream() const override; + private: fcgi_streambuf inputbuf; mutable std::istream input; fcgi_streambuf outputbuf; diff --git a/icespider/fcgi/main.cpp b/icespider/fcgi/main.cpp index b4b9052..4746f53 100644 --- a/icespider/fcgi/main.cpp +++ b/icespider/fcgi/main.cpp @@ -19,14 +19,14 @@ main(int argc, char ** argv, char ** env) FCGX_InitRequest(&request, 0, 0); while (FCGX_Accept_r(&request) == 0) { - FcgiRequest r(&core, &request); - core.process(&r); + FcgiRequest req(&core, &request); + core.process(&req); FCGX_Finish_r(&request); } } else { - CgiRequest r(&core, argc, argv, env); - core.process(&r); + CgiRequest req(&core, argc, argv, env); + core.process(&req); } return 0; } diff --git a/icespider/fileSessions/fileSessions.cpp b/icespider/fileSessions/fileSessions.cpp index 9a23898..da9fdea 100644 --- a/icespider/fileSessions/fileSessions.cpp +++ b/icespider/fileSessions/fileSessions.cpp @@ -15,7 +15,6 @@ #include <exception> #include <factory.impl.h> #include <fileUtils.h> -#include <ios> #include <memory> #include <session.h> #include <string> @@ -28,9 +27,10 @@ namespace IceSpider { class FileSessions : public Plugin, public SessionManager { public: - FileSessions(Ice::CommunicatorPtr c, const Ice::PropertiesPtr & p) : - ic(std::move(c)), root(p->getProperty("IceSpider.FileSessions.Path")), - duration(static_cast<Ice::Short>(p->getPropertyAsIntWithDefault("IceSpider.FileSessions.Duration", 3600))) + FileSessions(Ice::CommunicatorPtr com, const Ice::PropertiesPtr & props) : + ic(std::move(com)), root(props->getProperty("IceSpider.FileSessions.Path")), + duration(static_cast<Ice::Short>( + props->getPropertyAsIntWithDefault("IceSpider.FileSessions.Duration", 3600))) { if (!root.empty() && !std::filesystem::exists(root)) { std::filesystem::create_directories(root); @@ -45,8 +45,7 @@ namespace IceSpider { try { removeExpired(); } - catch (...) { - // Meh :) + catch (...) { // NOLINT(bugprone-empty-catch) - Meh :) } } @@ -56,36 +55,36 @@ namespace IceSpider { SessionPtr createSession(const ::Ice::Current &) override { - auto s = std::make_shared<Session>(); + auto session = std::make_shared<Session>(); // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall) - s->id = boost::lexical_cast<std::string>(boost::uuids::random_generator()()); - s->duration = duration; - save(s); - return s; + session->id = boost::lexical_cast<std::string>(boost::uuids::random_generator()()); + session->duration = duration; + save(session); + return session; } SessionPtr - getSession(const ::std::string id, const ::Ice::Current & current) override + getSession(const ::std::string sessionId, const ::Ice::Current & current) override { - auto s = load(id); - if (s && isExpired(s)) { - destroySession(id, current); + auto session = load(sessionId); + if (session && isExpired(session)) { + destroySession(sessionId, current); return nullptr; } - return s; + return session; } void - updateSession(const SessionPtr s, const ::Ice::Current &) override + updateSession(const SessionPtr session, const ::Ice::Current &) override { - save(s); + save(session); } void - destroySession(const ::std::string id, const ::Ice::Current &) override + destroySession(const ::std::string sessionId, const ::Ice::Current &) override { try { - std::filesystem::remove(root / id); + std::filesystem::remove(root / sessionId); } catch (const std::exception & e) { throw SessionError(e.what()); @@ -94,36 +93,36 @@ namespace IceSpider { private: void - save(const SessionPtr & s) + save(const SessionPtr & session) { - s->lastUsed = time(nullptr); + session->lastUsed = time(nullptr); Ice::OutputStream buf(ic); - buf.write(s); + buf.write(session); const auto range = buf.finished(); // NOLINTNEXTLINE(hicpp-signed-bitwise) - AdHoc::FileUtils::FileHandle f(root / s->id, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - sysassert(flock(f.fh, LOCK_EX), -1); - sysassert(pwrite(f.fh, range.first, static_cast<size_t>(range.second - range.first), 0), -1); - sysassert(ftruncate(f.fh, range.second - range.first), -1); - sysassert(flock(f.fh, LOCK_UN), -1); + AdHoc::FileUtils::FileHandle sessionFile(root / session->id, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + sysassert(flock(sessionFile.fh, LOCK_EX), -1); + sysassert(pwrite(sessionFile.fh, range.first, static_cast<size_t>(range.second - range.first), 0), -1); + sysassert(ftruncate(sessionFile.fh, range.second - range.first), -1); + sysassert(flock(sessionFile.fh, LOCK_UN), -1); } SessionPtr - load(const std::string & id) + load(const std::string & sessionId) { - auto path = root / id; + auto path = root / sessionId; if (!std::filesystem::exists(path)) { return nullptr; } try { - AdHoc::FileUtils::MemMap f(path); - sysassert(flock(f.fh, LOCK_SH), -1); - auto fbuf = f.sv<Ice::Byte>(); + AdHoc::FileUtils::MemMap sessionFile(path); + sysassert(flock(sessionFile.fh, LOCK_SH), -1); + auto fbuf = sessionFile.sv<Ice::Byte>(); Ice::InputStream buf(ic, std::make_pair(fbuf.begin(), fbuf.end())); - SessionPtr s; - buf.read(s); - sysassert(flock(f.fh, LOCK_UN), -1); - return s; + SessionPtr session; + buf.read(session); + sysassert(flock(sessionFile.fh, LOCK_UN), -1); + return session; } catch (const AdHoc::SystemException & e) { if (e.errNo == ENOENT) { @@ -139,20 +138,21 @@ namespace IceSpider { if (root.empty() || !std::filesystem::exists(root)) { return; } - std::filesystem::directory_iterator di(root); - while (di != std::filesystem::directory_iterator()) { - auto s = load(di->path()); - if (s && isExpired(s)) { - FileSessions::destroySession(s->id, Ice::Current()); + std::filesystem::directory_iterator dirIter(root); + while (dirIter != std::filesystem::directory_iterator()) { + auto session = load(dirIter->path()); + if (session && isExpired(session)) { + FileSessions::destroySession(session->id, Ice::Current()); } - di++; + dirIter++; } } - bool - isExpired(const SessionPtr & s) + [[nodiscard]] + static bool + isExpired(const SessionPtr & session) { - return (s->lastUsed + s->duration < time(nullptr)); + return (session->lastUsed + session->duration < time(nullptr)); } template<typename R, typename ER> diff --git a/icespider/testing/testRequest.cpp b/icespider/testing/testRequest.cpp index 61c7d94..86e856b 100644 --- a/icespider/testing/testRequest.cpp +++ b/icespider/testing/testRequest.cpp @@ -1,5 +1,4 @@ #include "testRequest.h" -#include <array> #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/constants.hpp> #include <boost/algorithm/string/find_iterator.hpp> @@ -12,16 +11,15 @@ #include <utility> namespace IceSpider { - constexpr std::string_view slash("/"); + constexpr std::string_view SLASH("/"); - TestRequest::TestRequest(const Core * c, HttpMethod m, const std::string_view p) : IHttpRequest(c), method(m) + TestRequest::TestRequest(const Core * core, HttpMethod method, std::string_view path) : + IHttpRequest(core), method(method) { namespace ba = boost::algorithm; - auto path = p.substr(1); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + path.remove_prefix(1); if (!path.empty()) { - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - ba::split(url, path, ba::is_any_of(slash), ba::token_compress_off); + ba::split(url, path, ba::is_any_of(SLASH), ba::token_compress_off); } } @@ -74,13 +72,13 @@ namespace IceSpider { } OptionalString - TestRequest::get(const std::string_view key, const MapVars & vars) const + TestRequest::get(const std::string_view key, const MapVars & vars) { - auto i = vars.find(key); - if (i == vars.end()) { + auto iter = vars.find(key); + if (iter == vars.end()) { return {}; } - return i->second; + return iter->second; } void @@ -143,9 +141,9 @@ namespace IceSpider { } std::ostream & - TestRequest::dump(std::ostream & s) const + TestRequest::dump(std::ostream & strm) const { - return s; + return strm; } const TestRequest::MapVars & @@ -153,13 +151,21 @@ namespace IceSpider { { if (responseHeaders.empty()) { while (true) { - std::array<char, BUFSIZ> buf {}, n {}, v {}; - output.getline(buf.data(), BUFSIZ); - // NOLINTNEXTLINE(hicpp-vararg) - if (sscanf(buf.data(), "%[^:]: %[^\r]", n.data(), v.data()) != 2) { + std::string lineBuffer; + lineBuffer.resize_and_overwrite(BUFSIZ, [this](char * buf, size_t len) { + output.getline(buf, static_cast<std::streamsize>(len)); + return static_cast<size_t>(output.gcount()); + }); + if (lineBuffer.empty()) { break; } - responseHeaders[n.data()] = v.data(); + auto colonPos = lineBuffer.find(':'); + if (colonPos == std::string::npos) { + break; + } + auto valStart = lineBuffer.find_first_not_of(' ', colonPos + 1); + auto valEnd = lineBuffer.find_first_of("\r\n", valStart); + responseHeaders.emplace(lineBuffer.substr(0, colonPos), lineBuffer.substr(valStart, valEnd - valStart)); } } return responseHeaders; diff --git a/icespider/testing/testRequest.h b/icespider/testing/testRequest.h index 77efda2..6d87bb0 100644 --- a/icespider/testing/testRequest.h +++ b/icespider/testing/testRequest.h @@ -16,25 +16,25 @@ namespace IceSpider { public: using MapVars = std::map<std::string, std::string, std::less<>>; - TestRequest(const Core * c, HttpMethod m, const std::string_view p); + TestRequest(const Core * core, HttpMethod method, std::string_view path); const PathElements & getRequestPath() const override; PathElements & getRequestPath() override; HttpMethod getRequestMethod() const override; - OptionalString getEnvStr(const std::string_view key) const override; - OptionalString getQueryStringParamStr(const std::string_view key) const override; - OptionalString getCookieParamStr(const std::string_view key) const override; - OptionalString getHeaderParamStr(const std::string_view key) const override; + OptionalString getEnvStr(std::string_view key) const override; + OptionalString getQueryStringParamStr(std::string_view key) const override; + OptionalString getCookieParamStr(std::string_view key) const override; + OptionalString getHeaderParamStr(std::string_view key) const override; bool isSecure() const override; - void setQueryStringParam(const std::string_view, const OptionalString &); - void setHeaderParam(const std::string_view, const OptionalString &); - void setCookieParam(const std::string_view, const OptionalString &); - void setEnv(const std::string_view, const OptionalString &); + void setQueryStringParam(std::string_view, const OptionalString &); + void setHeaderParam(std::string_view, const OptionalString &); + void setCookieParam(std::string_view, const OptionalString &); + void setEnv(std::string_view, const OptionalString &); std::istream & getInputStream() const override; std::ostream & getOutputStream() const override; - void response(short statusCode, const std::string_view statusMsg) const override; - void setHeader(const std::string_view header, const std::string_view value) const override; - std::ostream & dump(std::ostream & s) const override; + void response(short statusCode, std::string_view statusMsg) const override; + void setHeader(std::string_view header, std::string_view value) const override; + std::ostream & dump(std::ostream & strm) const override; const MapVars & getResponseHeaders(); @@ -48,8 +48,8 @@ namespace IceSpider { const HttpMethod method; protected: - OptionalString get(const std::string_view, const MapVars &) const; - void set(const std::string_view, const OptionalString &, MapVars &); + static OptionalString get(std::string_view, const MapVars &); + static void set(std::string_view, const OptionalString &, MapVars &); private: MapVars responseHeaders; diff --git a/icespider/unittests/testAccept.cpp b/icespider/unittests/testAccept.cpp index 410147f..303cd7f 100644 --- a/icespider/unittests/testAccept.cpp +++ b/icespider/unittests/testAccept.cpp @@ -2,6 +2,7 @@ #include <boost/test/data/test_case.hpp> #include <boost/test/unit_test.hpp> +#include <exceptions.h> #include <ihttpRequest.h> #include <optional> #include <ostream> @@ -9,7 +10,7 @@ #include <vector> namespace IceSpider { - class Http400_BadRequest; + class Http400BadRequest; } auto parse = IceSpider::IHttpRequest::parseAccept; @@ -42,7 +43,7 @@ BOOST_DATA_TEST_CASE(bad_requests, }), a) { - BOOST_CHECK_THROW(parse(a), IceSpider::Http400_BadRequest); + BOOST_CHECK_THROW(parse(a), IceSpider::Http400BadRequest); } BOOST_DATA_TEST_CASE(texthtml, diff --git a/icespider/unittests/testApp.cpp b/icespider/unittests/testApp.cpp index c40ed95..de59cfd 100644 --- a/icespider/unittests/testApp.cpp +++ b/icespider/unittests/testApp.cpp @@ -104,13 +104,13 @@ BOOST_AUTO_TEST_CASE(testFindRoutes) BOOST_REQUIRE(findRoute(&requestGetIndex)); TestRequest requestPostIndex(this, HttpMethod::POST, "/"); - BOOST_REQUIRE_THROW(findRoute(&requestPostIndex), IceSpider::Http405_MethodNotAllowed); + BOOST_REQUIRE_THROW(findRoute(&requestPostIndex), IceSpider::Http405MethodNotAllowed); TestRequest requestPostUpdate(this, HttpMethod::POST, "/something"); BOOST_REQUIRE(findRoute(&requestPostUpdate)); TestRequest requestGetUpdate(this, HttpMethod::GET, "/something"); - BOOST_REQUIRE_THROW(findRoute(&requestGetUpdate), IceSpider::Http405_MethodNotAllowed); + BOOST_REQUIRE_THROW(findRoute(&requestGetUpdate), IceSpider::Http405MethodNotAllowed); TestRequest requestGetItem(this, HttpMethod::GET, "/view/something/something"); BOOST_REQUIRE(findRoute(&requestGetItem)); @@ -123,13 +123,13 @@ BOOST_AUTO_TEST_CASE(testFindRoutes) TestRequest requestGetItemLong( this, HttpMethod::GET, "/view/something/something/extra/many/things/longer/than/longest/route"); - BOOST_REQUIRE_THROW(findRoute(&requestGetItemLong), IceSpider::Http404_NotFound); + BOOST_REQUIRE_THROW(findRoute(&requestGetItemLong), IceSpider::Http404NotFound); TestRequest requestGetItemShort(this, HttpMethod::GET, "/view/missingSomething"); - BOOST_REQUIRE_THROW(findRoute(&requestGetItemShort), IceSpider::Http404_NotFound); + BOOST_REQUIRE_THROW(findRoute(&requestGetItemShort), IceSpider::Http404NotFound); TestRequest requestGetNothing(this, HttpMethod::GET, "/badview/something/something"); - BOOST_REQUIRE_THROW(findRoute(&requestGetNothing), IceSpider::Http404_NotFound); + BOOST_REQUIRE_THROW(findRoute(&requestGetNothing), IceSpider::Http404NotFound); TestRequest requestDeleteThing(this, HttpMethod::DELETE, "/something"); BOOST_REQUIRE(findRoute(&requestDeleteThing)); @@ -540,18 +540,18 @@ public: { if (const auto * tex = dynamic_cast<const TestIceSpider::Ex *>(&ex)) { if (tex->message == "404") { - throw IceSpider::Http404_NotFound(); + throw IceSpider::Http404NotFound(); } if (tex->message == "304") { request->getRequestPath().front() = "some value"; - return IceSpider::ErrorHandlerResult_Modified; + return IceSpider::ErrorHandlerResult::Modified; } if (tex->message == "400") { request->response(400, "Handled"); - return IceSpider::ErrorHandlerResult_Handled; + return IceSpider::ErrorHandlerResult::Handled; } } - return IceSpider::ErrorHandlerResult_Unhandled; + return IceSpider::ErrorHandlerResult::Unhandled; } }; diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp index b3ea6e2..67ab322 100644 --- a/icespider/unittests/testFcgi.cpp +++ b/icespider/unittests/testFcgi.cpp @@ -8,6 +8,7 @@ #include <cstdlib> #include <cstring> #include <ctime> +#include <exceptions.h> #include <http.h> #include <ihttpRequest.h> #include <iostream> @@ -21,11 +22,11 @@ #include <vector> namespace IceSpider { - class Http400_BadRequest; + class Http400BadRequest; } namespace IceSpider { - class Http405_MethodNotAllowed; + class Http405MethodNotAllowed; } using namespace std::literals; @@ -106,7 +107,7 @@ BOOST_FIXTURE_TEST_SUITE(CgiRequestBase, IceSpider::CoreWithDefaultRouter); BOOST_AUTO_TEST_CASE(NoEnvironment) { - BOOST_REQUIRE_THROW({ TestRequest r(this, {}); }, IceSpider::Http400_BadRequest); + BOOST_REQUIRE_THROW({ TestRequest r(this, {}); }, IceSpider::Http400BadRequest); } BOOST_AUTO_TEST_CASE(script_name_root) @@ -206,13 +207,13 @@ BOOST_AUTO_TEST_CASE(requestmethod_post) BOOST_AUTO_TEST_CASE(requestmethod_bad) { TestRequest r(this, {{"SCRIPT_NAME=/", "REQUEST_METHOD=No"}}); - BOOST_REQUIRE_THROW((void)r.getRequestMethod(), IceSpider::Http405_MethodNotAllowed); + BOOST_REQUIRE_THROW((void)r.getRequestMethod(), IceSpider::Http405MethodNotAllowed); } BOOST_AUTO_TEST_CASE(requestmethod_missing) { TestRequest r {this, {{"SCRIPT_NAME=/"}}}; - BOOST_REQUIRE_THROW((void)r.getRequestMethod(), IceSpider::Http400_BadRequest); + BOOST_REQUIRE_THROW((void)r.getRequestMethod(), IceSpider::Http400BadRequest); } BOOST_AUTO_TEST_CASE(acceptheader) diff --git a/icespider/unittests/testFlatMap.cpp b/icespider/unittests/testFlatMap.cpp index ed19371..f673cdd 100644 --- a/icespider/unittests/testFlatMap.cpp +++ b/icespider/unittests/testFlatMap.cpp @@ -7,7 +7,7 @@ #include <utility> #include <vector> -using TM = IceSpider::flatmap<std::string_view, int>; +using TM = IceSpider::FlatMap<std::string_view, int>; BOOST_TEST_DONT_PRINT_LOG_VALUE(TM::const_iterator) @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(several) BOOST_AUTO_TEST_SUITE_END() -using TMI = IceSpider::flatmap<int, std::string_view>; +using TMI = IceSpider::FlatMap<int, std::string_view>; BOOST_TEST_DONT_PRINT_LOG_VALUE(TMI::const_iterator) diff --git a/icespider/xslt/xsltStreamSerializer.cpp b/icespider/xslt/xsltStreamSerializer.cpp index c89e89c..4099317 100644 --- a/icespider/xslt/xsltStreamSerializer.cpp +++ b/icespider/xslt/xsltStreamSerializer.cpp @@ -1,5 +1,4 @@ #include "xsltStreamSerializer.h" -#include <chrono> #include <filesystem> #include <libxml++/document.h> #include <libxml++/exceptions/exception.h> @@ -52,12 +51,15 @@ namespace IceSpider { return std::make_shared<XsltStreamSerializer>(strm, stylesheet.get()); } - XsltStreamSerializer::XsltStreamSerializer(std::ostream & os, xsltStylesheet * ss) : strm(os), stylesheet(ss) { } + XsltStreamSerializer::XsltStreamSerializer(std::ostream & strm, xsltStylesheet * stylesheet) : + strm(strm), stylesheet(stylesheet) + { + } void - XsltStreamSerializer::Serialize(Slicer::ModelPartForRootParam mp) + XsltStreamSerializer::Serialize(Slicer::ModelPartForRootParam modelPart) { - Slicer::XmlDocumentSerializer::Serialize(mp); + Slicer::XmlDocumentSerializer::Serialize(modelPart); const auto result = std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> { xsltApplyStylesheet(stylesheet, doc.cobj(), nullptr), &xmlFreeDoc}; if (!result) { diff --git a/icespider/xslt/xsltStreamSerializer.h b/icespider/xslt/xsltStreamSerializer.h index 3dda157..f64ed7e 100644 --- a/icespider/xslt/xsltStreamSerializer.h +++ b/icespider/xslt/xsltStreamSerializer.h @@ -27,7 +27,7 @@ namespace IceSpider { XsltStreamSerializer(std::ostream &, xsltStylesheet *); - void Serialize(Slicer::ModelPartForRootParam mp) override; + void Serialize(Slicer::ModelPartForRootParam modelPart) override; protected: std::ostream & strm; |