<commit_before>#include "filename-parser-test.h"
#include <QMap>
#include <QString>
#include <QtTest>
#include "filename/filename-parser.h"
#include "filename/ast/filename-node-conditional.h"
#include "filename/ast/filename-node-condition-invert.h"
#include "filename/ast/filename-node-condition-op.h"
#include "filename/ast/filename-node-condition-tag.h"
#include "filename/ast/filename-node-condition-token.h"
#include "filename/ast/filename-node-root.h"
#include "filename/ast/filename-node-text.h"
#include "filename/ast/filename-node-variable.h"

void FilenameParserTest::testParseText()
{
	FilenameParser parser("image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto txt = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt != nullptr);
	QCOMPARE(txt->text, QString("image.png"));
}

void FilenameParserTest::testParseVariable()
{
	FilenameParser parser("%md5%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto var = dynamic_cast<FilenameNodeVariable*>(filename->exprs[0]);
	QVERIFY(var != nullptr);
	QCOMPARE(var->name, QString("md5"));
	QCOMPARE(var->opts.count(), 0);
}

void FilenameParserTest::testParseVariableWithOptions()
{
	FilenameParser parser("%md5:flag,opt=val%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto var = dynamic_cast<FilenameNodeVariable*>(filename->exprs[0]);
	QVERIFY(var != nullptr);
	QCOMPARE(var->name, QString("md5"));
	QCOMPARE(var->opts.count(), 2);
	QCOMPARE(var->opts.keys(), QStringList() << "flag" << "opt");
	QCOMPARE(var->opts["flag"], QString());
	QCOMPARE(var->opts["opt"], QString("val"));
}

void FilenameParserTest::testParseMixed()
{
	FilenameParser parser("out/%md5%.%ext%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 4);
}

void FilenameParserTest::testParseConditional()
{
	FilenameParser parser("out/<\"tag\"?some tag is present:%artist%>/image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 3);

	auto txt1 = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt1 != nullptr);
	QCOMPARE(txt1->text, QString("out/"));

	auto conditional = dynamic_cast<FilenameNodeConditional*>(filename->exprs[1]);
	QVERIFY(conditional != nullptr);
	QVERIFY(conditional->ifTrue != nullptr);
	QVERIFY(conditional->ifFalse != nullptr);

	auto cond = dynamic_cast<FilenameNodeConditionTag*>(conditional->condition);
	QVERIFY(cond != nullptr);
	QCOMPARE(cond->tag.text(), QString("tag"));

	auto ifTrue = dynamic_cast<FilenameNodeText*>(conditional->ifTrue);
	QVERIFY(ifTrue != nullptr);
	QCOMPARE(ifTrue->text, QString("some tag is present"));

	auto ifFalse = dynamic_cast<FilenameNodeVariable*>(conditional->ifFalse);
	QVERIFY(ifFalse != nullptr);
	QCOMPARE(ifFalse->name, QString("artist"));

	auto txt2 = dynamic_cast<FilenameNodeText*>(filename->exprs[2]);
	QVERIFY(txt2 != nullptr);
	QCOMPARE(txt2->text, QString("/image.png"));
}

void FilenameParserTest::testParseConditionalLegacy()
{
	FilenameParser parser("out/<some \"tag\" is present/>image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 3);

	auto txt1 = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt1 != nullptr);
	QCOMPARE(txt1->text, QString("out/"));

	auto conditional = dynamic_cast<FilenameNodeConditional*>(filename->exprs[1]);
	QVERIFY(conditional != nullptr);
	QVERIFY(conditional->ifTrue != nullptr);
	QVERIFY(conditional->ifFalse == nullptr);

	auto cond = dynamic_cast<FilenameNodeConditionTag*>(conditional->condition);
	QVERIFY(cond != nullptr);
	QCOMPARE(cond->tag.text(), QString("tag"));

	auto ifTrue = dynamic_cast<FilenameNodeRoot*>(conditional->ifTrue);
	QVERIFY(ifTrue != nullptr);
	QCOMPARE(ifTrue->exprs.count(), 3);

	auto ifTrue1 = dynamic_cast<FilenameNodeText*>(ifTrue->exprs[0]);
	QVERIFY(ifTrue1 != nullptr);
	QCOMPARE(ifTrue1->text, QString("some "));

	auto ifTrue2 = dynamic_cast<FilenameNodeConditionTag*>(ifTrue->exprs[1]);
	QVERIFY(ifTrue2 != nullptr);
	QCOMPARE(ifTrue2->tag.text(), QString("tag"));

	auto ifTrue3 = dynamic_cast<FilenameNodeText*>(ifTrue->exprs[2]);
	QVERIFY(ifTrue3 != nullptr);
	QCOMPARE(ifTrue3->text, QString(" is present/"));

	auto txt2 = dynamic_cast<FilenameNodeText*>(filename->exprs[2]);
	QVERIFY(txt2 != nullptr);
	QCOMPARE(txt2->text, QString("image.png"));
}

void FilenameParserTest::testParseConditionTag()
{
	FilenameParser parser("\"my_tag\"");
	auto cond = parser.parseCondition();

	auto tagCond = dynamic_cast<FilenameNodeConditionTag*>(cond);
	QVERIFY(tagCond != nullptr);
	QCOMPARE(tagCond->tag.text(), QString("my_tag"));
}

void FilenameParserTest::testParseConditionToken()
{
	FilenameParser parser("%my_token%");
	auto cond = parser.parseCondition();

	auto tokenCond = dynamic_cast<FilenameNodeConditionToken*>(cond);
	QVERIFY(tokenCond != nullptr);
	QCOMPARE(tokenCond->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionInvert()
{
	FilenameParser parser("!%my_token%");
	auto cond = parser.parseCondition();

	auto invertCond = dynamic_cast<FilenameNodeConditionInvert*>(cond);
	QVERIFY(invertCond != nullptr);

	auto tokenCond = dynamic_cast<FilenameNodeConditionToken*>(invertCond->node);
	QVERIFY(tokenCond != nullptr);
	QCOMPARE(tokenCond->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionOperator()
{
	FilenameParser parser("\"my_tag\" & %my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::And);

	auto left = dynamic_cast<FilenameNodeConditionTag*>(opCond->left);
	QVERIFY(left != nullptr);
	QCOMPARE(left->tag.text(), QString("my_tag"));

	auto right = dynamic_cast<FilenameNodeConditionToken*>(opCond->right);
	QVERIFY(right != nullptr);
	QCOMPARE(right->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionMixedOperators()
{
	FilenameParser parser("\"my_tag\" | %some_token% & !%my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::Or);

	auto right = dynamic_cast<FilenameNodeConditionOp*>(opCond->right);
	QVERIFY(right != nullptr);
	QCOMPARE(right->op, FilenameNodeConditionOp::Operator::And);

	auto invert = dynamic_cast<FilenameNodeConditionInvert*>(right->right);
	QVERIFY(invert != nullptr);
}

void FilenameParserTest::testParseConditionTagParenthesis()
{
	FilenameParser parser("(\"my_tag\")");
	auto cond = parser.parseCondition();

	auto tagCond = dynamic_cast<FilenameNodeConditionTag*>(cond);
	QVERIFY(tagCond != nullptr);
	QCOMPARE(tagCond->tag.text(), QString("my_tag"));
}

void FilenameParserTest::testParseConditionMixedParenthesis()
{
	FilenameParser parser("(\"my_tag\" | %some_token%) & %my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::And);

	auto right = dynamic_cast<FilenameNodeConditionOp*>(opCond->left);
	QVERIFY(right != nullptr);
	QCOMPARE(right->op, FilenameNodeConditionOp::Operator::Or);
}

QTEST_MAIN(FilenameParserTest)
<commit_msg>Fix GCC qCompare between QList<QString> and QStringList<commit_after>#include "filename-parser-test.h"
#include <QMap>
#include <QString>
#include <QtTest>
#include "filename/filename-parser.h"
#include "filename/ast/filename-node-conditional.h"
#include "filename/ast/filename-node-condition-invert.h"
#include "filename/ast/filename-node-condition-op.h"
#include "filename/ast/filename-node-condition-tag.h"
#include "filename/ast/filename-node-condition-token.h"
#include "filename/ast/filename-node-root.h"
#include "filename/ast/filename-node-text.h"
#include "filename/ast/filename-node-variable.h"

void FilenameParserTest::testParseText()
{
	FilenameParser parser("image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto txt = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt != nullptr);
	QCOMPARE(txt->text, QString("image.png"));
}

void FilenameParserTest::testParseVariable()
{
	FilenameParser parser("%md5%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto var = dynamic_cast<FilenameNodeVariable*>(filename->exprs[0]);
	QVERIFY(var != nullptr);
	QCOMPARE(var->name, QString("md5"));
	QCOMPARE(var->opts.count(), 0);
}

void FilenameParserTest::testParseVariableWithOptions()
{
	FilenameParser parser("%md5:flag,opt=val%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 1);

	auto var = dynamic_cast<FilenameNodeVariable*>(filename->exprs[0]);
	QVERIFY(var != nullptr);
	QCOMPARE(var->name, QString("md5"));
	QCOMPARE(var->opts.count(), 2);
	QCOMPARE(var->opts.keys(), QList<QString>() << "flag" << "opt");
	QCOMPARE(var->opts["flag"], QString());
	QCOMPARE(var->opts["opt"], QString("val"));
}

void FilenameParserTest::testParseMixed()
{
	FilenameParser parser("out/%md5%.%ext%");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 4);
}

void FilenameParserTest::testParseConditional()
{
	FilenameParser parser("out/<\"tag\"?some tag is present:%artist%>/image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 3);

	auto txt1 = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt1 != nullptr);
	QCOMPARE(txt1->text, QString("out/"));

	auto conditional = dynamic_cast<FilenameNodeConditional*>(filename->exprs[1]);
	QVERIFY(conditional != nullptr);
	QVERIFY(conditional->ifTrue != nullptr);
	QVERIFY(conditional->ifFalse != nullptr);

	auto cond = dynamic_cast<FilenameNodeConditionTag*>(conditional->condition);
	QVERIFY(cond != nullptr);
	QCOMPARE(cond->tag.text(), QString("tag"));

	auto ifTrue = dynamic_cast<FilenameNodeText*>(conditional->ifTrue);
	QVERIFY(ifTrue != nullptr);
	QCOMPARE(ifTrue->text, QString("some tag is present"));

	auto ifFalse = dynamic_cast<FilenameNodeVariable*>(conditional->ifFalse);
	QVERIFY(ifFalse != nullptr);
	QCOMPARE(ifFalse->name, QString("artist"));

	auto txt2 = dynamic_cast<FilenameNodeText*>(filename->exprs[2]);
	QVERIFY(txt2 != nullptr);
	QCOMPARE(txt2->text, QString("/image.png"));
}

void FilenameParserTest::testParseConditionalLegacy()
{
	FilenameParser parser("out/<some \"tag\" is present/>image.png");
	auto filename = parser.parseRoot();

	QCOMPARE(filename->exprs.count(), 3);

	auto txt1 = dynamic_cast<FilenameNodeText*>(filename->exprs[0]);
	QVERIFY(txt1 != nullptr);
	QCOMPARE(txt1->text, QString("out/"));

	auto conditional = dynamic_cast<FilenameNodeConditional*>(filename->exprs[1]);
	QVERIFY(conditional != nullptr);
	QVERIFY(conditional->ifTrue != nullptr);
	QVERIFY(conditional->ifFalse == nullptr);

	auto cond = dynamic_cast<FilenameNodeConditionTag*>(conditional->condition);
	QVERIFY(cond != nullptr);
	QCOMPARE(cond->tag.text(), QString("tag"));

	auto ifTrue = dynamic_cast<FilenameNodeRoot*>(conditional->ifTrue);
	QVERIFY(ifTrue != nullptr);
	QCOMPARE(ifTrue->exprs.count(), 3);

	auto ifTrue1 = dynamic_cast<FilenameNodeText*>(ifTrue->exprs[0]);
	QVERIFY(ifTrue1 != nullptr);
	QCOMPARE(ifTrue1->text, QString("some "));

	auto ifTrue2 = dynamic_cast<FilenameNodeConditionTag*>(ifTrue->exprs[1]);
	QVERIFY(ifTrue2 != nullptr);
	QCOMPARE(ifTrue2->tag.text(), QString("tag"));

	auto ifTrue3 = dynamic_cast<FilenameNodeText*>(ifTrue->exprs[2]);
	QVERIFY(ifTrue3 != nullptr);
	QCOMPARE(ifTrue3->text, QString(" is present/"));

	auto txt2 = dynamic_cast<FilenameNodeText*>(filename->exprs[2]);
	QVERIFY(txt2 != nullptr);
	QCOMPARE(txt2->text, QString("image.png"));
}

void FilenameParserTest::testParseConditionTag()
{
	FilenameParser parser("\"my_tag\"");
	auto cond = parser.parseCondition();

	auto tagCond = dynamic_cast<FilenameNodeConditionTag*>(cond);
	QVERIFY(tagCond != nullptr);
	QCOMPARE(tagCond->tag.text(), QString("my_tag"));
}

void FilenameParserTest::testParseConditionToken()
{
	FilenameParser parser("%my_token%");
	auto cond = parser.parseCondition();

	auto tokenCond = dynamic_cast<FilenameNodeConditionToken*>(cond);
	QVERIFY(tokenCond != nullptr);
	QCOMPARE(tokenCond->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionInvert()
{
	FilenameParser parser("!%my_token%");
	auto cond = parser.parseCondition();

	auto invertCond = dynamic_cast<FilenameNodeConditionInvert*>(cond);
	QVERIFY(invertCond != nullptr);

	auto tokenCond = dynamic_cast<FilenameNodeConditionToken*>(invertCond->node);
	QVERIFY(tokenCond != nullptr);
	QCOMPARE(tokenCond->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionOperator()
{
	FilenameParser parser("\"my_tag\" & %my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::And);

	auto left = dynamic_cast<FilenameNodeConditionTag*>(opCond->left);
	QVERIFY(left != nullptr);
	QCOMPARE(left->tag.text(), QString("my_tag"));

	auto right = dynamic_cast<FilenameNodeConditionToken*>(opCond->right);
	QVERIFY(right != nullptr);
	QCOMPARE(right->token, QString("my_token"));
}

void FilenameParserTest::testParseConditionMixedOperators()
{
	FilenameParser parser("\"my_tag\" | %some_token% & !%my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::Or);

	auto right = dynamic_cast<FilenameNodeConditionOp*>(opCond->right);
	QVERIFY(right != nullptr);
	QCOMPARE(right->op, FilenameNodeConditionOp::Operator::And);

	auto invert = dynamic_cast<FilenameNodeConditionInvert*>(right->right);
	QVERIFY(invert != nullptr);
}

void FilenameParserTest::testParseConditionTagParenthesis()
{
	FilenameParser parser("(\"my_tag\")");
	auto cond = parser.parseCondition();

	auto tagCond = dynamic_cast<FilenameNodeConditionTag*>(cond);
	QVERIFY(tagCond != nullptr);
	QCOMPARE(tagCond->tag.text(), QString("my_tag"));
}

void FilenameParserTest::testParseConditionMixedParenthesis()
{
	FilenameParser parser("(\"my_tag\" | %some_token%) & %my_token%");
	auto cond = parser.parseCondition();

	auto opCond = dynamic_cast<FilenameNodeConditionOp*>(cond);
	QVERIFY(opCond != nullptr);
	QCOMPARE(opCond->op, FilenameNodeConditionOp::Operator::And);

	auto right = dynamic_cast<FilenameNodeConditionOp*>(opCond->left);
	QVERIFY(right != nullptr);
	QCOMPARE(right->op, FilenameNodeConditionOp::Operator::Or);
}

QTEST_MAIN(FilenameParserTest)
<|endoftext|>


<commit_before>/*
 * SessionPanmirrorCrossref.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionPanmirrorCrossref.hpp"

#include <shared_core/Error.hpp>
#include <shared_core/json/Json.hpp>

#include <core/Exec.hpp>
#include <core/json/JsonRpc.hpp>
#include <core/http/Util.hpp>

#include <r/ROptions.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionAsyncDownloadFile.hpp>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace panmirror {
namespace crossref {

namespace {

void crossrefContentRequestHandler(const core::json::Value& value, core::json::JsonRpcResponse* pResponse)
{
   pResponse->setResult(value);
}

void crossrefApiRequestHandler(const core::json::Value& value, core::json::JsonRpcResponse* pResponse)
{
   if (json::isType<json::Object>(value))
   {
      json::Object responseJson = value.getObject();
      std::string status;
      json::Object message;
      Error error = json::readObject(responseJson, "status", status,
                                                   "message", message);
      if (error)
      {
         json::setErrorResponse(error, pResponse);
      }
      else if (status != "ok")
      {
         Error error = systemError(boost::system::errc::state_not_recoverable,
                                   "Unexpected status from crossref api: " + status,
                                   ERROR_LOCATION);
         json::setErrorResponse(error, pResponse);
      }
      else
      {
         pResponse->setResult(message);
      }
   }
   else
   {
      Error error = systemError(boost::system::errc::state_not_recoverable,
                                "Unexpected response from crossref api",
                                ERROR_LOCATION);
      json::setErrorResponse(error, pResponse);
   }
}

void crossrefRequest(const std::string& resource,
                     const http::Fields& params,
                     const session::JsonRpcResponseHandler& handler,
                     const json::JsonRpcFunctionContinuation& cont)
{
   // build user agent
   std::string userAgent = r::options::getOption<std::string>("HTTPUserAgent", "RStudio") +
                           "; RStudio Crossref Cite (mailto:crossref@rstudio.com)";

   // build query string
   std::string queryString;
   core::http::util::buildQueryString(params, &queryString);
   if (queryString.length() > 0)
      queryString = "?" + queryString;

   // build the url and make the request
   boost::format fmt("%s/%s%s");
   const std::string url = boost::str(fmt % kCrossrefApiHost % resource % queryString);

   http::Fields headers;
   asyncJsonRpcRequest(url, userAgent, headers, handler, cont);
}

void crossrefWorks(const json::JsonRpcRequest& request,
                   const json::JsonRpcFunctionContinuation& cont)
{
   // extract query
   std::string query;
   Error error = json::readParams(request.params, &query);
   if (error)
   {
     json::JsonRpcResponse response;
     setErrorResponse(error, &response);
     cont(Success(), &response);
     return;
   }

   // build params
   core::http::Fields params;
   params.push_back(std::make_pair("query", query));

   // make the request
   crossrefRequest(kCrossrefWorks, params, crossrefApiRequestHandler, cont);
}

void crossrefDoi(const json::JsonRpcRequest& request,
                 const json::JsonRpcFunctionContinuation& cont)
{
    std::string doi;
    Error error = json::readParams(request.params, &doi);
    if (error)
    {
      json::JsonRpcResponse response;
      setErrorResponse(error, &response);
      cont(Success(), &response);
      return;
    }

    // Path to DOI metadata works/{doi}/transform/{format} (see: https://citation.crosscite.org/docs.html#sec-5)
    const char * const kCitationFormat = "application/vnd.citationstyles.csl+json";
    boost::format fmt("%s/%s/transform/%s");
    const std::string resourcePath = boost::str(fmt % kCrossrefWorks % doi % kCitationFormat);

    // No parameters
    core::http::Fields params;

    // make the request
    crossrefRequest(resourcePath, params, crossrefContentRequestHandler, cont);
}

} // end anonymous namespace

Error initialize()
{
   ExecBlock initBlock;
   initBlock.addFunctions()
      (boost::bind(module_context::registerAsyncRpcMethod, "crossref_works", crossrefWorks))
      (boost::bind(module_context::registerAsyncRpcMethod, "crossref_doi", crossrefDoi))
   ;
   return initBlock.execute();
}

} // end namespace crossref
} // end namespace panmirror
} // end namespace modules
} // end namespace session
} // end namespace rstudio
<commit_msg>ability to specify crossref email<commit_after>/*
 * SessionPanmirrorCrossref.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionPanmirrorCrossref.hpp"

#include <shared_core/Error.hpp>
#include <shared_core/json/Json.hpp>

#include <core/Exec.hpp>
#include <core/json/JsonRpc.hpp>
#include <core/http/Util.hpp>

#include <r/ROptions.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionAsyncDownloadFile.hpp>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace panmirror {
namespace crossref {

namespace {

void crossrefContentRequestHandler(const core::json::Value& value, core::json::JsonRpcResponse* pResponse)
{
   pResponse->setResult(value);
}

void crossrefApiRequestHandler(const core::json::Value& value, core::json::JsonRpcResponse* pResponse)
{
   if (json::isType<json::Object>(value))
   {
      json::Object responseJson = value.getObject();
      std::string status;
      json::Object message;
      Error error = json::readObject(responseJson, "status", status,
                                                   "message", message);
      if (error)
      {
         json::setErrorResponse(error, pResponse);
      }
      else if (status != "ok")
      {
         Error error = systemError(boost::system::errc::state_not_recoverable,
                                   "Unexpected status from crossref api: " + status,
                                   ERROR_LOCATION);
         json::setErrorResponse(error, pResponse);
      }
      else
      {
         pResponse->setResult(message);
      }
   }
   else
   {
      Error error = systemError(boost::system::errc::state_not_recoverable,
                                "Unexpected response from crossref api",
                                ERROR_LOCATION);
      json::setErrorResponse(error, pResponse);
   }
}

void crossrefRequest(const std::string& resource,
                     const http::Fields& params,
                     const session::JsonRpcResponseHandler& handler,
                     const json::JsonRpcFunctionContinuation& cont)
{
   // email address
   std::string email = r::options::getOption<std::string>("rstudio.crossref_email",
                                                          "crossref@rstudio.com", false);

   // build user agent
   std::string userAgent = r::options::getOption<std::string>("HTTPUserAgent", "RStudio") +
                           "; RStudio Crossref Cite (mailto:" + email + ")";

   // build query string
   std::string queryString;
   core::http::util::buildQueryString(params, &queryString);
   if (queryString.length() > 0)
      queryString = "?" + queryString;

   // build the url and make the request
   boost::format fmt("%s/%s%s");
   const std::string url = boost::str(fmt % kCrossrefApiHost % resource % queryString);

   http::Fields headers;
   asyncJsonRpcRequest(url, userAgent, headers, handler, cont);
}

void crossrefWorks(const json::JsonRpcRequest& request,
                   const json::JsonRpcFunctionContinuation& cont)
{
   // extract query
   std::string query;
   Error error = json::readParams(request.params, &query);
   if (error)
   {
     json::JsonRpcResponse response;
     setErrorResponse(error, &response);
     cont(Success(), &response);
     return;
   }

   // build params
   core::http::Fields params;
   params.push_back(std::make_pair("query", query));

   // make the request
   crossrefRequest(kCrossrefWorks, params, crossrefApiRequestHandler, cont);
}

void crossrefDoi(const json::JsonRpcRequest& request,
                 const json::JsonRpcFunctionContinuation& cont)
{
    std::string doi;
    Error error = json::readParams(request.params, &doi);
    if (error)
    {
      json::JsonRpcResponse response;
      setErrorResponse(error, &response);
      cont(Success(), &response);
      return;
    }

    // Path to DOI metadata works/{doi}/transform/{format} (see: https://citation.crosscite.org/docs.html#sec-5)
    const char * const kCitationFormat = "application/vnd.citationstyles.csl+json";
    boost::format fmt("%s/%s/transform/%s");
    const std::string resourcePath = boost::str(fmt % kCrossrefWorks % doi % kCitationFormat);

    // No parameters
    core::http::Fields params;

    // make the request
    crossrefRequest(resourcePath, params, crossrefContentRequestHandler, cont);
}

} // end anonymous namespace

Error initialize()
{
   ExecBlock initBlock;
   initBlock.addFunctions()
      (boost::bind(module_context::registerAsyncRpcMethod, "crossref_works", crossrefWorks))
      (boost::bind(module_context::registerAsyncRpcMethod, "crossref_doi", crossrefDoi))
   ;
   return initBlock.execute();
}

} // end namespace crossref
} // end namespace panmirror
} // end namespace modules
} // end namespace session
} // end namespace rstudio
<|endoftext|>


<commit_before>#include "overlay.hpp"
#include "../proxy/mouse_proxy.hpp"

#include "../../context.hpp"
#include "size_container.hpp"

using namespace morda;

namespace{
class context_menu_wrapper : public size_container{
public:
	context_menu_wrapper(std::shared_ptr<morda::context> c, const puu::forest& desc) :
			widget(std::move(c), desc),
			size_container(this->context, desc)
	{}
};
}

overlay::overlay(std::shared_ptr<morda::context> c, const puu::forest& desc) :
		widget(std::move(c), desc),
		pile(this->context, desc)
{}

std::shared_ptr<widget> overlay::show_context_menu(std::shared_ptr<widget> w, vector2 anchor){
	auto c = std::make_shared<context_menu_wrapper>(this->context, puu::read(R"qwertyuiop(
		layout{
			dx{fill} dy{fill}
		}
		@mouse_proxy{
			layout{
				dx{fill} dy{fill}
			}
			x{0} y{0}
		}
	)qwertyuiop"));

	auto& mp = *std::dynamic_pointer_cast<mouse_proxy>(c->children().back());

	mp.mouse_button_handler = [](widget& w, bool is_down, const vector2& pos, mouse_button button, unsigned pointer_id) -> bool{
		ASSERT(w.parent())
		auto wsp = utki::make_shared_from_this(*w.parent());
		w.context->run_from_ui_thread([wsp](){
			wsp->remove_from_parent();
		});
		return false;
	};

	c->push_back(w);

	auto& lp = c->get_layout_params(*w);

	vector2 dim = this->dims_for_widget(*w, lp);

	for(unsigned i = 0; i != 2; ++i){
		utki::clampTop(dim[i], this->rect().d[i]);
	}

	w->resize(dim);

	for(unsigned i = 0; i != 2; ++i){
		utki::clampRange(anchor[i], 0.0f, this->rect().d[i] - w->rect().d[i]);
	}

	w->move_to(anchor);

	auto sp = utki::make_shared_from_this(*this);
	ASSERT(sp)
	this->context->run_from_ui_thread([this, c, sp](){
		sp->push_back(c);
	});

	return c;
}

void overlay::close_all_context_menus(){
	while(dynamic_cast<context_menu_wrapper*>(this->children().back().get())){
		this->pop_back();
	}
}
<commit_msg>macosx build fix<commit_after>#include "overlay.hpp"
#include "../proxy/mouse_proxy.hpp"

#include "../../context.hpp"
#include "size_container.hpp"

using namespace morda;

namespace{
class context_menu_wrapper : public size_container{
public:
	context_menu_wrapper(std::shared_ptr<morda::context> c, const puu::forest& desc) :
			widget(std::move(c), desc),
			size_container(this->context, desc)
	{}
};
}

overlay::overlay(std::shared_ptr<morda::context> c, const puu::forest& desc) :
		widget(std::move(c), desc),
		pile(this->context, desc)
{}

std::shared_ptr<widget> overlay::show_context_menu(std::shared_ptr<widget> w, vector2 anchor){
	auto c = std::make_shared<context_menu_wrapper>(this->context, puu::read(R"qwertyuiop(
		layout{
			dx{fill} dy{fill}
		}
		@mouse_proxy{
			layout{
				dx{fill} dy{fill}
			}
			x{0} y{0}
		}
	)qwertyuiop"));

	auto& mp = *std::dynamic_pointer_cast<mouse_proxy>(c->children().back());

	mp.mouse_button_handler = [](widget& w, bool is_down, const vector2& pos, mouse_button button, unsigned pointer_id) -> bool{
		ASSERT(w.parent())
		auto wsp = utki::make_shared_from_this(*w.parent());
		w.context->run_from_ui_thread([wsp](){
			wsp->remove_from_parent();
		});
		return false;
	};

	c->push_back(w);

	auto& lp = c->get_layout_params(*w);

	vector2 dim = this->dims_for_widget(*w, lp);

	for(unsigned i = 0; i != 2; ++i){
		utki::clampTop(dim[i], this->rect().d[i]);
	}

	w->resize(dim);

	for(unsigned i = 0; i != 2; ++i){
		utki::clampRange(anchor[i], 0.0f, this->rect().d[i] - w->rect().d[i]);
	}

	w->move_to(anchor);

	auto sp = utki::make_shared_from_this(*this);
	ASSERT(sp)
	this->context->run_from_ui_thread([c, sp](){
		sp->push_back(c);
	});

	return c;
}

void overlay::close_all_context_menus(){
	while(dynamic_cast<context_menu_wrapper*>(this->children().back().get())){
		this->pop_back();
	}
}
<|endoftext|>


<commit_before>/*
 *  The Mana World
 *  Copyright (C) 2009  The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "net/manaserv/generalhandler.h"

#include "gui/changeemaildialog.h"
#include "gui/charselectdialog.h"
#include "gui/inventorywindow.h"
#include "gui/partywindow.h"
#include "gui/register.h"
#include "gui/skilldialog.h"
#include "gui/specialswindow.h"
#include "gui/statuswindow.h"

#include "net/manaserv/network.h"
#include "net/manaserv/connection.h"

#include "net/manaserv/beinghandler.h"
#include "net/manaserv/buysellhandler.h"
#include "net/manaserv/charhandler.h"
#include "net/manaserv/chathandler.h"
#include "net/manaserv/effecthandler.h"
#include "net/manaserv/gamehandler.h"
#include "net/manaserv/guildhandler.h"
#include "net/manaserv/inventoryhandler.h"
#include "net/manaserv/itemhandler.h"
#include "net/manaserv/loginhandler.h"
#include "net/manaserv/npchandler.h"
#include "net/manaserv/partyhandler.h"
#include "net/manaserv/playerhandler.h"
#include "net/manaserv/specialhandler.h"
#include "net/manaserv/tradehandler.h"

#include "utils/gettext.h"

#include "main.h"

#include <list>

extern Net::GeneralHandler *generalHandler;

extern ManaServ::LoginHandler *loginHandler;

namespace ManaServ {

Connection *accountServerConnection = 0;
Connection *chatServerConnection = 0;
Connection *gameServerConnection = 0;
std::string netToken = "";
ServerInfo gameServer;
ServerInfo chatServer;

GeneralHandler::GeneralHandler():
        mBeingHandler(new BeingHandler),
        mBuySellHandler(new BuySellHandler),
        mCharHandler(new CharHandler),
        mChatHandler(new ChatHandler),
        mEffectHandler(new EffectHandler),
        mGameHandler(new GameHandler),
        mGuildHandler(new GuildHandler),
        mInventoryHandler(new InventoryHandler),
        mItemHandler(new ItemHandler),
        mLoginHandler(new LoginHandler),
        mNpcHandler(new NpcHandler),
        mPartyHandler(new PartyHandler),
        mPlayerHandler(new PlayerHandler),
        mTradeHandler(new TradeHandler),
        mSpecialHandler(new SpecialHandler)
{
    initialize();

    accountServerConnection = getConnection();
    gameServerConnection = getConnection();
    chatServerConnection = getConnection();

    generalHandler = this;

    std::list<ItemDB::Stat> stats;
    stats.push_back(ItemDB::Stat("str", N_("Strength %+d")));
    stats.push_back(ItemDB::Stat("agi", N_("Agility %+d")));
    stats.push_back(ItemDB::Stat("dex", N_("Dexterity %+d")));
    stats.push_back(ItemDB::Stat("vit", N_("Vitality %+d")));
    stats.push_back(ItemDB::Stat("int", N_("Intelligence %+d")));
    stats.push_back(ItemDB::Stat("will", N_("Willpower %+d")));

    ItemDB::setStatsList(stats);
}

void GeneralHandler::load()
{
    registerHandler(mBeingHandler.get());
    registerHandler(mBuySellHandler.get());
    registerHandler(mCharHandler.get());
    registerHandler(mChatHandler.get());
    registerHandler(mEffectHandler.get());
    registerHandler(mGameHandler.get());
    registerHandler(mGuildHandler.get());
    registerHandler(mInventoryHandler.get());
    registerHandler(mItemHandler.get());
    registerHandler(mLoginHandler.get());
    registerHandler(mNpcHandler.get());
    registerHandler(mPartyHandler.get());
    registerHandler(mPlayerHandler.get());
    registerHandler(mTradeHandler.get());
}

void GeneralHandler::reload()
{
    // Nothing needed yet
}

void GeneralHandler::unload()
{
    clearHandlers();

    if (accountServerConnection)
        accountServerConnection->disconnect();
    if (gameServerConnection)
        gameServerConnection->disconnect();
    if (chatServerConnection)
        chatServerConnection->disconnect();

    delete accountServerConnection;
    delete gameServerConnection;
    delete chatServerConnection;

    finalize();
}

void GeneralHandler::flushNetwork()
{
    flush();

    if (state == STATE_SWITCH_CHARACTER &&
        Net::getLoginHandler()->isConnected())
    {
        loginHandler->reconnect();
        state = STATE_GET_CHARACTERS;
    }
}

void GeneralHandler::guiWindowsLoaded()
{
    inventoryWindow->setSplitAllowed(true);
    partyWindow->clearPartyName();
    skillDialog->loadSkills("tmw-skills.xml");
    specialsWindow->loadSpecials("specials.xml");

    player_node->setExpNeeded(100);

    statusWindow->addAttribute(16, _("Strength"), true);
    statusWindow->addAttribute(17, _("Agility"), true);
    statusWindow->addAttribute(18, _("Dexterity"), true);
    statusWindow->addAttribute(19, _("Vitality"), true);
    statusWindow->addAttribute(20, _("Intelligence"), true);
    statusWindow->addAttribute(21, _("Willpower"), true);
}

void GeneralHandler::guiWindowsUnloaded()
{
    // TODO
}

void GeneralHandler::clearHandlers()
{
    clearNetworkHandlers();
}

} // namespace ManaServ
<commit_msg>Update des Sourcecodes.<commit_after>/*
 *  The Mana World
 *  Copyright (C) 2009  The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "net/manaserv/generalhandler.h"

#include "gui/changeemaildialog.h"
#include "gui/charselectdialog.h"
#include "gui/inventorywindow.h"
#include "gui/partywindow.h"
#include "gui/register.h"
#include "gui/skilldialog.h"
#include "gui/specialswindow.h"
#include "gui/statuswindow.h"

#include "net/manaserv/network.h"
#include "net/manaserv/connection.h"

#include "net/manaserv/beinghandler.h"
#include "net/manaserv/buysellhandler.h"
#include "net/manaserv/charhandler.h"
#include "net/manaserv/chathandler.h"
#include "net/manaserv/effecthandler.h"
#include "net/manaserv/gamehandler.h"
#include "net/manaserv/guildhandler.h"
#include "net/manaserv/inventoryhandler.h"
#include "net/manaserv/itemhandler.h"
#include "net/manaserv/loginhandler.h"
#include "net/manaserv/npchandler.h"
#include "net/manaserv/partyhandler.h"
#include "net/manaserv/playerhandler.h"
#include "net/manaserv/specialhandler.h"
#include "net/manaserv/tradehandler.h"

#include "utils/gettext.h"

#include "main.h"

#include <list>

extern Net::GeneralHandler *generalHandler;

extern ManaServ::LoginHandler *loginHandler;

namespace ManaServ {

Connection *accountServerConnection = 0;
Connection *chatServerConnection = 0;
Connection *gameServerConnection = 0;
std::string netToken = "";
ServerInfo gameServer;
ServerInfo chatServer;

GeneralHandler::GeneralHandler():
        mBeingHandler(new BeingHandler),
        mBuySellHandler(new BuySellHandler),
        mCharHandler(new CharHandler),
        mChatHandler(new ChatHandler),
        mEffectHandler(new EffectHandler),
        mGameHandler(new GameHandler),
        mGuildHandler(new GuildHandler),
        mInventoryHandler(new InventoryHandler),
        mItemHandler(new ItemHandler),
        mLoginHandler(new LoginHandler),
        mNpcHandler(new NpcHandler),
        mPartyHandler(new PartyHandler),
        mPlayerHandler(new PlayerHandler),
        mTradeHandler(new TradeHandler),
        mSpecialHandler(new SpecialHandler)
{
    initialize();

    accountServerConnection = getConnection();
    gameServerConnection = getConnection();
    chatServerConnection = getConnection();

    generalHandler = this;

    std::list<ItemDB::Stat> stats;
    stats.push_back(ItemDB::Stat("str", N_("Strength %+d")));
    stats.push_back(ItemDB::Stat("agi", N_("Agility %+d")));
    stats.push_back(ItemDB::Stat("dex", N_("Dexterity %+d")));
    stats.push_back(ItemDB::Stat("vit", N_("Vitality %+d")));
    stats.push_back(ItemDB::Stat("int", N_("Intelligence %+d")));
    stats.push_back(ItemDB::Stat("will", N_("Willpower %+d")));

    ItemDB::setStatsList(stats);
}

void GeneralHandler::load()
{
    registerHandler(mBeingHandler.get());
    registerHandler(mBuySellHandler.get());
    registerHandler(mCharHandler.get());
    registerHandler(mChatHandler.get());
    registerHandler(mEffectHandler.get());
    registerHandler(mGameHandler.get());
    registerHandler(mGuildHandler.get());
    registerHandler(mInventoryHandler.get());
    registerHandler(mItemHandler.get());
    registerHandler(mLoginHandler.get());
    registerHandler(mNpcHandler.get());
    registerHandler(mPartyHandler.get());
    registerHandler(mPlayerHandler.get());
    registerHandler(mTradeHandler.get());
}

void GeneralHandler::reload()
{
    // Nothing needed yet
}

void GeneralHandler::unload()
{
    clearHandlers();

    if (accountServerConnection)
        accountServerConnection->disconnect();
    if (gameServerConnection)
        gameServerConnection->disconnect();
    if (chatServerConnection)
        chatServerConnection->disconnect();

    delete accountServerConnection;
    delete gameServerConnection;
    delete chatServerConnection;

    finalize();
}

void GeneralHandler::flushNetwork()
{
    flush();

    if (state == STATE_SWITCH_CHARACTER &&
        Net::getLoginHandler()->isConnected())
    {
        loginHandler->reconnect();
        state = STATE_GET_CHARACTERS;
    }
}

void GeneralHandler::guiWindowsLoaded()
{
    inventoryWindow->setSplitAllowed(true);
    partyWindow->clearPartyName();
    skillDialog->loadSkills("mana-skills.xml");
    specialsWindow->loadSpecials("specials.xml");

    player_node->setExpNeeded(100);

    statusWindow->addAttribute(16, _("Strength"), true);
    statusWindow->addAttribute(17, _("Agility"), true);
    statusWindow->addAttribute(18, _("Dexterity"), true);
    statusWindow->addAttribute(19, _("Vitality"), true);
    statusWindow->addAttribute(20, _("Intelligence"), true);
    statusWindow->addAttribute(21, _("Willpower"), true);
}

void GeneralHandler::guiWindowsUnloaded()
{
    // TODO
}

void GeneralHandler::clearHandlers()
{
    clearNetworkHandlers();
}

} // namespace ManaServ
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2013 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "libmesh/libmesh_singleton.h"
#include "libmesh/threads.h"

// C/C++ includes
#include <vector>

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous bits
namespace
{
  using namespace libMesh;

  // Mutex object for required locking
  typedef Threads::spin_mutex SingletonMutex;
  SingletonMutex singleton_mtx, setup_mtx;

  // global list of runtime Singleton objects - created dynamically,
  // cleaned up in reverse order.
  typedef std::vector<Singleton*> SingletonList;

  SingletonList& get_singleton_cache()
  {
    static SingletonList singleton_cache;
    return singleton_cache;
  }

  typedef std::vector<Singleton::Setup*> SetupList;
  SetupList& get_setup_cache()
  {
    static SetupList setup_cache;
    return setup_cache;
  }

} // end anonymous namespace

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous bits
namespace libMesh
{

  Singleton::Singleton ()
  {
    SingletonMutex::scoped_lock lock(singleton_mtx);

    get_singleton_cache().push_back (this);
  }

  Singleton::Setup::Setup ()
  {
    SingletonMutex::scoped_lock lock(setup_mtx);

    get_setup_cache().push_back (this);
  }

  void Singleton::setup ()
  {
    SingletonMutex::scoped_lock lock(setup_mtx);

    SetupList& setup_cache = get_setup_cache();

    for (SetupList::iterator it = setup_cache.begin();
	 it!=setup_cache.end(); ++it)
      {
	libmesh_assert (*it != NULL);
	(*it)->setup();
      }
  }

  void Singleton::cleanup ()
  {
    SingletonMutex::scoped_lock lock(singleton_mtx);

    SetupList& singleton_cache = get_singleton_cache();

    for (SingletonList::reverse_iterator it = singleton_cache.rbegin();
	 it!=singleton_cache.rend(); ++it)
      {
	libmesh_assert (*it != NULL);
	delete *it;
	*it = NULL;
      }

    singleton_cache.clear();
  }

} // namespace libMesh
<commit_msg>Fix cut-n-paste typo<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2013 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "libmesh/libmesh_singleton.h"
#include "libmesh/threads.h"

// C/C++ includes
#include <vector>

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous bits
namespace
{
  using namespace libMesh;

  // Mutex object for required locking
  typedef Threads::spin_mutex SingletonMutex;
  SingletonMutex singleton_mtx, setup_mtx;

  // global list of runtime Singleton objects - created dynamically,
  // cleaned up in reverse order.
  typedef std::vector<Singleton*> SingletonList;

  SingletonList& get_singleton_cache()
  {
    static SingletonList singleton_cache;
    return singleton_cache;
  }

  typedef std::vector<Singleton::Setup*> SetupList;
  SetupList& get_setup_cache()
  {
    static SetupList setup_cache;
    return setup_cache;
  }

} // end anonymous namespace

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous bits
namespace libMesh
{

  Singleton::Singleton ()
  {
    SingletonMutex::scoped_lock lock(singleton_mtx);

    get_singleton_cache().push_back (this);
  }

  Singleton::Setup::Setup ()
  {
    SingletonMutex::scoped_lock lock(setup_mtx);

    get_setup_cache().push_back (this);
  }

  void Singleton::setup ()
  {
    SingletonMutex::scoped_lock lock(setup_mtx);

    SetupList& setup_cache = get_setup_cache();

    for (SetupList::iterator it = setup_cache.begin();
	 it!=setup_cache.end(); ++it)
      {
	libmesh_assert (*it != NULL);
	(*it)->setup();
      }
  }

  void Singleton::cleanup ()
  {
    SingletonMutex::scoped_lock lock(singleton_mtx);

    SingletonList& singleton_cache = get_singleton_cache();

    for (SingletonList::reverse_iterator it = singleton_cache.rbegin();
	 it!=singleton_cache.rend(); ++it)
      {
	libmesh_assert (*it != NULL);
	delete *it;
	*it = NULL;
      }

    singleton_cache.clear();
  }

} // namespace libMesh
<|endoftext|>


<commit_before>#ifndef context_hh_INCLUDED
#define context_hh_INCLUDED

#include "window.hh"
#include "client.hh"
#include "user_interface.hh"

namespace Kakoune
{

// A Context is provided to all commands, it permits
// to access a client, window, editor or buffer if available.
struct Context
{
    Context() {}
    Context(Editor& editor)
        : m_editor(&editor) {}

    Context(Client& client)
        : m_client(&client) {}

    // to allow func(Context(Editor(...)))
    Context(Editor&& editor)
        : m_editor(&editor) {}

    Context(const Context&) = delete;
    Context& operator=(const Context&) = delete;

    Buffer& buffer() const
    {
        if (not has_buffer())
            throw runtime_error("no buffer in context");
        return m_editor->buffer();
    }
    bool has_buffer() const { return (bool)m_editor; }

    Editor& editor() const
    {
        if (not has_editor())
            throw runtime_error("no editor in context");
        return *m_editor.get();
    }
    bool has_editor() const { return (bool)m_editor; }

    Window& window() const
    {
        if (not has_window())
            throw runtime_error("no window in context");
        return *dynamic_cast<Window*>(m_editor.get());
    }
    bool has_window() const { return (bool)m_editor and dynamic_cast<Window*>(m_editor.get()); }

    Client& client() const
    {
        if (not has_client())
            throw runtime_error("no client in context");
        return *m_client;
    }
    bool has_client() const { return (bool)m_client; }

    UserInterface& ui() const
    {
        if (not has_ui())
            throw runtime_error("no user interface in context");
        return *m_ui;
    }
    bool has_ui() const { return (bool)m_ui; }

    void change_editor(Editor& editor)
    {
        m_editor.reset(&editor);
    }

    void change_ui(UserInterface& ui)
    {
        m_ui.reset(&ui);
    }

    OptionManager& option_manager() const
    {
        if (has_window())
            return window().option_manager();
        if (has_buffer())
            return buffer().option_manager();
        return GlobalOptionManager::instance();
    }

    void draw_ifn() const
    {
        if (has_ui() and has_window())
            ui().draw_window(window());
    }

    void print_status(const String& status) const
    {
        if (has_ui())
            ui().print_status(status);
    }

    using Insertion = std::pair<InsertMode, std::vector<Key>>;
    Insertion& last_insert() { return m_last_insert; }

    int& numeric_param() { return m_numeric_param; }
private:
    safe_ptr<Editor>        m_editor;
    safe_ptr<Client>        m_client;
    safe_ptr<UserInterface> m_ui;

    Insertion m_last_insert = {InsertMode::Insert, {}};
    int m_numeric_param = 0;
};

}
#endif // context_hh_INCLUDED
<commit_msg>Context: explicit constructors and more comments<commit_after>#ifndef context_hh_INCLUDED
#define context_hh_INCLUDED

#include "window.hh"
#include "client.hh"
#include "user_interface.hh"

namespace Kakoune
{

// A Context is used to access non singleton objects for various services
// in commands.
//
// The Context object links a Client, an Editor (which may be a Window),
// and a UserInterface. It may represent an interactive user window, or
// a hook execution or a macro replay.
struct Context
{
    Context() {}
    explicit Context(Editor& editor)
        : m_editor(&editor) {}

    explicit Context(Client& client)
        : m_client(&client) {}

    // to allow func(Context(Editor(...)))
    // make sure the context will not survive the next ';'
    explicit Context(Editor&& editor)
        : m_editor(&editor) {}

    Context(const Context&) = delete;
    Context& operator=(const Context&) = delete;

    Buffer& buffer() const
    {
        if (not has_buffer())
            throw runtime_error("no buffer in context");
        return m_editor->buffer();
    }
    bool has_buffer() const { return (bool)m_editor; }

    Editor& editor() const
    {
        if (not has_editor())
            throw runtime_error("no editor in context");
        return *m_editor.get();
    }
    bool has_editor() const { return (bool)m_editor; }

    Window& window() const
    {
        if (not has_window())
            throw runtime_error("no window in context");
        return *dynamic_cast<Window*>(m_editor.get());
    }
    bool has_window() const { return (bool)m_editor and dynamic_cast<Window*>(m_editor.get()); }

    Client& client() const
    {
        if (not has_client())
            throw runtime_error("no client in context");
        return *m_client;
    }
    bool has_client() const { return (bool)m_client; }

    UserInterface& ui() const
    {
        if (not has_ui())
            throw runtime_error("no user interface in context");
        return *m_ui;
    }
    bool has_ui() const { return (bool)m_ui; }

    void change_editor(Editor& editor)
    {
        m_editor.reset(&editor);
    }

    void change_ui(UserInterface& ui)
    {
        m_ui.reset(&ui);
    }

    OptionManager& option_manager() const
    {
        if (has_window())
            return window().option_manager();
        if (has_buffer())
            return buffer().option_manager();
        return GlobalOptionManager::instance();
    }

    void draw_ifn() const
    {
        if (has_ui() and has_window())
            ui().draw_window(window());
    }

    void print_status(const String& status) const
    {
        if (has_ui())
            ui().print_status(status);
    }

    using Insertion = std::pair<InsertMode, std::vector<Key>>;
    Insertion& last_insert() { return m_last_insert; }

    int& numeric_param() { return m_numeric_param; }
private:
    safe_ptr<Editor>        m_editor;
    safe_ptr<Client>        m_client;
    safe_ptr<UserInterface> m_ui;

    Insertion m_last_insert = {InsertMode::Insert, {}};
    int m_numeric_param = 0;
};

}
#endif // context_hh_INCLUDED
<|endoftext|>


<commit_before>// -*- C++ -*-

// httpd.conf:
//
// LoadModule acmacs_module "mod_acmacs.so"
// AddHandler acmacs .ace .save .save.xz .acd1 .acd1.xz
//
// /etc/apache2/envvars:
//
// export ACMACSD_ROOT="/home/.../AD"

#include <iostream>
#include <string>
#include <typeinfo>

#include "apache2/httpd.h"
#include "apache2/http_core.h"
#include "apache2/http_protocol.h"
#include "apache2/http_request.h"
#include "apache2/http_log.h"
#include "apache2/util_script.h"

#include "acmacs-base/filesystem.hh"
#include "acmacs-base/gzip.hh"
#include "acmacs-base/range.hh"
#include "acmacs-base/virus-name.hh"
#include "locationdb/locdb.hh"
#include "seqdb/seqdb.hh"
#include "acmacs-chart-2/chart-modify.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/ace-export.hh"

static void register_hooks(apr_pool_t *pool);
static int acmacs_handler(request_rec *r);
static void make_html(request_rec *r, const char* view_mode, const char* coloring);
static void make_ace(request_rec *r);

// ----------------------------------------------------------------------

extern "C" module acmacs_module;
extern "C"  {
module AP_MODULE_DECLARE_DATA acmacs_module = {
    STANDARD20_MODULE_STUFF, nullptr, nullptr, nullptr, nullptr, nullptr, register_hooks
};
}
APLOG_USE_MODULE(acmacs);

#ifdef __clang__
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wunused-macros"
#endif

static void register_hooks(apr_pool_t * /*pool*/) {
    ap_hook_handler(acmacs_handler, nullptr, nullptr, APR_HOOK_LAST);
}

#define AP_WARN APLOG_MARK, APLOG_WARNING, 0
#define AP_ERR APLOG_MARK, APLOG_ERR, 0

// ----------------------------------------------------------------------

// ----------------------------------------------------------------------

static int acmacs_handler(request_rec *r) {
    if (!r->handler || r->handler != std::string("acmacs"))
        return DECLINED;

    apr_table_t *GET;
    ap_args_to_table(r, &GET);
    const char* acv_c = apr_table_get(GET, "acv");
    const std::string acv = acv_c ? acv_c : "";

    if (!fs::exists(fs::path(r->filename)))
        return HTTP_NOT_FOUND;

    try {
        if (acv == "html") {
            const char* view_mode = apr_table_get(GET, "view-mode");
            const char* coloring = apr_table_get(GET, "coloring");
            make_html(r, view_mode ? view_mode : "best-projection", coloring ? coloring : "default");
        }
        else if (acv == "ace") {
            make_ace(r);
        }
        else {
            return DECLINED;
        }
        return OK;
    }
    catch (std::exception& err) {
        ap_log_rerror(AP_ERR, r, "%s: %s", typeid(err).name(), err.what());
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    return HTTP_INTERNAL_SERVER_ERROR;
}

// ----------------------------------------------------------------------

static const char* sHtml = R"(
<!DOCTYPE html>

   <meta charset="utf-8" />
   <title>%s</title>

)";

void make_html(request_rec *r, const char* view_mode, const char* coloring)
{
    // ap_log_rerror(AP_WARN, r, "uri: %s", r->uri);
    // ap_log_rerror(AP_WARN, r, "path_info: %s", r->path_info);

    ap_set_content_type(r, "text/html");
    ap_rprintf(r, sHtml, r->filename, view_mode, coloring, r->uri);

} // make_html

// ----------------------------------------------------------------------

void make_ace(request_rec* r)
{
    const auto& locdb = get_locdb(report_time::Yes);
    const auto& seqdb = seqdb::get(report_time::Yes);

    acmacs::chart::ChartModify chart(acmacs::chart::import_from_file(r->filename, acmacs::chart::Verify::None, report_time::No));
    auto antigens = chart.antigens_modify();

    // set continent info
    for (auto antigen_no : acmacs::range(antigens->size())) {
        auto& antigen = antigens->at(antigen_no);
        if (antigen.continent().empty()) {
            try {
                antigen.continent(locdb.continent(virus_name::location(antigen.name())));
            }
            catch (std::exception& err) {
                ap_log_rerror(AP_WARN, r, "cannot figure out continent for \"%s\": %s", antigen.name().data(), err.what());
            }
            catch (...) {
                ap_log_rerror(AP_WARN, r, "cannot figure out continent for \"%s\": unknown exception", antigen.name().data());
            }
        }
    }

    // set clade info
    for (auto antigen_no : acmacs::range(antigens->size())) {
        auto& antigen = antigens->at(antigen_no);
        try {
            const auto* entry_seq = seqdb.find_hi_name(antigen.full_name());
            if (entry_seq) {
                for (const auto& clade : entry_seq->seq().clades()) {
                    antigen.add_clade(clade);
                }
            }
        }
        catch (std::exception& err) {
            ap_log_rerror(AP_WARN, r, "cannot figure out clade for \"%s\": %s", antigen.name().data(), err.what());
        }
        catch (...) {
            ap_log_rerror(AP_WARN, r, "cannot figure out clade for \"%s\": unknown exception", antigen.name().data());
        }
    }

    ap_set_content_type(r, "application/json");
    r->content_encoding = "gzip";
    const auto exported = ace_export(chart, "mod_acmacs");
    const auto compressed = acmacs::file::gzip_compress(exported);
    ap_rwrite(compressed.data(), static_cast<int>(compressed.size()), r);

} // make_ace

// ----------------------------------------------------------------------

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>exporting ace without json pretty printing for apache mod_acmacs<commit_after>// -*- C++ -*-

// httpd.conf:
//
// LoadModule acmacs_module "mod_acmacs.so"
// AddHandler acmacs .ace .save .save.xz .acd1 .acd1.xz
//
// /etc/apache2/envvars:
//
// export ACMACSD_ROOT="/home/.../AD"

#include <iostream>
#include <string>
#include <typeinfo>

#include "apache2/httpd.h"
#include "apache2/http_core.h"
#include "apache2/http_protocol.h"
#include "apache2/http_request.h"
#include "apache2/http_log.h"
#include "apache2/util_script.h"

#include "acmacs-base/filesystem.hh"
#include "acmacs-base/gzip.hh"
#include "acmacs-base/range.hh"
#include "acmacs-base/virus-name.hh"
#include "locationdb/locdb.hh"
#include "seqdb/seqdb.hh"
#include "acmacs-chart-2/chart-modify.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/ace-export.hh"

static void register_hooks(apr_pool_t *pool);
static int acmacs_handler(request_rec *r);
static void make_html(request_rec *r, const char* view_mode, const char* coloring);
static void make_ace(request_rec *r);

// ----------------------------------------------------------------------

extern "C" module acmacs_module;
extern "C"  {
module AP_MODULE_DECLARE_DATA acmacs_module = {
    STANDARD20_MODULE_STUFF, nullptr, nullptr, nullptr, nullptr, nullptr, register_hooks
};
}
APLOG_USE_MODULE(acmacs);

#ifdef __clang__
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wunused-macros"
#endif

static void register_hooks(apr_pool_t * /*pool*/) {
    ap_hook_handler(acmacs_handler, nullptr, nullptr, APR_HOOK_LAST);
}

#define AP_WARN APLOG_MARK, APLOG_WARNING, 0
#define AP_ERR APLOG_MARK, APLOG_ERR, 0

// ----------------------------------------------------------------------

// ----------------------------------------------------------------------

static int acmacs_handler(request_rec *r) {
    if (!r->handler || r->handler != std::string("acmacs"))
        return DECLINED;

    apr_table_t *GET;
    ap_args_to_table(r, &GET);
    const char* acv_c = apr_table_get(GET, "acv");
    const std::string acv = acv_c ? acv_c : "";

    if (!fs::exists(fs::path(r->filename)))
        return HTTP_NOT_FOUND;

    try {
        if (acv == "html") {
            const char* view_mode = apr_table_get(GET, "view-mode");
            const char* coloring = apr_table_get(GET, "coloring");
            make_html(r, view_mode ? view_mode : "best-projection", coloring ? coloring : "default");
        }
        else if (acv == "ace") {
            make_ace(r);
        }
        else {
            return DECLINED;
        }
        return OK;
    }
    catch (std::exception& err) {
        ap_log_rerror(AP_ERR, r, "%s: %s", typeid(err).name(), err.what());
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    return HTTP_INTERNAL_SERVER_ERROR;
}

// ----------------------------------------------------------------------

static const char* sHtml = R"(
<!DOCTYPE html>

   <meta charset="utf-8" />
   <title>%s</title>

)";

void make_html(request_rec *r, const char* view_mode, const char* coloring)
{
    // ap_log_rerror(AP_WARN, r, "uri: %s", r->uri);
    // ap_log_rerror(AP_WARN, r, "path_info: %s", r->path_info);

    ap_set_content_type(r, "text/html");
    ap_rprintf(r, sHtml, r->filename, view_mode, coloring, r->uri);

} // make_html

// ----------------------------------------------------------------------

void make_ace(request_rec* r)
{
    const auto& locdb = get_locdb(report_time::Yes);
    const auto& seqdb = seqdb::get(report_time::Yes);

    acmacs::chart::ChartModify chart(acmacs::chart::import_from_file(r->filename, acmacs::chart::Verify::None, report_time::No));
    auto antigens = chart.antigens_modify();

    // set continent info
    for (auto antigen_no : acmacs::range(antigens->size())) {
        auto& antigen = antigens->at(antigen_no);
        if (antigen.continent().empty()) {
            try {
                antigen.continent(locdb.continent(virus_name::location(antigen.name())));
            }
            catch (std::exception& err) {
                ap_log_rerror(AP_WARN, r, "cannot figure out continent for \"%s\": %s", antigen.name().data(), err.what());
            }
            catch (...) {
                ap_log_rerror(AP_WARN, r, "cannot figure out continent for \"%s\": unknown exception", antigen.name().data());
            }
        }
    }

    // set clade info
    for (auto antigen_no : acmacs::range(antigens->size())) {
        auto& antigen = antigens->at(antigen_no);
        try {
            const auto* entry_seq = seqdb.find_hi_name(antigen.full_name());
            if (entry_seq) {
                for (const auto& clade : entry_seq->seq().clades()) {
                    antigen.add_clade(clade);
                }
            }
        }
        catch (std::exception& err) {
            ap_log_rerror(AP_WARN, r, "cannot figure out clade for \"%s\": %s", antigen.name().data(), err.what());
        }
        catch (...) {
            ap_log_rerror(AP_WARN, r, "cannot figure out clade for \"%s\": unknown exception", antigen.name().data());
        }
    }

    ap_set_content_type(r, "application/json");
    r->content_encoding = "gzip";
    const auto exported = ace_export(chart, "mod_acmacs", 0);
    const auto compressed = acmacs::file::gzip_compress(exported);
    ap_rwrite(compressed.data(), static_cast<int>(compressed.size()), r);

} // make_ace

// ----------------------------------------------------------------------

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before><commit_msg>Added a comment.<commit_after><|endoftext|>


<commit_before>//
//  Reference : Chapter 6, "Introduction to Algorithms 3rd ed", aka CLRS.
//
#pragma once

#include <vector>
#include <functional>
#include <stdexcept>
#include <algorithm>

using std::move;
using std::find_if;

namespace search
{
    //
    //  parent
    //  O(1)
    //
    template<typename Iterator>
    auto inline parent(Iterator first, Iterator it) -> Iterator
    {
        return first + (it - first - 1) / 2;
    }
    //
    //  left_child
    //  O(1)
    //
    template<typename Iterator>
    auto inline left_child(Iterator first, Iterator last, Iterator it) -> Iterator
    {
        auto size = last - first;
        auto offset = 2 * (it - first) + 1;
        return offset > size ? last : first + offset;
    }
    //
    //  right_child
    //  O(1)
    //
    template<typename Iterator>
    auto inline right_child(Iterator first, Iterator last, Iterator it) -> Iterator
    {
        auto left = left_child(first, last, it);
        return left != last ? left + 1 : last;
    }
    //
    //  heapify
    //  O(lg n)
    //  maintain heap's peroperties with a float down way
    //
    template<typename Iterator, typename CompareFunc>
    auto heapify(Iterator first, Iterator last, Iterator curr, CompareFunc && compare) -> void
    {
        while (true)
        {
            auto left = left_child(first, last, curr);
            auto right = right_child(first, last, curr);

            //! find max or min amoung curr, left and right children, depending on the CommpareFunc passed in.
            auto max_min = (left != last && compare(*left, *curr)) ? left : curr;
            if (right != last && compare(*right, *max_min))	max_min = right;

            //!	exchange.
            if (max_min != curr)
            {
                std::swap(*max_min, *curr);
                curr = max_min;
            }
            else
            {
                return;
            }
        }
    }
    //
    //  build_heap
    //  O(n)
    //
    template<typename Iterator, typename CompareFunc>
    auto inline build_heap(Iterator first, Iterator last, CompareFunc && compare) -> void
    {
        auto size = last - first;
        for (auto curr = first + size / 2 - 1; /* */; --curr)
        {
            heapify(first, last, curr, compare);
            if (curr == first) return;
        }
    }

    template<typename Iterator, typename CompareFunc>
    auto inline sift_up(Iterator first, Iterator curr, CompareFunc && compare) -> bool
    {
        auto c = curr;
        auto p = [&] { return parent(first, c); };
        auto is_needed = [&] { return c != first && !compare(*p(), *c); };

        if (!is_needed()) return false;
        for (; is_needed(); c = p())  std::swap(*p(), *c);
        return true;
    }

    //
    //  PriorityQueue
    //
    template<typename Value, typename CompareFunc>
    class PriorityQueue
    {
    public:
        using Vector = std::vector < Value >;
        using SizeType = typename Vector::size_type;
        using Iterator = typename Vector::iterator;

        PriorityQueue() = default;

        PriorityQueue(CompareFunc c)
            : _seq{}, _compare{ c }
        {   }

        PriorityQueue(std::initializer_list<Value>&& list, CompareFunc&& c)
            : _seq(std::move(list)), _compare{ std::move(c) }
        {
            if (!empty())
                build_heap(_seq.begin(), _seq.end(), _compare);
        }

        template<typename Iterator>
        PriorityQueue(Iterator first, Iterator last, CompareFunc&& c)
            : _seq(first, last), _compare{ std::move(c) }
        {
            if (!empty())
                build_heap(_seq.begin(), _seq.end(), _compare);
        }

        auto top() const -> Value const&
        {
            return _seq.front();
        }

        auto size() const -> SizeType
        {
            return _seq.size();
        }

        auto empty() const -> bool
        {
            return _seq.empty();
        }

        auto contains(Value const& value) const -> bool
        {
            return _seq.cend() != std::find(_seq.cbegin(), _seq.cend(), value);
        }

        template<typename Predicate>
        auto any(Predicate predicate) const -> bool
        {
            return std::any_of(_seq.cbegin(), _seq.cend(), predicate);
        }

        auto push(Value const& new_val) -> void
        {
            // find the right place for new_val
            _seq.resize(size() + 1);
            auto curr = _seq.end() - 1;
            for (; curr > _seq.begin() && _compare(new_val, *parent(_seq.begin(), curr)); curr = parent(_seq.begin(), curr))
                *curr = *parent(_seq.begin(), curr);

            // insert
            *curr = new_val;
        }

        auto pop() -> Value
        {
            if (empty())
                throw std::underflow_error{ "underflow." };
            auto popped = _seq.front();
            _seq.front() = _seq.back();
            _seq.resize(_seq.size() - 1);
            heapify(_seq.begin(), _seq.end(), _seq.begin(), _compare);

            return popped;
        }

        auto remove(Value const& item) -> void
        {
            auto it = std::find(_seq.begin(), _seq.end(), item);
            if (_seq.end() != it)
                remove(it);
        }
        //
        //  O(lg n)
        //
        auto substitute(Value const& old_value, Value const& new_value) -> void
        {
            remove(old_value);
            push(new_value);
        }

        template<typename Predicate>
        auto update_with_if(Value const& new_value, Predicate predicate) -> void
        {
            auto iterator = find_if(_seq.begin(), _seq.end(), [&](Value const& value) {
                return predicate(value);
            });
            if (iterator != _seq.end() && _compare(new_value, *iterator))
                substitute(*iterator, new_value);
        }

        void reset()
        {
            _seq.clear();
        }

        void reset(CompareFunc && c)
        {
            _compare = move(c);
            reset();
        }

    private:
        Vector _seq;
        CompareFunc _compare;
        //
        //  Make sure vector is not empty.
        //  O(lg n)
        //
        template<typename Iterator>
        auto remove(Iterator at) -> void
        {
            std::swap(*at, *(_seq.end() - 1));
            if (!sift_up(_seq.begin(), at, _compare))
                heapify(_seq.begin(), _seq.end() - 1, at, _compare);//avoid involving the last item.
            _seq.resize(size() - 1);
        }
    };
}<commit_msg>polishing 	modified:   planning/lib/priority_queue.hpp<commit_after>//
//  Reference : Chapter 6, "Introduction to Algorithms 3rd ed", aka CLRS.
//
#pragma once

#include <vector>
#include <functional>
#include <stdexcept>
#include <algorithm>

using std::move;
using std::find_if;
using std::swap;

namespace search
{
    //
    //  parent
    //  O(1)
    //
    template<typename Iterator>
    auto inline parent(Iterator first, Iterator it) -> Iterator
    {
        return first + (it - first - 1) / 2;
    }
    //
    //  left_child
    //  O(1)
    //
    template<typename Iterator>
    auto inline left_child(Iterator first, Iterator last, Iterator it) -> Iterator
    {
        auto size = last - first;
        auto offset = 2 * (it - first) + 1;
        return offset > size ? last : first + offset;
    }
    //
    //  right_child
    //  O(1)
    //
    template<typename Iterator>
    auto inline right_child(Iterator first, Iterator last, Iterator it) -> Iterator
    {
        auto left = left_child(first, last, it);
        return left != last ? left + 1 : last;
    }
    //
    //  heapify
    //  O(lg n)
    //  maintain heap's peroperties with a float down way
    //
    template<typename Iterator, typename CompareFunc>
    auto heapify(Iterator first, Iterator last, Iterator curr, CompareFunc && compare) -> void
    {
        while (true)
        {
            auto left = left_child(first, last, curr);
            auto right = right_child(first, last, curr);

            //! find max or min amoung curr, left and right children, depending on the CommpareFunc passed in.
            auto max_min = (left != last && compare(*left, *curr)) ? left : curr;
            if (right != last && compare(*right, *max_min))	max_min = right;

            if (curr == max_min) return;

            //!	exchange.
            swap(*max_min, *curr);
            curr = max_min;
        }
    }
    //
    //  build_heap
    //  O(n)
    //
    template<typename Iterator, typename CompareFunc>
    auto inline build_heap(Iterator first, Iterator last, CompareFunc && compare) -> void
    {
        auto size = last - first;
        for (auto curr = first + size / 2 - 1; /* */; --curr)
        {
            heapify(first, last, curr, compare);
            if (curr == first) return;
        }
    }

    template<typename Iterator, typename CompareFunc>
    auto inline sift_up(Iterator first, Iterator curr, CompareFunc && compare) -> bool
    {
        auto c = curr;
        auto p = [&] { return parent(first, c); };
        auto is_needed = [&] { return c != first && !compare(*p(), *c); };

        if (!is_needed()) return false;
        for (; is_needed(); c = p())  std::swap(*p(), *c);
        return true;
    }

    //
    //  PriorityQueue
    //
    template<typename Value, typename CompareFunc>
    class PriorityQueue
    {
    public:
        using Vector = std::vector < Value >;
        using SizeType = typename Vector::size_type;
        using Iterator = typename Vector::iterator;

        PriorityQueue() = default;

        PriorityQueue(CompareFunc c)
            : _seq{}, _compare{ c }
        {   }

        PriorityQueue(std::initializer_list<Value>&& list, CompareFunc&& c)
            : _seq(std::move(list)), _compare{ std::move(c) }
        {
            if (!empty())
                build_heap(_seq.begin(), _seq.end(), _compare);
        }

        template<typename Iterator>
        PriorityQueue(Iterator first, Iterator last, CompareFunc&& c)
            : _seq(first, last), _compare{ std::move(c) }
        {
            if (!empty())
                build_heap(_seq.begin(), _seq.end(), _compare);
        }

        auto top() const -> Value const&
        {
            return _seq.front();
        }

        auto size() const -> SizeType
        {
            return _seq.size();
        }

        auto empty() const -> bool
        {
            return _seq.empty();
        }

        auto contains(Value const& value) const -> bool
        {
            return _seq.cend() != std::find(_seq.cbegin(), _seq.cend(), value);
        }

        template<typename Predicate>
        auto any(Predicate predicate) const -> bool
        {
            return std::any_of(_seq.cbegin(), _seq.cend(), predicate);
        }

        auto push(Value const& new_val) -> void
        {
            // find the right place for new_val
            _seq.resize(size() + 1);
            auto curr = _seq.end() - 1;
            for (; curr > _seq.begin() && _compare(new_val, *parent(_seq.begin(), curr)); curr = parent(_seq.begin(), curr))
                *curr = *parent(_seq.begin(), curr);

            // insert
            *curr = new_val;
        }

        auto pop() -> Value
        {
            if (empty())
                throw std::underflow_error{ "underflow." };
            auto popped = _seq.front();
            _seq.front() = _seq.back();
            _seq.resize(_seq.size() - 1);
            heapify(_seq.begin(), _seq.end(), _seq.begin(), _compare);

            return popped;
        }

        auto remove(Value const& item) -> void
        {
            auto it = std::find(_seq.begin(), _seq.end(), item);
            if (_seq.end() != it)
                remove(it);
        }
        //
        //  O(lg n)
        //
        auto substitute(Value const& old_value, Value const& new_value) -> void
        {
            remove(old_value);
            push(new_value);
        }

        template<typename Predicate>
        auto update_with_if(Value const& new_value, Predicate predicate) -> void
        {
            auto iterator = find_if(_seq.begin(), _seq.end(), [&](Value const& value) {
                return predicate(value);
            });
            if (iterator != _seq.end() && _compare(new_value, *iterator))
                substitute(*iterator, new_value);
        }

        void reset()
        {
            _seq.clear();
        }

        void reset(CompareFunc && c)
        {
            _compare = move(c);
            reset();
        }

    private:
        Vector _seq;
        CompareFunc _compare;
        //
        //  Make sure vector is not empty.
        //  O(lg n)
        //
        template<typename Iterator>
        auto remove(Iterator at) -> void
        {
            std::swap(*at, *(_seq.end() - 1));
            if (!sift_up(_seq.begin(), at, _compare))
                heapify(_seq.begin(), _seq.end() - 1, at, _compare);//avoid involving the last item.
            _seq.resize(size() - 1);
        }
    };
}<|endoftext|>


<commit_before>#include "logger_metrics_mongo.h"
#include "mongo/bson/bson.h"
#include "mongo/util/net/hostandport.h"
#include "jml/utils/string_functions.h"

namespace Datacratic{

using namespace std;
using namespace mongo;

LoggerMetricsMongo::LoggerMetricsMongo(Json::Value config,
    const string& coll, const string& appName) : ILoggerMetrics(coll)
{
    for(string s: {"hostAndPort", "database", "user", "pwd"}){
        if(config[s].isNull()){
            throw ML::Exception("Missing LoggerMetricsMongo parameter [%s]",
                                s.c_str());
        }
    }

    vector<string> hapStrs = ML::split(config["hostAndPort"].asString(), ',');
    if (hapStrs.size() > 1) {
        vector<HostAndPort> haps;
        for (const string & hapStr: hapStrs) {
               haps.emplace_back(hapStr);
        }
        conn.reset(new mongo::DBClientReplicaSet(hapStrs[0], haps, 100));
    }
    else {
        std::shared_ptr<DBClientConnection> tmpConn =
            make_shared<DBClientConnection>();
        tmpConn->connect(hapStrs[0]);
        conn = tmpConn;
    }
    db = config["database"].asString();
    string err;
    if(!conn->auth(db, config["user"].asString(),
                  config["pwd"].asString(), err))
    {
        cerr << __FILE__ << ":" << __LINE__ << endl;
        throw ML::Exception(
            "MongoDB connection failed with msg [%s]", err.c_str());
    }
    BSONObj obj = BSON(GENOID);
    conn->insert(db + "." + coll, obj);
    objectId = obj["_id"].OID();
    logToTerm = config["logToTerm"].asBool();
}

void LoggerMetricsMongo::logInCategory(const string& category,
    const Json::Value& json)
{
    BSONObjBuilder bson;
    vector<string> stack;
    function<void(const Json::Value&)> doit;

    auto format = [](const Json::Value& v) -> string{
        string str = v.toString();
        if(v.isInt() || v.isUInt() || v.isDouble() || v.isNumeric()){
            return str.substr(0, str.length() - 1);
        }
        return str.substr(1, str.length() - 3);
    };

    doit = [&](const Json::Value& v){
        for(auto it = v.begin(); it != v.end(); ++it){
            if(v[it.memberName()].isObject()){
                stack.push_back(it.memberName());
                doit(v[it.memberName()]);
                stack.pop_back();
            }else{
                Json::Value current = v[it.memberName()];
                stringstream key;
                key << category;
                for(string s: stack){
                    key << "." << s;
                }
                key << "." << it.memberName();
                if(current.isArray()){
                    BSONArrayBuilder arr;
                    for(const Json::Value el: current){
                        arr.append(format(el));
                    }
                    bson.append(key.str(), arr.arr());
                }else{
                    bson.append(key.str(), format(current));
                }
            }
        }
    };
    doit(json);

    if(logToTerm){
        cout << objectId << "." << coll << "." << category
             << ": " << json.toStyledString() << endl;
    }

    conn->update(db + "." + coll,
                BSON("_id" << objectId),
                BSON("$set" << bson.obj()),
                    true);
}

void LoggerMetricsMongo
::logInCategory(const std::string& category,
              const std::vector<std::string>& path,
              const NumOrStr& val)
{
    if(path.size() == 0){
        throw new ML::Exception(
            "You need to specify a path where to log the value");
    }
    stringstream ss;
    ss << val;
    stringstream newCat;
    newCat << category;
    for(string part: path){
        newCat << "." << part;
    }
    string newCatStr = newCat.str();
    string str = ss.str();

    if(logToTerm){
        cout << newCatStr << ": " << str << endl;
    }
    conn->update(db + "." + coll,
                BSON("_id" << objectId),
                BSON("$set"
                    << BSON(newCatStr << str)),
                true);
}

const std::string LoggerMetricsMongo::getProcessId() const{
    return objectId.toString();
}

}//namespace Datacratic
<commit_msg>Removed debug line<commit_after>#include "logger_metrics_mongo.h"
#include "mongo/bson/bson.h"
#include "mongo/util/net/hostandport.h"
#include "jml/utils/string_functions.h"

namespace Datacratic{

using namespace std;
using namespace mongo;

LoggerMetricsMongo::LoggerMetricsMongo(Json::Value config,
    const string& coll, const string& appName) : ILoggerMetrics(coll)
{
    for(string s: {"hostAndPort", "database", "user", "pwd"}){
        if(config[s].isNull()){
            throw ML::Exception("Missing LoggerMetricsMongo parameter [%s]",
                                s.c_str());
        }
    }

    vector<string> hapStrs = ML::split(config["hostAndPort"].asString(), ',');
    if (hapStrs.size() > 1) {
        vector<HostAndPort> haps;
        for (const string & hapStr: hapStrs) {
               haps.emplace_back(hapStr);
        }
        conn.reset(new mongo::DBClientReplicaSet(hapStrs[0], haps, 100));
    }
    else {
        std::shared_ptr<DBClientConnection> tmpConn =
            make_shared<DBClientConnection>();
        tmpConn->connect(hapStrs[0]);
        conn = tmpConn;
    }
    db = config["database"].asString();
    string err;
    if(!conn->auth(db, config["user"].asString(),
                  config["pwd"].asString(), err))
    {
        throw ML::Exception(
            "MongoDB connection failed with msg [%s]", err.c_str());
    }
    BSONObj obj = BSON(GENOID);
    conn->insert(db + "." + coll, obj);
    objectId = obj["_id"].OID();
    logToTerm = config["logToTerm"].asBool();
}

void LoggerMetricsMongo::logInCategory(const string& category,
    const Json::Value& json)
{
    BSONObjBuilder bson;
    vector<string> stack;
    function<void(const Json::Value&)> doit;

    auto format = [](const Json::Value& v) -> string{
        string str = v.toString();
        if(v.isInt() || v.isUInt() || v.isDouble() || v.isNumeric()){
            return str.substr(0, str.length() - 1);
        }
        return str.substr(1, str.length() - 3);
    };

    doit = [&](const Json::Value& v){
        for(auto it = v.begin(); it != v.end(); ++it){
            if(v[it.memberName()].isObject()){
                stack.push_back(it.memberName());
                doit(v[it.memberName()]);
                stack.pop_back();
            }else{
                Json::Value current = v[it.memberName()];
                stringstream key;
                key << category;
                for(string s: stack){
                    key << "." << s;
                }
                key << "." << it.memberName();
                if(current.isArray()){
                    BSONArrayBuilder arr;
                    for(const Json::Value el: current){
                        arr.append(format(el));
                    }
                    bson.append(key.str(), arr.arr());
                }else{
                    bson.append(key.str(), format(current));
                }
            }
        }
    };
    doit(json);

    if(logToTerm){
        cout << objectId << "." << coll << "." << category
             << ": " << json.toStyledString() << endl;
    }

    conn->update(db + "." + coll,
                BSON("_id" << objectId),
                BSON("$set" << bson.obj()),
                    true);
}

void LoggerMetricsMongo
::logInCategory(const std::string& category,
              const std::vector<std::string>& path,
              const NumOrStr& val)
{
    if(path.size() == 0){
        throw new ML::Exception(
            "You need to specify a path where to log the value");
    }
    stringstream ss;
    ss << val;
    stringstream newCat;
    newCat << category;
    for(string part: path){
        newCat << "." << part;
    }
    string newCatStr = newCat.str();
    string str = ss.str();

    if(logToTerm){
        cout << newCatStr << ": " << str << endl;
    }
    conn->update(db + "." + coll,
                BSON("_id" << objectId),
                BSON("$set"
                    << BSON(newCatStr << str)),
                true);
}

const std::string LoggerMetricsMongo::getProcessId() const{
    return objectId.toString();
}

}//namespace Datacratic
<|endoftext|>


<commit_before>#include "filesystem.h"
#include <sstream>
#include <algorithm>

namespace alpr
{

  bool startsWith(std::string const &fullString, std::string const &prefix)
  {
    if(fullString.substr(0, prefix.size()).compare(prefix) == 0) {
        return true;
    }

    return false;
  }

  bool hasEnding (std::string const &fullString, std::string const &ending)
  {
    if (fullString.length() >= ending.length())
    {
      return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
    }
    else
    {
      return false;
    }
  }

  bool hasEndingInsensitive(const std::string& fullString, const std::string& ending)
  {
    if (fullString.length() < ending.length())
      return false;

    int startidx = fullString.length() - ending.length();

    for (unsigned int i = startidx; i < fullString.length(); ++i)
        if (tolower(fullString[i]) != tolower(ending[i - startidx]))
            return false;
    return true;
  }

  bool DirectoryExists( const char* pzPath )
  {
    if ( pzPath == NULL) return false;

    DIR *pDir;
    bool bExists = false;

    pDir = opendir (pzPath);

    if (pDir != NULL)
    {
      bExists = true;
      (void) closedir (pDir);
    }

    return bExists;
  }

  bool fileExists( const char* pzPath )
  {
    if (pzPath == NULL) return false;

    bool fExists = false;
    std::ifstream f(pzPath);
    fExists = f.is_open();
    f.close();
    return fExists;
  }

  std::vector<std::string> getFilesInDir(const char* dirPath)
  {
    DIR *dir;

    std::vector<std::string> files;

    struct dirent *ent;
    if ((dir = opendir (dirPath)) != NULL)
    {
      /* print all the files and directories within directory */
      while ((ent = readdir (dir)) != NULL)
      {
        if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0)
          files.push_back(ent->d_name);
      }
      closedir (dir);
    }
    else
    {
      /* could not open directory */
      perror ("");
      return files;
    }

    return files;
  }

  bool stringCompare( const std::string &left, const std::string &right )
  {
    for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
      if( tolower( *lit ) < tolower( *rit ) )
        return true;
      else if( tolower( *lit ) > tolower( *rit ) )
        return false;
    if( left.size() < right.size() )
      return true;
    return false;
  }

  std::string filenameWithoutExtension(std::string filename)
  {
    int lastslash = filename.find_last_of("/");
    if (lastslash >= filename.size())
      lastslash = 0;
    else
      lastslash += 1;

    int lastindex = filename.find_last_of(".");

    return filename.substr(lastslash, lastindex - lastslash);
  }

  std::string get_filename_from_path(std::string file_path)
  {

    size_t found;
    found=file_path.find_last_of("/\\");

    if (found >= 0)
      return file_path.substr(found+1);

    return "";

  }

  std::string get_directory_from_path(std::string file_path)
  {
    if (DirectoryExists(file_path.c_str()))
      return file_path;

    size_t found;

    found=file_path.find_last_of("/\\");

    if (found >= 0)
      return file_path.substr(0,found);

    return "";
  }

  #ifdef WINDOWS
  // Stub out these functions on Windows.  They're used for the daemon anyway, which isn't supported on Windows.

  static int makeDir(const char *path, mode_t mode) { return 0; }
  bool makePath(const char* path, mode_t mode) {
	  std::stringstream pathstream;
	  pathstream << "mkdir " << path;
	  std::string candidate_path = pathstream.str();
	  std::replace(candidate_path.begin(), candidate_path.end(), '/', '\\');

	  system(candidate_path.c_str());
	  return true;
  }
  FileInfo getFileInfo(std::string filename) {
    FileInfo response;
    response.creation_time = 0;
    response.size = 0;
    return response;
  }

  #else

  FileInfo getFileInfo(std::string filename)
  {
    FileInfo response;

    struct stat stat_buf;
    int rc = stat(filename.c_str(), &stat_buf);
    //return rc == 0 ? stat_buf.st_size : -1;

    // 512 bytes is the standard block size
    if (rc == 0)
    {
      #if defined(__APPLE__)
            double milliseconds = (stat_buf.st_ctimespec.tv_sec * 1000) +  (((double) stat_buf.st_ctimespec.tv_nsec) / 1000000.0);
      #else
            double milliseconds = (stat_buf.st_ctim.tv_sec * 1000) +  (((double) stat_buf.st_ctim.tv_nsec) / 1000000.0);
      #endif
      response.size = 512 * stat_buf.st_blocks;
      response.creation_time = (int64_t) milliseconds;
    }
    else
    {
      response.creation_time = 0;
      response.size = 0;
    }

    return response;
  }

  static int makeDir(const char *path, mode_t mode)
  {
    struct stat            st;
    int             status = 0;

    if (stat(path, &st) != 0)
    {
        /* Directory does not exist. EEXIST for race condition */
        if (mkdir(path, mode) != 0 && errno != EEXIST)
            status = -1;
    }
    else if (!S_ISDIR(st.st_mode))
    {
        errno = ENOTDIR;
        status = -1;
    }

    return(status);
  }

  /**
  ** makePath - ensure all directories in path exist
  ** Algorithm takes the pessimistic view and works top-down to ensure
  ** each directory in path exists, rather than optimistically creating
  ** the last element and working backwards.
  */
  bool makePath(const char* path, mode_t mode)
  {

    char           *pp;
    char           *sp;
    int             status;
    char           *copypath = strdup(path);

    status = 0;
    pp = copypath;
    while (status == 0 && (sp = strchr(pp, '/')) != 0)
    {
        if (sp != pp)
        {
            /* Neither root nor double slash in path */
            *sp = '\0';
            status = makeDir(copypath, mode);
            *sp = '/';
        }
        pp = sp + 1;
    }
    if (status == 0)
        status = makeDir(path, mode);
    free(copypath);
    return (status == 0);

  }

  #endif
}
<commit_msg>Fix ifs that were always true<commit_after>#include "filesystem.h"
#include <sstream>
#include <algorithm>

namespace alpr
{

  bool startsWith(std::string const &fullString, std::string const &prefix)
  {
    if(fullString.substr(0, prefix.size()).compare(prefix) == 0) {
        return true;
    }

    return false;
  }

  bool hasEnding (std::string const &fullString, std::string const &ending)
  {
    if (fullString.length() >= ending.length())
    {
      return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
    }
    else
    {
      return false;
    }
  }

  bool hasEndingInsensitive(const std::string& fullString, const std::string& ending)
  {
    if (fullString.length() < ending.length())
      return false;

    int startidx = fullString.length() - ending.length();

    for (unsigned int i = startidx; i < fullString.length(); ++i)
        if (tolower(fullString[i]) != tolower(ending[i - startidx]))
            return false;
    return true;
  }

  bool DirectoryExists( const char* pzPath )
  {
    if ( pzPath == NULL) return false;

    DIR *pDir;
    bool bExists = false;

    pDir = opendir (pzPath);

    if (pDir != NULL)
    {
      bExists = true;
      (void) closedir (pDir);
    }

    return bExists;
  }

  bool fileExists( const char* pzPath )
  {
    if (pzPath == NULL) return false;

    bool fExists = false;
    std::ifstream f(pzPath);
    fExists = f.is_open();
    f.close();
    return fExists;
  }

  std::vector<std::string> getFilesInDir(const char* dirPath)
  {
    DIR *dir;

    std::vector<std::string> files;

    struct dirent *ent;
    if ((dir = opendir (dirPath)) != NULL)
    {
      /* print all the files and directories within directory */
      while ((ent = readdir (dir)) != NULL)
      {
        if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0)
          files.push_back(ent->d_name);
      }
      closedir (dir);
    }
    else
    {
      /* could not open directory */
      perror ("");
      return files;
    }

    return files;
  }

  bool stringCompare( const std::string &left, const std::string &right )
  {
    for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
      if( tolower( *lit ) < tolower( *rit ) )
        return true;
      else if( tolower( *lit ) > tolower( *rit ) )
        return false;
    if( left.size() < right.size() )
      return true;
    return false;
  }

  std::string filenameWithoutExtension(std::string filename)
  {
    int lastslash = filename.find_last_of("/");
    if (lastslash >= filename.size())
      lastslash = 0;
    else
      lastslash += 1;

    int lastindex = filename.find_last_of(".");

    return filename.substr(lastslash, lastindex - lastslash);
  }

  std::string get_filename_from_path(std::string file_path)
  {

    size_t found;
    found=file_path.find_last_of("/\\");

    if (found != std::string::npos)
      return file_path.substr(found+1);

    return "";

  }

  std::string get_directory_from_path(std::string file_path)
  {
    if (DirectoryExists(file_path.c_str()))
      return file_path;

    size_t found;

    found=file_path.find_last_of("/\\");

    if (found != std::string::npos)
      return file_path.substr(0,found);

    return "";
  }

  #ifdef WINDOWS
  // Stub out these functions on Windows.  They're used for the daemon anyway, which isn't supported on Windows.

  static int makeDir(const char *path, mode_t mode) { return 0; }
  bool makePath(const char* path, mode_t mode) {
	  std::stringstream pathstream;
	  pathstream << "mkdir " << path;
	  std::string candidate_path = pathstream.str();
	  std::replace(candidate_path.begin(), candidate_path.end(), '/', '\\');

	  system(candidate_path.c_str());
	  return true;
  }
  FileInfo getFileInfo(std::string filename) {
    FileInfo response;
    response.creation_time = 0;
    response.size = 0;
    return response;
  }

  #else

  FileInfo getFileInfo(std::string filename)
  {
    FileInfo response;

    struct stat stat_buf;
    int rc = stat(filename.c_str(), &stat_buf);
    //return rc == 0 ? stat_buf.st_size : -1;

    // 512 bytes is the standard block size
    if (rc == 0)
    {
      #if defined(__APPLE__)
            double milliseconds = (stat_buf.st_ctimespec.tv_sec * 1000) +  (((double) stat_buf.st_ctimespec.tv_nsec) / 1000000.0);
      #else
            double milliseconds = (stat_buf.st_ctim.tv_sec * 1000) +  (((double) stat_buf.st_ctim.tv_nsec) / 1000000.0);
      #endif
      response.size = 512 * stat_buf.st_blocks;
      response.creation_time = (int64_t) milliseconds;
    }
    else
    {
      response.creation_time = 0;
      response.size = 0;
    }

    return response;
  }

  static int makeDir(const char *path, mode_t mode)
  {
    struct stat            st;
    int             status = 0;

    if (stat(path, &st) != 0)
    {
        /* Directory does not exist. EEXIST for race condition */
        if (mkdir(path, mode) != 0 && errno != EEXIST)
            status = -1;
    }
    else if (!S_ISDIR(st.st_mode))
    {
        errno = ENOTDIR;
        status = -1;
    }

    return(status);
  }

  /**
  ** makePath - ensure all directories in path exist
  ** Algorithm takes the pessimistic view and works top-down to ensure
  ** each directory in path exists, rather than optimistically creating
  ** the last element and working backwards.
  */
  bool makePath(const char* path, mode_t mode)
  {

    char           *pp;
    char           *sp;
    int             status;
    char           *copypath = strdup(path);

    status = 0;
    pp = copypath;
    while (status == 0 && (sp = strchr(pp, '/')) != 0)
    {
        if (sp != pp)
        {
            /* Neither root nor double slash in path */
            *sp = '\0';
            status = makeDir(copypath, mode);
            *sp = '/';
        }
        pp = sp + 1;
    }
    if (status == 0)
        status = makeDir(path, mode);
    free(copypath);
    return (status == 0);

  }

  #endif
}
<|endoftext|>