From 7ab9c7944815426744d9ace42f076d0aebc163fb Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 26 Jul 2023 13:48:04 +0100 Subject: Simplified C++17 namespaces --- icespider/compile/routeCompiler.cpp | 1027 +++++++++++++++++------------------ 1 file changed, 509 insertions(+), 518 deletions(-) diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index 3d3913d..a7a7695 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -26,567 +26,591 @@ #include #include -namespace IceSpider { +namespace IceSpider::Compile { using namespace AdHoc::literals; - namespace Compile { - RouteCompiler::RouteCompiler() - { - searchPath.push_back(std::filesystem::current_path()); - } + RouteCompiler::RouteCompiler() + { + searchPath.push_back(std::filesystem::current_path()); + } - RouteConfigurationPtr - RouteCompiler::loadConfiguration(const std::filesystem::path & input) const - { - auto deserializer = Slicer::DeserializerPtr( - Slicer::FileDeserializerFactory::createNew(input.extension().string(), input)); - return Slicer::DeserializeAnyWith(deserializer); - } + RouteConfigurationPtr + RouteCompiler::loadConfiguration(const std::filesystem::path & input) const + { + auto deserializer = Slicer::DeserializerPtr( + Slicer::FileDeserializerFactory::createNew(input.extension().string(), input)); + return Slicer::DeserializeAnyWith(deserializer); + } - Ice::StringSeq - operator+(Ice::StringSeq ss, const std::string & s) - { - ss.push_back(s); - return ss; - } + 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) - { - 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 & m : c->modules()) { - if (auto op = findOperation(on, m, ns + m->name())) { + Slice::OperationPtr + // NOLINTNEXTLINE(misc-no-recursion) + RouteCompiler::findOperation(const std::string & on, const Slice::ContainerPtr & c, const Ice::StringSeq & ns) + { + 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; } } - return nullptr; } + for (const auto & m : c->modules()) { + if (auto op = findOperation(on, m, ns + m->name())) { + return op; + } + } + return nullptr; + } - Slice::OperationPtr - // NOLINTNEXTLINE(misc-no-recursion) - RouteCompiler::findOperation(const std::string & on, const Units & us) - { - for (const auto & u : us) { - if (auto op = findOperation(on, u.second)) { - return op; - } + Slice::OperationPtr + // NOLINTNEXTLINE(misc-no-recursion) + RouteCompiler::findOperation(const std::string & on, const Units & us) + { + for (const auto & u : us) { + if (auto op = findOperation(on, u.second)) { + return op; } - throw std::runtime_error("Find operation " + on + " failed."); } + throw std::runtime_error("Find operation " + on + " failed."); + } - std::optional - // NOLINTNEXTLINE(misc-no-recursion) - RouteCompiler::findType(const std::string & tn, const Slice::ContainerPtr & c, const Ice::StringSeq & ns) - { - for (const auto & strct : c->structs()) { - auto fqon = boost::algorithm::join(ns + strct->name(), "."); - if (fqon == tn) { - return {{Slice::typeToString(strct), {}, strct->dataMembers()}}; - } - auto t = findType(tn, strct, ns + strct->name()); + std::optional + // NOLINTNEXTLINE(misc-no-recursion) + RouteCompiler::findType(const std::string & tn, const Slice::ContainerPtr & c, const Ice::StringSeq & ns) + { + 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 & cls : c->classes()) { - auto fqon = boost::algorithm::join(ns + cls->name(), "."); - if (fqon == tn) { - return {{Slice::typeToString(cls->declaration()), cls->scoped(), cls->dataMembers()}}; - } - if (auto t = findType(tn, cls, ns + cls->name())) { - return t; - } + 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()}}; } - for (const auto & m : c->modules()) { - if (auto t = findType(tn, m, ns + m->name())) { - return t; - } + if (auto t = findType(tn, cls, ns + cls->name())) { + return t; } - return {}; } + for (const auto & m : c->modules()) { + if (auto t = findType(tn, m, ns + m->name())) { + return t; + } + } + return {}; + } - RouteCompiler::Type - RouteCompiler::findType(const std::string & tn, const Units & us) - { - for (const auto & u : us) { - if (auto t = findType(tn, u.second)) { - return *t; - } + RouteCompiler::Type + RouteCompiler::findType(const std::string & tn, const Units & us) + { + for (const auto & u : us) { + if (auto t = findType(tn, u.second)) { + return *t; } - throw std::runtime_error("Find type " + tn + " failed."); } + throw std::runtime_error("Find type " + tn + " failed."); + } - RouteCompiler::ParameterMap - RouteCompiler::findParameters(const RoutePtr & r, const Units & us) - { - 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); + RouteCompiler::ParameterMap + RouteCompiler::findParameters(const RoutePtr & r, const Units & us) + { + 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; } - for (const auto & p : op->parameters()) { - auto po = o.second->paramOverrides.find(p->name()); - if (po != o.second->paramOverrides.end()) { - pm[po->second] = p; - } - else { - pm[p->name()] = p; - } + else { + pm[p->name()] = p; } } - return pm; } + return pm; + } - void - RouteCompiler::applyDefaults(const RouteConfigurationPtr & c, const Units & u) const - { - for (const auto & r : c->routes) { - if (r.second->operation) { - r.second->operations[std::string()] - = std::make_shared(*r.second->operation, StringMap()); + void + RouteCompiler::applyDefaults(const RouteConfigurationPtr & c, const Units & u) const + { + for (const auto & r : c->routes) { + if (r.second->operation) { + r.second->operations[std::string()] = std::make_shared(*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()) { + 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(ParameterSource::URL, p.first, false, + Ice::optional(), Ice::optional(), + false)}) + .first; } - 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()) { - if (!defined->second->key && defined->second->source != ParameterSource::Body) { - defined->second->key = defined->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(pp.get())) { + return par->name == *d->key; } - } - else { - defined = r.second->params - .insert({p.first, - std::make_shared(ParameterSource::URL, p.first, false, - Ice::optional(), Ice::optional(), - 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(pp.get())) { - return par->name == *d->key; - } - return false; - }) != path.parts.end(); - } + return false; + }) != path.parts.end(); } } } + } - void - RouteCompiler::compile(const std::filesystem::path & input, const std::filesystem::path & output) const - { - auto configuration = loadConfiguration(input); - auto units = loadUnits(configuration); - auto outputh = std::filesystem::path(output).replace_extension(".h"); - applyDefaults(configuration, units); + void + RouteCompiler::compile(const std::filesystem::path & input, const std::filesystem::path & output) const + { + auto configuration = loadConfiguration(input); + auto units = loadUnits(configuration); + auto outputh = std::filesystem::path(output).replace_extension(".h"); + applyDefaults(configuration, units); + + AdHoc::ScopeExit uDestroy([&units]() { + for (auto & u : units) { + u.second->destroy(); + } + }); + + using FilePtr = std::unique_ptr; + const auto out = FilePtr {fopen(output.c_str(), "w"), &fclose}; + const auto outh = FilePtr {fopen(outputh.c_str(), "w"), &fclose}; + if (!out || !outh) { + throw std::runtime_error("Failed to open output files"); + } + AdHoc::ScopeExit outClose(nullptr, nullptr, [&output, &outputh]() { + std::filesystem::remove(output); + std::filesystem::remove(outputh); + }); + processConfiguration(out.get(), outh.get(), output.stem().string(), configuration, units); + } - AdHoc::ScopeExit uDestroy([&units]() { - for (auto & u : units) { - u.second->destroy(); + RouteCompiler::Units + RouteCompiler::loadUnits(const RouteConfigurationPtr & c) const + { + RouteCompiler::Units units; + AdHoc::ScopeExit uDestroy; + for (const auto & slice : c->slices) { + std::filesystem::path realSlice; + for (const auto & p : searchPath) { + if (std::filesystem::exists(p / slice)) { + realSlice = p / slice; + break; } - }); - - using FilePtr = std::unique_ptr; - const auto out = FilePtr {fopen(output.c_str(), "w"), &fclose}; - const auto outh = FilePtr {fopen(outputh.c_str(), "w"), &fclose}; - if (!out || !outh) { - throw std::runtime_error("Failed to open output files"); } - AdHoc::ScopeExit outClose(nullptr, nullptr, [&output, &outputh]() { - std::filesystem::remove(output); - std::filesystem::remove(outputh); - }); - processConfiguration(out.get(), outh.get(), output.stem().string(), configuration, units); - } - - RouteCompiler::Units - RouteCompiler::loadUnits(const RouteConfigurationPtr & c) const - { - RouteCompiler::Units units; - AdHoc::ScopeExit uDestroy; - for (const auto & slice : c->slices) { - std::filesystem::path realSlice; - for (const auto & p : searchPath) { - if (std::filesystem::exists(p / slice)) { - realSlice = p / slice; - break; - } - } - if (realSlice.empty()) { - throw std::runtime_error("Could not find slice file"); - } - std::vector cppArgs; - for (const auto & p : searchPath) { - cppArgs.emplace_back("-I"); - cppArgs.emplace_back(p.string()); - } - Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("IceSpider", realSlice.string(), cppArgs); - FILE * cppHandle = icecpp->preprocess(false); - - if (!cppHandle) { - throw std::runtime_error("Preprocess failed"); - } - - Slice::UnitPtr u = Slice::Unit::createUnit(false, false, false, false); - uDestroy.onFailure.emplace_back([u]() { - u->destroy(); - }); + if (realSlice.empty()) { + throw std::runtime_error("Could not find slice file"); + } + std::vector cppArgs; + for (const auto & p : searchPath) { + cppArgs.emplace_back("-I"); + cppArgs.emplace_back(p.string()); + } + Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("IceSpider", realSlice.string(), cppArgs); + FILE * cppHandle = icecpp->preprocess(false); - int parseStatus = u->parse(realSlice.string(), cppHandle, false); + if (!cppHandle) { + throw std::runtime_error("Preprocess failed"); + } - if (!icecpp->close()) { - throw std::runtime_error("Preprocess close failed"); - } + Slice::UnitPtr u = Slice::Unit::createUnit(false, false, false, false); + uDestroy.onFailure.emplace_back([u]() { + u->destroy(); + }); - if (parseStatus == EXIT_FAILURE) { - throw std::runtime_error("Unit parse failed"); - } + int parseStatus = u->parse(realSlice.string(), cppHandle, false); - units[slice] = u; + if (!icecpp->close()) { + throw std::runtime_error("Preprocess close failed"); } - return units; - } - template - void - fprintbf(unsigned int indent, FILE * output, const X &... x) - { - for (; indent > 0; --indent) { - fputc('\t', output); + if (parseStatus == EXIT_FAILURE) { + throw std::runtime_error("Unit parse failed"); } - // NOLINTNEXTLINE(hicpp-no-array-decay) - fprintbf(output, x...); - } - template - std::string - getEnumString(Enum & e) - { - return Slicer::ModelPartForEnum::lookup(e); + units[slice] = u; } + return units; + } - static std::string - outputSerializerClass(const IceSpider::OutputSerializers::value_type & os) - { - return boost::algorithm::replace_all_copy(os.second->serializer, ".", "::"); + template + void + fprintbf(unsigned int indent, FILE * output, const X &... x) + { + for (; indent > 0; --indent) { + fputc('\t', output); } + // NOLINTNEXTLINE(hicpp-no-array-decay) + fprintbf(output, x...); + } - AdHocFormatter(MimePair, R"C({ "%?", "%?" })C"); + template + std::string + getEnumString(Enum & e) + { + return Slicer::ModelPartForEnum::lookup(e); + } - static std::string - outputSerializerMime(const IceSpider::OutputSerializers::value_type & os) - { - auto slash = os.first.find('/'); - return MimePair::get(os.first.substr(0, slash), os.first.substr(slash + 1)); - } + static std::string + outputSerializerClass(const IceSpider::OutputSerializers::value_type & os) + { + return boost::algorithm::replace_all_copy(os.second->serializer, ".", "::"); + } - void - RouteCompiler::registerOutputSerializers(FILE * output, const RoutePtr & r) const - { - 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()) { - fputs(", ", output); - } - fputs(p->c_str(), output); + AdHocFormatter(MimePair, R"C({ "%?", "%?" })C"); + + static std::string + outputSerializerMime(const IceSpider::OutputSerializers::value_type & os) + { + auto slash = os.first.find('/'); + return MimePair::get(os.first.substr(0, slash), os.first.substr(slash + 1)); + } + + void + RouteCompiler::registerOutputSerializers(FILE * output, const RoutePtr & r) const + { + 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()) { + fputs(", ", output); } - fputs("));\n", output); + fputs(p->c_str(), output); } + fputs("));\n", output); } + } - void - RouteCompiler::processConfiguration(FILE * output, FILE * outputh, const std::string & name, - const RouteConfigurationPtr & c, const Units & units) const - { - fputs("// This source files was generated by IceSpider.\n", output); - fprintbf(output, "// Configuration name: %s\n\n", c->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); - - fputs("// Configuration headers.\n", output); - fprintbf(output, "#include \"%s.h\"\n", name); + void + RouteCompiler::processConfiguration(FILE * output, FILE * outputh, const std::string & name, + const RouteConfigurationPtr & c, const Units & units) const + { + fputs("// This source files was generated by IceSpider.\n", output); + fprintbf(output, "// Configuration name: %s\n\n", c->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); + + 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); + slicePath.replace_extension(".h"); + fprintbf(output, "#include <%s>\n", slicePath.string()); + fprintbf(outputh, "#include <%s>\n", slicePath.string()); + } - fputs("\n// Interface headers.\n", output); - fputs("\n// Interface headers.\n", outputh); - for (const auto & s : c->slices) { - std::filesystem::path slicePath(s); - slicePath.replace_extension(".h"); - fprintbf(output, "#include <%s>\n", slicePath.string()); - fprintbf(outputh, "#include <%s>\n", slicePath.string()); - } + fputs("\n// Standard headers.\n", outputh); + fputs("namespace IceSpider {\n", outputh); + fputs("\tclass Core; // IWYU pragma: keep\n", outputh); + fputs("\tclass IHttpRequest; // IWYU pragma: keep\n", outputh); + fputs("}\n", outputh); + + fputs("// Standard headers.\n", output); + for (const auto header : { + "core.h", + "irouteHandler.h", + "Ice/Config.h", + "Ice/Exception.h", + "Ice/Proxy.h", + "future", + "ios", + "memory", + "string", + "string_view", + "factory.h", + "http.h", + "ihttpRequest.h", + "util.h", + }) { + fprintbf(output, "#include <%s>\n", header); + } - fputs("\n// Standard headers.\n", outputh); - fputs("namespace IceSpider {\n", outputh); - fputs("\tclass Core; // IWYU pragma: keep\n", outputh); - fputs("\tclass IHttpRequest; // IWYU pragma: keep\n", outputh); - fputs("}\n", outputh); - - fputs("// Standard headers.\n", output); - for (const auto header : { - "core.h", - "irouteHandler.h", - "Ice/Config.h", - "Ice/Exception.h", - "Ice/Proxy.h", - "future", - "ios", - "memory", - "string", - "string_view", - "factory.h", - "http.h", - "ihttpRequest.h", - "util.h", - }) { - fprintbf(output, "#include <%s>\n", header); + if (!c->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); } + } - if (!c->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); - } - } + processBases(output, outputh, c, units); + processRoutes(output, c, units); - processBases(output, outputh, c, units); - processRoutes(output, c, units); + fputs("\n// End generated code.\n", output); + } - fputs("\n// End generated code.\n", output); + void + RouteCompiler::processBases(FILE * output, FILE * outputh, const RouteConfigurationPtr & c, const Units & u) const + { + fputs("\n", outputh); + fprintbf(outputh, "namespace %s {\n", c->name); + fprintbf(1, outputh, "// Base classes.\n\n"); + fputs("\n", output); + fprintbf(output, "namespace %s {\n", c->name); + fprintbf(1, output, "// Base classes.\n\n"); + for (const auto & r : c->routeBases) { + processBase(output, outputh, r, u); } + fprintbf(output, "} // namespace %s\n\n", c->name); + fprintbf(outputh, "} // namespace %s\n\n", c->name); + } - void - RouteCompiler::processBases( - FILE * output, FILE * outputh, const RouteConfigurationPtr & c, const Units & u) const - { - fputs("\n", outputh); - fprintbf(outputh, "namespace %s {\n", c->name); - fprintbf(1, outputh, "// Base classes.\n\n"); - fputs("\n", output); - fprintbf(output, "namespace %s {\n", c->name); - fprintbf(1, output, "// Base classes.\n\n"); - for (const auto & r : c->routeBases) { - processBase(output, outputh, r, u); - } - fprintbf(output, "} // namespace %s\n\n", c->name); - fprintbf(outputh, "} // namespace %s\n\n", c->name); - } - - void - RouteCompiler::processBase(FILE * output, FILE * outputh, const RouteBases::value_type & b, const Units &) const - { - fprintbf(1, outputh, "class %s {\n", b.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(1, output, "%s::%s(const IceSpider::Core * core)", b.first, b.first); - if (!b.second->proxies.empty()) { - fputs(" :", output); + void + RouteCompiler::processBase(FILE * output, FILE * outputh, const RouteBases::value_type & b, const Units &) const + { + fprintbf(1, outputh, "class %s {\n", b.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(1, output, "%s::%s(const IceSpider::Core * core)", b.first, b.first); + if (!b.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()) { + 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()) { - fputs(",", output); - } - fputs("\n", output); - } - fprintbf(1, outputh, "}; // %s\n", b.first); - fprintbf(1, output, "{ }\n"); } + fprintbf(1, outputh, "}; // %s\n", b.first); + fprintbf(1, output, "{ }\n"); + } - void - RouteCompiler::processRoutes(FILE * output, const RouteConfigurationPtr & c, const Units & u) const - { - fputs("\n", output); - fprintbf(output, "namespace %s {\n", c->name); - fprintbf(1, output, "// Implementation classes.\n\n"); - for (const auto & r : c->routes) { - processRoute(output, r, u); - } - fprintbf(output, "} // namespace %s\n\n", c->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); - } + void + RouteCompiler::processRoutes(FILE * output, const RouteConfigurationPtr & c, const Units & u) const + { + fputs("\n", output); + fprintbf(output, "namespace %s {\n", c->name); + fprintbf(1, output, "// Implementation classes.\n\n"); + for (const auto & r : c->routes) { + processRoute(output, r, u); } + fprintbf(output, "} // namespace %s\n\n", c->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); + } + } - void - RouteCompiler::processRoute(FILE * output, const Routes::value_type & r, const Units & units) const - { - std::string methodName = getEnumString(r.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) { - fputs(",\n", output); - fprintbf(3, output, "public %s", b); - } - 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) { - fputs(",\n", output); - fprintbf(4, output, "%s(core)", b); - } - auto proxies = initializeProxies(output, r.second); - fputs("\n", output); - fprintbf(3, output, "{\n"); - registerOutputSerializers(output, r.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); - 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());\n"); - } - doneBody = true; - } + void + RouteCompiler::processRoute(FILE * output, const Routes::value_type & r, const Units & units) const + { + std::string methodName = getEnumString(r.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) { + fputs(",\n", output); + fprintbf(3, output, "public %s", b); + } + 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) { + fputs(",\n", output); + fprintbf(4, output, "%s(core)", b); + } + auto proxies = initializeProxies(output, r.second); + fputs("\n", output); + fprintbf(3, output, "{\n"); + registerOutputSerializers(output, r.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); + 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 _p_%s(_pbody->%s", p.first, p.first); + fprintbf(4, output, "const auto _pbody(request->getBody<%s>());\n", *p.second->type); } else { - fprintbf(4, output, "const auto _p_%s(request->getBodyParam<%s>(_pbody, _pn_%s)", - p.first, paramType, p.first); + fprintbf(4, output, "const auto _pbody(request->getBody());\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->getBody<%s>()", p.first, paramType); + 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->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->getBody<%s>()", p.first, paramType); } - if (!p.second->isOptional && p.second->source != ParameterSource::URL) { - fprintbf(0, output, " /\n"); - if (p.second->defaultExpr) { - fprintbf(5, output, " [this]() { return _pd_%s; }", p.first); - } - else { - fprintbf(5, output, " [this]() { return requiredParameterNotFound<%s>(\"%s\", _pn_%s); }", - paramType, getEnumString(p.second->source), p.first); - } + } + 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); + } + if (!p.second->isOptional && p.second->source != ParameterSource::URL) { + fprintbf(0, output, " /\n"); + if (p.second->defaultExpr) { + fprintbf(5, output, " [this]() { return _pd_%s; }", p.first); + } + else { + fprintbf(5, output, " [this]() { return requiredParameterNotFound<%s>(\"%s\", _pn_%s); }", + paramType, getEnumString(p.second->source), p.first); } - fprintbf(0, output, ");\n"); } + fprintbf(0, output, ");\n"); } - if (r.second->operation) { - addSingleOperation(output, r.second, findOperation(*r.second->operation, units)); - } - else { - addMashupOperations(output, r.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); - long idx = -1; - for (const auto & pp : path.parts) { - if (auto par = dynamic_cast(pp.get())) { - if (par->name == *p.second->key) { - idx = &pp - &path.parts.front(); - } + } + if (r.second->operation) { + addSingleOperation(output, r.second, findOperation(*r.second->operation, units)); + } + else { + addMashupOperations(output, r.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); + long idx = -1; + for (const auto & pp : path.parts) { + if (auto par = dynamic_cast(pp.get())) { + if (par->name == *p.second->key) { + idx = &pp - &path.parts.front(); } } - fprintbf(3, output, "static constexpr unsigned int _pi_%s{%ld};\n", p.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); - } - fputs("};\n", output); } + fprintbf(3, output, "static constexpr unsigned int _pi_%s{%ld};\n", p.first, idx); } - 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); + else { + fprintbf(3, output, "static constexpr std::string_view _pn_%s{", p.first); + if (p.second->key) { + fprintbf(output, "\"%s\"", *p.second->key); + } + fputs("};\n", output); } } - fprintbf(1, output, "};\n\n"); + 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); + } } + fprintbf(1, output, "};\n\n"); + } - RouteCompiler::Proxies - RouteCompiler::initializeProxies(FILE * output, const RoutePtr & r) const - { - 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; - fputs(",\n", output); - fprintbf(4, output, "prx%d(core->getProxy<%s>())", n, - boost::algorithm::replace_all_copy(proxyName, ".", "::")); - n += 1; - } + RouteCompiler::Proxies + RouteCompiler::initializeProxies(FILE * output, const RoutePtr & r) const + { + 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; + fputs(",\n", output); + fprintbf(4, output, "prx%d(core->getProxy<%s>())", n, + boost::algorithm::replace_all_copy(proxyName, ".", "::")); + n += 1; } - return proxies; } + return proxies; + } - void - RouteCompiler::declareProxies(FILE * output, const Proxies & proxies) const - { - for (const auto & p : proxies) { - fprintbf(3, output, "const %sPrxPtr prx%d;\n", boost::algorithm::replace_all_copy(p.first, ".", "::"), - p.second); - } + void + RouteCompiler::declareProxies(FILE * output, const Proxies & proxies) const + { + for (const auto & p : proxies) { + fprintbf(3, output, "const %sPrxPtr prx%d;\n", boost::algorithm::replace_all_copy(p.first, ".", "::"), + p.second); } + } - void - RouteCompiler::addSingleOperation(FILE * output, const RoutePtr & r, const Slice::OperationPtr & o) const - { - auto operation = r->operation->substr(r->operation->find_last_of('.') + 1); - if (o->returnType()) { - fprintbf(4, output, "auto _responseModel = prx0->%s(", operation); + void + RouteCompiler::addSingleOperation(FILE * output, const RoutePtr & r, const Slice::OperationPtr & o) const + { + auto operation = r->operation->substr(r->operation->find_last_of('.') + 1); + if (o->returnType()) { + fprintbf(4, output, "auto _responseModel = prx0->%s(", operation); + } + else { + fprintbf(4, output, "prx0->%s(", operation); + } + for (const auto & p : o->parameters()) { + auto rp = *r->params.find(p->name()); + if (rp.second->hasUserSource) { + fprintbf(output, "_p_%s, ", p->name()); } else { - fprintbf(4, output, "prx0->%s(", operation); + fprintbf(output, "_pd_%s, ", p->name()); } - for (const auto & p : o->parameters()) { - auto rp = *r->params.find(p->name()); + } + fprintbf(output, "request->getContext());\n"); + for (const auto & mutator : r->mutators) { + fprintbf(4, output, "%s(request, _responseModel);\n", mutator); + } + if (o->returnType()) { + fprintbf(4, output, "request->response(this, _responseModel);\n"); + } + else { + fprintbf(4, output, "request->response(200, \"OK\");\n"); + } + } + + void + RouteCompiler::addMashupOperations( + FILE * output, const RoutePtr & r, const Proxies & proxies, const Units & us) const + { + 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()); } @@ -595,66 +619,33 @@ namespace IceSpider { } } fprintbf(output, "request->getContext());\n"); - for (const auto & mutator : r->mutators) { - fprintbf(4, output, "%s(request, _responseModel);\n", mutator); - } - if (o->returnType()) { - fprintbf(4, output, "request->response(this, _responseModel);\n"); - } - else { - fprintbf(4, output, "request->response(200, \"OK\");\n"); - } } - - void - RouteCompiler::addMashupOperations( - FILE * output, const RoutePtr & r, const Proxies & proxies, const Units & us) const - { + 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); + } + fprintbf(4, output, ";\n"); + for (const auto & mi : t.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); - 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()); - } - else { - fprintbf(output, "_pd_%s, ", p->name()); - } + if (mi->name() == o.first) { + fprintbf(output, "_ar_%s.get()", o.first); + isOp = true; + break; } - 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); + if (!isOp) { + fprintbf(output, "_p_%s", mi->name()); } - fprintbf(4, output, ";\n"); - for (const auto & mi : t.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); - isOp = true; - break; - } - } - if (!isOp) { - fprintbf(output, "_p_%s", mi->name()); - } - fputs(";\n", output); - } - for (const auto & mutator : r->mutators) { - fprintbf(4, output, "%s(request, _responseModel);\n", mutator); - } - fprintbf(4, output, "request->response(this, _responseModel);\n"); + fputs(";\n", output); + } + for (const auto & mutator : r->mutators) { + fprintbf(4, output, "%s(request, _responseModel);\n", mutator); } + fprintbf(4, output, "request->response(this, _responseModel);\n"); } } -- cgit v1.2.3