<commit_before>//
// MIT License
//
// Copyright (c) 2017 Thibault Martinez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//

#pragma once

#include <iostream>

#include <cpr/cpr.h>
#include <json.hpp>

using json = nlohmann::json;

namespace IOTA {

namespace API {

class Service {
public:
  Service(const std::string& host, const unsigned int& port);
  virtual ~Service();

public:
  template <typename Request, typename Response, typename... Args>
  Response request(Args&&... args) const {
    auto request = Request(args...);

    json data;
    request.serialize(data);

    auto url     = cpr::Url{ "http://" + host_ + ":" + std::to_string(port_) };
    auto body    = cpr::Body{ data.dump() };
    auto headers = cpr::Header{ { "Content-Type", "text/json" },
                                { "Content-Length", std::to_string(body.size()) } };
    auto res     = cpr::Post(url, body, headers);

    Response response;
    response.deserialize(json::parse(res.text));
    response.setStatusCode(res.status_code);

    return response;
  }

private:
  std::string  host_;
  unsigned int port_;
};

}  // namespace API

}  // namespace IOTA
<commit_msg>text/json to application/json<commit_after>//
// MIT License
//
// Copyright (c) 2017 Thibault Martinez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//

#pragma once

#include <iostream>

#include <cpr/cpr.h>
#include <json.hpp>

using json = nlohmann::json;

namespace IOTA {

namespace API {

class Service {
public:
  Service(const std::string& host, const unsigned int& port);
  virtual ~Service();

public:
  template <typename Request, typename Response, typename... Args>
  Response request(Args&&... args) const {
    auto request = Request(args...);

    json data;
    request.serialize(data);

    auto url     = cpr::Url{ "http://" + host_ + ":" + std::to_string(port_) };
    auto body    = cpr::Body{ data.dump() };
    auto headers = cpr::Header{ { "Content-Type", "application/json" },
                                { "Content-Length", std::to_string(body.size()) } };
    auto res     = cpr::Post(url, body, headers);

    Response response;
    response.deserialize(json::parse(res.text));
    response.setStatusCode(res.status_code);

    return response;
  }

private:
  std::string  host_;
  unsigned int port_;
};

}  // namespace API

}  // namespace IOTA
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <stdexcept>
#include <cstdint>
#include <utility>
#include <iostream>

#include "optional.hpp"

namespace jest
{
  namespace detail
  { struct default_test {}; }

  /* TODO: Access to test data? */
  template <typename T, size_t N>
  void test()
  { throw detail::default_test{}; }

  namespace detail
  {
    using failure = std::string;
    using optional_failure = optional<optional<failure>>;

    struct tally_results
    { size_t const total, failed; };

    void log_failure(size_t const n, std::string const &msg)
    { std::cerr << "  test " << n << " failure: " << msg << std::endl; }
    void log_success(size_t const n)
    { std::cerr << "  test " << n << " success" << std::endl; }

    template <typename Group, size_t TN>
    optional_failure test_impl(Group &g)
    {
      try
      {
        g.test<TN>();
        return {{}};
      }
      catch(std::exception const &e)
      { return {{ e.what() }}; }
      catch(default_test)
      { return {}; }
      catch(...)
      { return {{ "unknown exception thrown" }}; }
    }

    template <typename Group, size_t... Ns>
    tally_results run_impl(Group &g, std::string const &name,
                           std::integer_sequence<size_t, Ns...>)
    {
      std::cerr << "running group '" + name << "'" << std::endl;
      optional_failure const results[]{ test_impl<Group, Ns>(g)... };
      size_t total{}, failed{};
      for(size_t i{}; i < sizeof...(Ns); ++i)
      {
        if(results[i])
        {
          ++total;
          if(results[i].value())
          {
            log_failure(i, results[i].value().value());
            ++failed;
          }
          else
          { log_success(i); }
        }
      }
      std::cerr << "finished group '" + name << "'\n" << std::endl;
      return { total, failed };
    }
  }
}
<commit_msg>Fixed clang-specific errors on OS X<commit_after>#pragma once

#include <string>
#include <stdexcept>
#include <cstdint>
#include <utility>
#include <iostream>

#include "optional.hpp"

namespace jest
{
  namespace detail
  { struct default_test {}; }

  /* TODO: Access to test data? */
  template <typename T, size_t N>
  void test()
  { throw detail::default_test{}; }

  namespace detail
  {
    using failure = std::string;
    using optional_failure = optional<optional<failure>>;

    struct tally_results
    { size_t const total, failed; };

    void log_failure(size_t const n, std::string const &msg)
    { std::cerr << "  test " << n << " failure: " << msg << std::endl; }
    void log_success(size_t const n)
    { std::cerr << "  test " << n << " success" << std::endl; }

    template <typename Group, size_t TN>
    optional_failure test_impl(Group &g)
    {
      try
      {
        g.template test<TN>();
        return {{}};
      }
      catch(std::exception const &e)
      { return {{ e.what() }}; }
      catch(default_test)
      { return {}; }
      catch(...)
      { return {{ "unknown exception thrown" }}; }
    }

    template <typename Group, size_t... Ns>
    tally_results run_impl(Group &g, std::string const &name,
                           std::integer_sequence<size_t, Ns...>)
    {
      std::cerr << "running group '" + name << "'" << std::endl;
      optional_failure const results[]{ test_impl<Group, Ns>(g)... };
      size_t total{}, failed{};
      for(size_t i{}; i < sizeof...(Ns); ++i)
      {
        if(results[i])
        {
          ++total;
          if(results[i].value())
          {
            log_failure(i, results[i].value().value());
            ++failed;
          }
          else
          { log_success(i); }
        }
      }
      std::cerr << "finished group '" + name << "'\n" << std::endl;
      return { total, failed };
    }
  }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#include <string>
#include <fstream>
#include <iostream>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/lexical_cast.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

namespace libtorrent
{
	// DEBUG API

	namespace fs = boost::filesystem;

	struct logger
	{
		logger(fs::path const& filename, int instance, bool append = true)
		{
			fs::path dir(fs::complete("libtorrent_logs" + boost::lexical_cast<std::string>(instance)));
			if (!fs::exists(dir)) fs::create_directories(dir);
			m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
			*this << "\n\n\n*** starting log ***\n";
		}

		template <class T>
		logger& operator<<(T const& v)
		{
			m_file << v;
			m_file.flush();
			return *this;
		}

		std::ofstream m_file;
	};

}

#endif // TORRENT_DEBUG_HPP_INCLUDED

<commit_msg>fixes issue whith failure to create logs causes libtorrent to quit, fixes ticket #168<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#include <string>
#include <fstream>
#include <iostream>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/lexical_cast.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

namespace libtorrent
{
	// DEBUG API

	namespace fs = boost::filesystem;

	struct logger
	{
		logger(fs::path const& filename, int instance, bool append = true)
		{
			try
			{
				fs::path dir(fs::complete("libtorrent_logs" + boost::lexical_cast<std::string>(instance)));
				if (!fs::exists(dir)) fs::create_directories(dir);
				m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
				*this << "\n\n\n*** starting log ***\n";
			}
			catch (std::exception& e)
			{
				std::cerr << "failed to create log '" << filename << "': " << e.what() << std::endl;
			}
		}

		template <class T>
		logger& operator<<(T const& v)
		{
			m_file << v;
			m_file.flush();
			return *this;
		}

		std::ofstream m_file;
	};

}

#endif // TORRENT_DEBUG_HPP_INCLUDED

<|endoftext|>


<commit_before>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#include <config.h>

#include <kuniqueapplication.h>
#include <kglobal.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include "kmkernel.h" //control center
#include <kcmdlineargs.h>
#include <qtimer.h>

#undef Status // stupid X headers

#include "aboutdata.h"

#include "kmstartup.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of message."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'address'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to message."), 0 },
  { "msg <file>",		I18N_NOOP("Read message body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of message."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail. This can be repeated."), 0 },
  { "check",			I18N_NOOP("Only check for new mail."), 0 },
  { "composer",			I18N_NOOP("Only open composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send message to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

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

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };
  virtual int newInstance();
  void commitData(QSessionManager& sm);

};

void KMailApplication::commitData(QSessionManager& sm) {
  kmkernel->dumpDeadLetters();
  kmkernel->setShuttingDown( true ); // Prevent further dumpDeadLetters calls
  KApplication::commitData( sm );
}

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  if (dcopClient()->isSuspended())
  {
    // Try again later.
    QTimer::singleShot( 100, this, SLOT(newInstance()) );
    return 0;
  }

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile.setPath( QString::fromLocal8Bit(args->getOption("msg")) );
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->url(i).path();
     else
       to += QString::fromLocal8Bit( args->arg(i) );
     mailto = true;
  }

  args->clear();

  if (!kmkernel->firstInstance() || !kapp->isRestored())
    kmkernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kmkernel->setFirstInstance(FALSE);
  return 0;
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KMail::AboutData about;

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options
  if (!KMailApplication::start())
     return 0;

  KMailApplication app;

  // import i18n data from libraries:
  KMail::insertLibraryCatalogues();

  // Check that all updates have been run on the config file:
  KMail::checkConfigUpdates();

  // Make sure that the KNotify Daemon is running (this is necessary for people
  // using KMail without KDE)
  KNotifyClient::startDaemon();

  KMail::lockOrDie();

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  kmsetSignalHandler(kmsignalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  kmkernel->setStartingUp( false ); // Starting up is finished
  // Go!
  int ret = kapp->exec();
  // clean up
  if (kmkernel->shuttingDown())
      kmailKernel.notClosedByUser();
  else
      kmailKernel.cleanup();

  KMail::cleanup();
  return ret;
}
<commit_msg>Make it possible to pass a URL to kmail without the --attachment flag. According to Laurent this is done automatically in case a file is dropped on the KMail icon in Kicker. Based on patch by Laurent Montel.<commit_after>// -*- mode: C++; c-file-style: "gnu" -*-
// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#include <config.h>

#include <kuniqueapplication.h>
#include <kglobal.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include "kmkernel.h" //control center
#include <kcmdlineargs.h>
#include <qtimer.h>

#undef Status // stupid X headers

#include "aboutdata.h"

#include "kmstartup.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of message."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'address'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to message."), 0 },
  { "msg <file>",		I18N_NOOP("Read message body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of message."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail. This can be repeated."), 0 },
  { "check",			I18N_NOOP("Only check for new mail."), 0 },
  { "composer",			I18N_NOOP("Only open composer window."), 0 },
  { "+[address|URL]",		I18N_NOOP("Send message to 'address' resp. "
                                          "attach the file the 'URL' points "
                                          "to."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

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

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };
  virtual int newInstance();
  void commitData(QSessionManager& sm);

};

void KMailApplication::commitData(QSessionManager& sm) {
  kmkernel->dumpDeadLetters();
  kmkernel->setShuttingDown( true ); // Prevent further dumpDeadLetters calls
  KApplication::commitData( sm );
}

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  if (dcopClient()->isSuspended())
  {
    // Try again later.
    QTimer::singleShot( 100, this, SLOT(newInstance()) );
    return 0;
  }

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile.setPath( QString::fromLocal8Bit(args->getOption("msg")) );
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (strncasecmp(args->arg(i),"mailto:",7)==0)
      to += args->url(i).path() + ", ";
    else {
      QString tmpArg = QString::fromLocal8Bit( args->arg(i) );
      KURL url( tmpArg );
      if ( url.isValid() )
        attachURLs += url;
      else
        to += tmpArg + ", ";
    }
    mailto = true;
  }
  if ( !to.isEmpty() ) {
    // cut off the superfluous trailing ", "
    to.truncate( to.length() - 2 );
  }

  args->clear();

  if (!kmkernel->firstInstance() || !kapp->isRestored())
    kmkernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kmkernel->setFirstInstance(FALSE);
  return 0;
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KMail::AboutData about;

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options
  if (!KMailApplication::start())
     return 0;

  KMailApplication app;

  // import i18n data from libraries:
  KMail::insertLibraryCatalogues();

  // Check that all updates have been run on the config file:
  KMail::checkConfigUpdates();

  // Make sure that the KNotify Daemon is running (this is necessary for people
  // using KMail without KDE)
  KNotifyClient::startDaemon();

  KMail::lockOrDie();

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  kmsetSignalHandler(kmsignalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  kmkernel->setStartingUp( false ); // Starting up is finished
  // Go!
  int ret = kapp->exec();
  // clean up
  if (kmkernel->shuttingDown())
      kmailKernel.notClosedByUser();
  else
      kmailKernel.cleanup();

  KMail::cleanup();
  return ret;
}
<|endoftext|>


<commit_before>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <qtimer.h>

#include <kuniqueapplication.h>
#include <klocale.h>
#include <kglobal.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of message."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'address'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to message."), 0 },
  { "msg <file>",		I18N_NOOP("Read message body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of message."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail. This can be repeated."), 0 },
  { "check",			I18N_NOOP("Only check for new mail."), 0 },
  { "composer",			I18N_NOOP("Only open composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send message to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

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

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();

  void commitData(QSessionManager& sm) {
    kernel->notClosedByUser();
    KApplication::commitData( sm );
  }
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  if (!kernel->firstInstance() || !kapp->isRestored())
    kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kernel->setFirstInstance(FALSE);
  return 0;
}

namespace
{
QString getMyHostName(void)
{
  char hostNameC[256];
  // null terminate this C string
  hostNameC[255] = 0;
  // set the string to 0 length if gethostname fails
  if(gethostname(hostNameC, 255))
    hostNameC[0] = 0;
  return QString::fromLocal8Bit(hostNameC);
}
}

static void checkConfigUpdates() {
#if KDE_VERSION >= 306
  KConfig * config = kapp->config();
  const QString updateFile = QString::fromLatin1("kmail.upd");
  QStringList updates;
  updates << "9"
	  << "3.1-update-identities"
	  << "3.1-use-identity-uoids";
  for ( QStringList::const_iterator it = updates.begin() ; it != updates.end() ; ++it )
    config->checkUpdate( *it, updateFile );
#endif
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("The KDE Email client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2002, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Michael H\303\244ckel", I18N_NOOP("Current maintainer"), "haeckel@kde.org" );
  about.addAuthor( "Don Sanders", I18N_NOOP("Core developer and former maintainer"), "sanders@kde.org" );
  about.addAuthor( "Stefan Taferner ", I18N_NOOP("Original author"), "taferner@kde.org" );
  about.addAuthor( "Ingo Kl\303\266cker", I18N_NOOP("Encryption"), "kloecker@kde.de" );
  about.addAuthor( "Marc Mutz", I18N_NOOP("Core developer"), "mutz@kde.org" );
  about.addAuthor( "Daniel Naber", I18N_NOOP("Documentation"), "daniel.naber@t-online.de" );
  about.addAuthor( "Andreas Gungl", I18N_NOOP("Encryption"), "a.gungl@gmx.de" );

  about.addAuthor( "Toyohiro Asukai", 0, "toyohiro@ksmplus.com" );
  about.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
  about.addAuthor( "Carsten Burghardt", 0, "carsten.burghardt@web.de" );
  about.addAuthor( "Steven Brown", 0, "swbrown@ucsd.edu" );
  about.addAuthor( "Cristi Dumitrescu", 0, "cristid@chip.ro" );
  about.addAuthor( "Philippe Fremy", 0, "pfremy@chez.com" );
  about.addAuthor( "Kurt Granroth", 0, "granroth@kde.org" );
  about.addAuthor( "Heiko Hund", 0, "heiko@ist.eigentlich.net" );
  about.addAuthor( "Igor Janssen", 0, "rm@linux.ru.net" );
  about.addAuthor( "Matt Johnston", 0, "matt@caifex.org" );
  about.addAuthor( "Christer Kaivo-oja", 0, "whizkid@telia.com" );
  about.addAuthor( "Lars Knoll", 0, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", 0, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", 0, "coolo@kde.org" );
  about.addAuthor( "Guillaume Laurent", 0, "glaurent@telegraph-road.org" );
  about.addAuthor( "Sam Magnuson", 0, "sam@trolltech.com" );
  about.addAuthor( "Laurent Montel", 0, "lmontel@mandrakesoft.com" );
  about.addAuthor( "Matt Newell", 0, "newellm@proaxis.com" );
  about.addAuthor( "Denis Perchine", 0, "dyp@perchine.com" );
  about.addAuthor( "Samuel Penn", 0, "sam@bifrost.demon.co.uk" );
  about.addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org" );
  about.addAuthor( "Sven Radej", 0, "radej@kde.org" );
  about.addAuthor( "Mark Roberts", 0, "mark@taurine.demon.co.uk" );
  about.addAuthor( "Wolfgang Rohdewald", 0, "wrohdewald@dplanet.ch" );
  about.addAuthor( "Espen Sand", 0, "espen@kde.org" );
  about.addAuthor( "Jan Simonson", 0, "jan@simonson.pp.se" );
  about.addAuthor( "George Staikos", 0, "staikos@kde.org" );
  about.addAuthor( "Jason Stephenson", 0, "panda@mis.net" );
  about.addAuthor( "Jacek Stolarczyk", 0, "jacek@mer.chemia.polsl.gliwice.pl" );
  about.addAuthor( "Roberto S. Teixeira", 0, "maragato@kde.org" );
  about.addAuthor( "Ronen Tzur", 0, "rtzur@shani.net" );
  about.addAuthor( "Mario Weilguni", 0, "mweilguni@sime.com" );
  about.addAuthor( "Wynn Wilkes", 0, "wynnw@calderasystems.com" );
  about.addAuthor( "Robert D. Williams", 0, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", 0, "markus.wuebben@kde.org" );
  about.addAuthor( "Thorsten Zachmann", 0, "t.zachmann@zagge.de" );
  about.addAuthor( "Karl-Heinz Zimmer", 0, "khz@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  // Check that all updates have been run on the config file:
  checkConfigUpdates();

  // Check and create a lock file to prevent concurrent access to kmail files
  const QString lockLocation = locateLocal("appdata", "lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString hostName = getMyHostName();
  // proceed if there is no lock at present
  if (oldPid != -1 &&
  // proceed if the lock is our pid, or if the lock is from the same host
      oldPid != getpid() && hostName != oldHostName &&
  // proceed if the pid doesn't exist
      (kill(oldPid, 0) != -1 || errno != ESRCH))
  {
    QString msg = i18n("Only one instance of KMail can be run at "
      "any one time. It is already running on a different display "
      "with PID %1 on host %2 according to the lock file located "
      "at %3.").arg(oldPid).arg(oldHostName).arg(lockLocation);

    KNotifyClient::userEvent( msg,  KNotifyClient::Messagebox,
      KNotifyClient::Error );
    fprintf(stderr, "*** KMail is already running with PID %d on host %s\n",
            oldPid, oldHostName.local8Bit().data());
    return 1;
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.sync();

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  config.writeEntry("pid", -1);
  config.sync();
  return ret;
}

<commit_msg>Restore my position as a maintainer. Because:<commit_after>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <qtimer.h>

#include <kuniqueapplication.h>
#include <klocale.h>
#include <kglobal.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of message."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'address'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to message."), 0 },
  { "msg <file>",		I18N_NOOP("Read message body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of message."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail. This can be repeated."), 0 },
  { "check",			I18N_NOOP("Only check for new mail."), 0 },
  { "composer",			I18N_NOOP("Only open composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send message to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

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

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();

  void commitData(QSessionManager& sm) {
    kernel->notClosedByUser();
    KApplication::commitData( sm );
  }
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  if (!kernel->firstInstance() || !kapp->isRestored())
    kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kernel->setFirstInstance(FALSE);
  return 0;
}

namespace
{
QString getMyHostName(void)
{
  char hostNameC[256];
  // null terminate this C string
  hostNameC[255] = 0;
  // set the string to 0 length if gethostname fails
  if(gethostname(hostNameC, 255))
    hostNameC[0] = 0;
  return QString::fromLocal8Bit(hostNameC);
}
}

static void checkConfigUpdates() {
#if KDE_VERSION >= 306
  KConfig * config = kapp->config();
  const QString updateFile = QString::fromLatin1("kmail.upd");
  QStringList updates;
  updates << "9"
	  << "3.1-update-identities"
	  << "3.1-use-identity-uoids";
  for ( QStringList::const_iterator it = updates.begin() ; it != updates.end() ; ++it )
    config->checkUpdate( *it, updateFile );
#endif
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("The KDE Email client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2002, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Michael H\303\244ckel", I18N_NOOP("Current maintainer"), "haeckel@kde.org" );
  about.addAuthor( "Don Sanders", I18N_NOOP("Core developer and maintainer"), "sanders@kde.org" );
  about.addAuthor( "Stefan Taferner ", I18N_NOOP("Original author"), "taferner@kde.org" );
  about.addAuthor( "Ingo Kl\303\266cker", I18N_NOOP("Encryption"), "kloecker@kde.de" );
  about.addAuthor( "Marc Mutz", I18N_NOOP("Core developer"), "mutz@kde.org" );
  about.addAuthor( "Daniel Naber", I18N_NOOP("Documentation"), "daniel.naber@t-online.de" );
  about.addAuthor( "Andreas Gungl", I18N_NOOP("Encryption"), "a.gungl@gmx.de" );

  about.addAuthor( "Toyohiro Asukai", 0, "toyohiro@ksmplus.com" );
  about.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
  about.addAuthor( "Carsten Burghardt", 0, "carsten.burghardt@web.de" );
  about.addAuthor( "Steven Brown", 0, "swbrown@ucsd.edu" );
  about.addAuthor( "Cristi Dumitrescu", 0, "cristid@chip.ro" );
  about.addAuthor( "Philippe Fremy", 0, "pfremy@chez.com" );
  about.addAuthor( "Kurt Granroth", 0, "granroth@kde.org" );
  about.addAuthor( "Heiko Hund", 0, "heiko@ist.eigentlich.net" );
  about.addAuthor( "Igor Janssen", 0, "rm@linux.ru.net" );
  about.addAuthor( "Matt Johnston", 0, "matt@caifex.org" );
  about.addAuthor( "Christer Kaivo-oja", 0, "whizkid@telia.com" );
  about.addAuthor( "Lars Knoll", 0, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", 0, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", 0, "coolo@kde.org" );
  about.addAuthor( "Guillaume Laurent", 0, "glaurent@telegraph-road.org" );
  about.addAuthor( "Sam Magnuson", 0, "sam@trolltech.com" );
  about.addAuthor( "Laurent Montel", 0, "lmontel@mandrakesoft.com" );
  about.addAuthor( "Matt Newell", 0, "newellm@proaxis.com" );
  about.addAuthor( "Denis Perchine", 0, "dyp@perchine.com" );
  about.addAuthor( "Samuel Penn", 0, "sam@bifrost.demon.co.uk" );
  about.addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org" );
  about.addAuthor( "Sven Radej", 0, "radej@kde.org" );
  about.addAuthor( "Mark Roberts", 0, "mark@taurine.demon.co.uk" );
  about.addAuthor( "Wolfgang Rohdewald", 0, "wrohdewald@dplanet.ch" );
  about.addAuthor( "Espen Sand", 0, "espen@kde.org" );
  about.addAuthor( "Jan Simonson", 0, "jan@simonson.pp.se" );
  about.addAuthor( "George Staikos", 0, "staikos@kde.org" );
  about.addAuthor( "Jason Stephenson", 0, "panda@mis.net" );
  about.addAuthor( "Jacek Stolarczyk", 0, "jacek@mer.chemia.polsl.gliwice.pl" );
  about.addAuthor( "Roberto S. Teixeira", 0, "maragato@kde.org" );
  about.addAuthor( "Ronen Tzur", 0, "rtzur@shani.net" );
  about.addAuthor( "Mario Weilguni", 0, "mweilguni@sime.com" );
  about.addAuthor( "Wynn Wilkes", 0, "wynnw@calderasystems.com" );
  about.addAuthor( "Robert D. Williams", 0, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", 0, "markus.wuebben@kde.org" );
  about.addAuthor( "Thorsten Zachmann", 0, "t.zachmann@zagge.de" );
  about.addAuthor( "Karl-Heinz Zimmer", 0, "khz@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  // Check that all updates have been run on the config file:
  checkConfigUpdates();

  // Check and create a lock file to prevent concurrent access to kmail files
  const QString lockLocation = locateLocal("appdata", "lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString hostName = getMyHostName();
  // proceed if there is no lock at present
  if (oldPid != -1 &&
  // proceed if the lock is our pid, or if the lock is from the same host
      oldPid != getpid() && hostName != oldHostName &&
  // proceed if the pid doesn't exist
      (kill(oldPid, 0) != -1 || errno != ESRCH))
  {
    QString msg = i18n("Only one instance of KMail can be run at "
      "any one time. It is already running on a different display "
      "with PID %1 on host %2 according to the lock file located "
      "at %3.").arg(oldPid).arg(oldHostName).arg(lockLocation);

    KNotifyClient::userEvent( msg,  KNotifyClient::Messagebox,
      KNotifyClient::Error );
    fprintf(stderr, "*** KMail is already running with PID %d on host %s\n",
            oldPid, oldHostName.local8Bit().data());
    return 1;
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.sync();

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  config.writeEntry("pid", -1);
  config.sync();
  return ret;
}

<|endoftext|>


<commit_before>/* Definition of the pqxx::stream_from class.
 *
 * pqxx::stream_from enables optimized batch reads from a database table.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
 *
 * Copyright (c) 2000-2021, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_STREAM_FROM
#define PQXX_H_STREAM_FROM

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cassert>
#include <functional>
#include <variant>

#include "pqxx/except.hxx"
#include "pqxx/internal/concat.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/internal/stream_iterator.hxx"
#include "pqxx/separated_list.hxx"
#include "pqxx/transaction_base.hxx"
#include "pqxx/transaction_focus.hxx"

namespace pqxx
{
/// Pass this to a @c stream_from constructor to stream table contents.
/** @deprecated Use stream_from::table() instead.
 */
constexpr from_table_t from_table;
/// Pass this to a @c stream_from constructor to stream query results.
/** @deprecated Use stream_from::query() instead.
 */
constexpr from_query_t from_query;

/// Stream data from the database.
/** Retrieving data this way is likely to be faster than executing a query and
 * then iterating and converting the rows fields.  You will also be able to
 * start processing before all of the data has come in.
 *
 * There are also downsides.  If there's an error, it may leave the entire
 * connection in an unusable state, so you'll have to give the whole thing up.
 * Also, your connection to the database may break before you've received all
 * the data, so you may end up processing only part of the data.  Finally,
 * opening a stream puts the connection in a special state, so you won't be
 * able to do many other things with the connection or the transaction while
 * the stream is open.
 *
 * There are two ways of starting a stream: you stream either all rows in a
 * table (using one of the factories, @c table() or @c raw_table()), or the
 * results of a query (using the @c query() factory).
 *
 * Usually you'll want the @c stream convenience wrapper in transaction_base,
 * so you don't need to deal with this class directly.
 *
 * @warning While a stream is active, you cannot execute queries, open a
 * pipeline, etc. on the same transaction.  A transaction can have at most one
 * object of a type derived from @c pqxx::transaction_focus active on it at a
 * time.
 */
class PQXX_LIBEXPORT stream_from : transaction_focus
{
public:
  using raw_line =
    std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;

  /// Factory: Execute query, and stream the results.
  /** The query can be a SELECT query or a VALUES query; or it can be an
   * UPDATE, INSERT, or DELETE with a RETURNING clause.
   *
   * The query is executed as part of a COPY statement, so there are additional
   * restrictions on what kind of query you can use here.  See the PostgreSQL
   * documentation for the COPY command:
   *
   *     https://www.postgresql.org/docs/current/sql-copy.html
   */
  static stream_from query(transaction_base &tx, std::string_view q)
  {
#include "pqxx/internal/ignore-deprecated-pre.hxx"
    return stream_from{tx, from_query, q};
#include "pqxx/internal/ignore-deprecated-post.hxx"
  }

  /**
   * @name Streaming data from tables
   *
   * You can use @c stream_from to read a table's contents.  This is a quick
   * and easy way to read a table, but it comes with limitations.  It cannot
   * stream from a view, only from a table.  It does not support conditions.
   * And there are no guarantees about ordering.  If you need any of those
   * things, consider streaming from a query instead.
   */
  //@{

  /// Factory: Stream data from a pre-quoted table and columns.
  /** Use this factory if you need to create multiple streams using the same
   * table path and/or columns list, and you want to save a bit of work on
   * composing the internal SQL statement for starting the stream.  It lets you
   * compose the string representations for the table path and the columns
   * list, so you can compute these once and then re-use them later.
   *
   * @param tx The transaction within which the stream will operate.
   * @param path Name or path for the table upon which the stream will
   *     operate.  If any part of the table path may contain special
   *     characters or be case-sensitive, quote the path using
   *     pqxx::connection::quote_table().
   * @param columns Columns which the stream will read.  They should be
   *     comma-separated and, if needed, quoted.  You can produce the string
   *     using pqxx::connection::quote_columns().  If you omit this argument,
   *     the stream will read all columns in the table, in schema order.
   */
  static stream_from raw_table(
    transaction_base &tx, std::string_view path,
    std::string_view columns = ""sv);

  /// Factory: Stream data from a given table.
  /** This is the convenient way to stream from a table.
   */
  static stream_from table(
    transaction_base &tx, table_path path,
    std::initializer_list<std::string_view> columns = {});
  //@}

  /// Execute query, and stream over the results.
  /** @deprecated Use factory function @c query() instead.
   */
  PQXX_DEPRECATED("Use query() factory instead.")
  stream_from(transaction_base &, from_query_t, std::string_view query);

  /// Stream all rows in table, all columns.
  /** @deprecated Use factory function @c table() or @c raw_table() instead.
   */
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(transaction_base &, from_table_t, std::string_view table);

  /// Stream given columns from all rows in table.
  /** @deprecated Use factory function @c table() or @c raw_table() instead.
   */
  template<typename Iter>
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(
    transaction_base &, from_table_t, std::string_view table,
    Iter columns_begin, Iter columns_end);

  /// Stream given columns from all rows in table.
  /** @deprecated Use factory function @c query() instead.
   */
  template<typename Columns>
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(
    transaction_base &tx, from_table_t, std::string_view table,
    Columns const &columns);

#include "pqxx/internal/ignore-deprecated-pre.hxx"
  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(transaction_base &tx, std::string_view table) :
          stream_from{tx, from_table, table}
  {}
#include "pqxx/internal/ignore-deprecated-post.hxx"

  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  template<typename Columns>
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(
    transaction_base &tx, std::string_view table, Columns const &columns) :
          stream_from{tx, from_table, table, columns}
  {}

  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  template<typename Iter>
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(
    transaction_base &, std::string_view table, Iter columns_begin,
    Iter columns_end);

  ~stream_from() noexcept;

  /// May this stream still produce more data?
  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
  /// Has this stream produced all the data it is going to produce?
  [[nodiscard]] bool operator!() const noexcept { return m_finished; }

  /// Finish this stream.  Call this before continuing to use the connection.
  /** Consumes all remaining lines, and closes the stream.
   *
   * This may take a while if you're abandoning the stream before it's done, so
   * skip it in error scenarios where you're not planning to use the connection
   * again afterwards.
   */
  void complete();

  /// Read one row into a tuple.
  /** Converts the row's fields into the fields making up the tuple.
   *
   * For a column which can contain nulls, be sure to give the corresponding
   * tuple field a type which can be null.  For example, to read a field as
   * @c int when it may contain nulls, read it as @c std::optional<int>.
   * Using @c std::shared_ptr or @c std::unique_ptr will also work.
   */
  template<typename Tuple> stream_from &operator>>(Tuple &);

  /// Doing this with a @c std::variant is going to be horrifically borked.
  template<typename... Vs>
  stream_from &operator>>(std::variant<Vs...> &) = delete;

  // TODO: Hide this from the public.
  /// Iterate over this stream.  Supports range-based "for" loops.
  /** Produces an input iterator over the stream.
   *
   * Do not call this yourself.  Use it like "for (auto data : stream.iter())".
   */
  template<typename... TYPE> [[nodiscard]] auto iter()
  {
    return pqxx::internal::stream_input_iteration<TYPE...>{*this};
  }

  /// Read a row.  Return fields as views, valid until you read the next row.
  /** Returns @c nullptr when there are no more rows to read.  Do not attempt
   * to read any further rows after that.
   *
   * Do not access the vector, or the storage referenced by the views, after
   * closing or completing the stream, or after attempting to read a next row.
   *
   * A @c pqxx::zview is like a @c std::string_view, but with the added
   * guarantee that if its data pointer is non-null, the string is followed by
   * a terminating zero (which falls just outside the view itself).
   *
   * If any of the views' data pointer is null, that means that the
   * corresponding SQL field is null.
   *
   * @warning The return type may change in the future, to support C++20
   * coroutine-based usage.
   */
  std::vector<zview> const *read_row();

  /// Read a raw line of text from the COPY command.
  /** @warning Do not use this unless you really know what you're doing. */
  raw_line get_raw_line();

private:
  // TODO: Clean up this signature once we cull the deprecated constructors.
  /// @deprecated
  stream_from(
    transaction_base &tx, std::string_view table, std::string_view columns,
    from_table_t);

  // TODO: Clean up this signature once we cull the deprecated constructors.
  /// @deprecated
  stream_from(
    transaction_base &, std::string_view unquoted_table,
    std::string_view columns, from_table_t, int);

  template<typename Tuple, std::size_t... indexes>
  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
  {
    (extract_value<Tuple, indexes>(t), ...);
  }

  pqxx::internal::glyph_scanner_func *m_glyph_scanner;

  /// Current row's fields' text, combined into one reusable string.
  std::string m_row;

  /// The current row's fields.
  std::vector<zview> m_fields;

  bool m_finished = false;

  void close();

  template<typename Tuple, std::size_t index>
  void extract_value(Tuple &) const;

  /// Read a line of COPY data, write @c m_row and @c m_fields.
  void parse_line();
};

template<typename Columns>
inline stream_from::stream_from(
  transaction_base &tb, from_table_t, std::string_view table_name,
  Columns const &columns) :
        stream_from{
          tb, from_table, table_name, std::begin(columns), std::end(columns)}
{}

template<typename Iter>
inline stream_from::stream_from(
  transaction_base &tx, from_table_t, std::string_view table,
  Iter columns_begin, Iter columns_end) :
        stream_from{
          tx, table, separated_list(",", columns_begin, columns_end),
          from_table, 1}
{}

template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
{
  if (m_finished)
    return *this;
  constexpr auto tup_size{std::tuple_size_v<Tuple>};
  m_fields.reserve(tup_size);
  parse_line();
  if (m_finished)
    return *this;

  if (std::size(m_fields) != tup_size)
    throw usage_error{internal::concat(
      "Tried to extract ", tup_size, " field(s) from a stream of ",
      std::size(m_fields), ".")};

  extract_fields(t, std::make_index_sequence<tup_size>{});
  return *this;
}

template<typename Tuple, std::size_t index>
inline void stream_from::extract_value(Tuple &t) const
{
  using field_type = strip_t<decltype(std::get<index>(t))>;
  using nullity = nullness<field_type>;
  assert(index < std::size(m_fields));
  if constexpr (nullity::always_null)
  {
    if (m_fields[index].data() != nullptr)
      throw conversion_error{"Streaming non-null value into null field."};
  }
  else if (m_fields[index].data() == nullptr)
  {
    if constexpr (nullity::has_null)
      std::get<index>(t) = nullity::null();
    else
      internal::throw_null_conversion(type_name<field_type>);
  }
  else
  {
    // Don't ever try to convert a non-null value to nullptr_t!
    std::get<index>(t) = from_string<field_type>(m_fields[index]);
  }
}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<commit_msg>Retire a TODO.<commit_after>/* Definition of the pqxx::stream_from class.
 *
 * pqxx::stream_from enables optimized batch reads from a database table.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
 *
 * Copyright (c) 2000-2021, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_STREAM_FROM
#define PQXX_H_STREAM_FROM

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cassert>
#include <functional>
#include <variant>

#include "pqxx/except.hxx"
#include "pqxx/internal/concat.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/internal/stream_iterator.hxx"
#include "pqxx/separated_list.hxx"
#include "pqxx/transaction_base.hxx"
#include "pqxx/transaction_focus.hxx"

namespace pqxx
{
/// Pass this to a @c stream_from constructor to stream table contents.
/** @deprecated Use stream_from::table() instead.
 */
constexpr from_table_t from_table;
/// Pass this to a @c stream_from constructor to stream query results.
/** @deprecated Use stream_from::query() instead.
 */
constexpr from_query_t from_query;

/// Stream data from the database.
/** Retrieving data this way is likely to be faster than executing a query and
 * then iterating and converting the rows fields.  You will also be able to
 * start processing before all of the data has come in.
 *
 * There are also downsides.  If there's an error, it may leave the entire
 * connection in an unusable state, so you'll have to give the whole thing up.
 * Also, your connection to the database may break before you've received all
 * the data, so you may end up processing only part of the data.  Finally,
 * opening a stream puts the connection in a special state, so you won't be
 * able to do many other things with the connection or the transaction while
 * the stream is open.
 *
 * There are two ways of starting a stream: you stream either all rows in a
 * table (using one of the factories, @c table() or @c raw_table()), or the
 * results of a query (using the @c query() factory).
 *
 * Usually you'll want the @c stream convenience wrapper in transaction_base,
 * so you don't need to deal with this class directly.
 *
 * @warning While a stream is active, you cannot execute queries, open a
 * pipeline, etc. on the same transaction.  A transaction can have at most one
 * object of a type derived from @c pqxx::transaction_focus active on it at a
 * time.
 */
class PQXX_LIBEXPORT stream_from : transaction_focus
{
public:
  using raw_line =
    std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;

  /// Factory: Execute query, and stream the results.
  /** The query can be a SELECT query or a VALUES query; or it can be an
   * UPDATE, INSERT, or DELETE with a RETURNING clause.
   *
   * The query is executed as part of a COPY statement, so there are additional
   * restrictions on what kind of query you can use here.  See the PostgreSQL
   * documentation for the COPY command:
   *
   *     https://www.postgresql.org/docs/current/sql-copy.html
   */
  static stream_from query(transaction_base &tx, std::string_view q)
  {
#include "pqxx/internal/ignore-deprecated-pre.hxx"
    return stream_from{tx, from_query, q};
#include "pqxx/internal/ignore-deprecated-post.hxx"
  }

  /**
   * @name Streaming data from tables
   *
   * You can use @c stream_from to read a table's contents.  This is a quick
   * and easy way to read a table, but it comes with limitations.  It cannot
   * stream from a view, only from a table.  It does not support conditions.
   * And there are no guarantees about ordering.  If you need any of those
   * things, consider streaming from a query instead.
   */
  //@{

  /// Factory: Stream data from a pre-quoted table and columns.
  /** Use this factory if you need to create multiple streams using the same
   * table path and/or columns list, and you want to save a bit of work on
   * composing the internal SQL statement for starting the stream.  It lets you
   * compose the string representations for the table path and the columns
   * list, so you can compute these once and then re-use them later.
   *
   * @param tx The transaction within which the stream will operate.
   * @param path Name or path for the table upon which the stream will
   *     operate.  If any part of the table path may contain special
   *     characters or be case-sensitive, quote the path using
   *     pqxx::connection::quote_table().
   * @param columns Columns which the stream will read.  They should be
   *     comma-separated and, if needed, quoted.  You can produce the string
   *     using pqxx::connection::quote_columns().  If you omit this argument,
   *     the stream will read all columns in the table, in schema order.
   */
  static stream_from raw_table(
    transaction_base &tx, std::string_view path,
    std::string_view columns = ""sv);

  /// Factory: Stream data from a given table.
  /** This is the convenient way to stream from a table.
   */
  static stream_from table(
    transaction_base &tx, table_path path,
    std::initializer_list<std::string_view> columns = {});
  //@}

  /// Execute query, and stream over the results.
  /** @deprecated Use factory function @c query() instead.
   */
  PQXX_DEPRECATED("Use query() factory instead.")
  stream_from(transaction_base &, from_query_t, std::string_view query);

  /// Stream all rows in table, all columns.
  /** @deprecated Use factory function @c table() or @c raw_table() instead.
   */
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(transaction_base &, from_table_t, std::string_view table);

  /// Stream given columns from all rows in table.
  /** @deprecated Use factory function @c table() or @c raw_table() instead.
   */
  template<typename Iter>
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(
    transaction_base &, from_table_t, std::string_view table,
    Iter columns_begin, Iter columns_end);

  /// Stream given columns from all rows in table.
  /** @deprecated Use factory function @c query() instead.
   */
  template<typename Columns>
  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
  stream_from(
    transaction_base &tx, from_table_t, std::string_view table,
    Columns const &columns);

#include "pqxx/internal/ignore-deprecated-pre.hxx"
  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(transaction_base &tx, std::string_view table) :
          stream_from{tx, from_table, table}
  {}
#include "pqxx/internal/ignore-deprecated-post.hxx"

  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  template<typename Columns>
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(
    transaction_base &tx, std::string_view table, Columns const &columns) :
          stream_from{tx, from_table, table, columns}
  {}

  /// @deprecated Use factory function @c table() or @c raw_table() instead.
  template<typename Iter>
  PQXX_DEPRECATED("Use the from_table_t overload instead.")
  stream_from(
    transaction_base &, std::string_view table, Iter columns_begin,
    Iter columns_end);

  ~stream_from() noexcept;

  /// May this stream still produce more data?
  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
  /// Has this stream produced all the data it is going to produce?
  [[nodiscard]] bool operator!() const noexcept { return m_finished; }

  /// Finish this stream.  Call this before continuing to use the connection.
  /** Consumes all remaining lines, and closes the stream.
   *
   * This may take a while if you're abandoning the stream before it's done, so
   * skip it in error scenarios where you're not planning to use the connection
   * again afterwards.
   */
  void complete();

  /// Read one row into a tuple.
  /** Converts the row's fields into the fields making up the tuple.
   *
   * For a column which can contain nulls, be sure to give the corresponding
   * tuple field a type which can be null.  For example, to read a field as
   * @c int when it may contain nulls, read it as @c std::optional<int>.
   * Using @c std::shared_ptr or @c std::unique_ptr will also work.
   */
  template<typename Tuple> stream_from &operator>>(Tuple &);

  /// Doing this with a @c std::variant is going to be horrifically borked.
  template<typename... Vs>
  stream_from &operator>>(std::variant<Vs...> &) = delete;

  /// Iterate over this stream.  Supports range-based "for" loops.
  /** Produces an input iterator over the stream.
   *
   * Do not call this yourself.  Use it like "for (auto data : stream.iter())".
   */
  template<typename... TYPE> [[nodiscard]] auto iter()
  {
    return pqxx::internal::stream_input_iteration<TYPE...>{*this};
  }

  /// Read a row.  Return fields as views, valid until you read the next row.
  /** Returns @c nullptr when there are no more rows to read.  Do not attempt
   * to read any further rows after that.
   *
   * Do not access the vector, or the storage referenced by the views, after
   * closing or completing the stream, or after attempting to read a next row.
   *
   * A @c pqxx::zview is like a @c std::string_view, but with the added
   * guarantee that if its data pointer is non-null, the string is followed by
   * a terminating zero (which falls just outside the view itself).
   *
   * If any of the views' data pointer is null, that means that the
   * corresponding SQL field is null.
   *
   * @warning The return type may change in the future, to support C++20
   * coroutine-based usage.
   */
  std::vector<zview> const *read_row();

  /// Read a raw line of text from the COPY command.
  /** @warning Do not use this unless you really know what you're doing. */
  raw_line get_raw_line();

private:
  // TODO: Clean up this signature once we cull the deprecated constructors.
  /// @deprecated
  stream_from(
    transaction_base &tx, std::string_view table, std::string_view columns,
    from_table_t);

  // TODO: Clean up this signature once we cull the deprecated constructors.
  /// @deprecated
  stream_from(
    transaction_base &, std::string_view unquoted_table,
    std::string_view columns, from_table_t, int);

  template<typename Tuple, std::size_t... indexes>
  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
  {
    (extract_value<Tuple, indexes>(t), ...);
  }

  pqxx::internal::glyph_scanner_func *m_glyph_scanner;

  /// Current row's fields' text, combined into one reusable string.
  std::string m_row;

  /// The current row's fields.
  std::vector<zview> m_fields;

  bool m_finished = false;

  void close();

  template<typename Tuple, std::size_t index>
  void extract_value(Tuple &) const;

  /// Read a line of COPY data, write @c m_row and @c m_fields.
  void parse_line();
};

template<typename Columns>
inline stream_from::stream_from(
  transaction_base &tb, from_table_t, std::string_view table_name,
  Columns const &columns) :
        stream_from{
          tb, from_table, table_name, std::begin(columns), std::end(columns)}
{}

template<typename Iter>
inline stream_from::stream_from(
  transaction_base &tx, from_table_t, std::string_view table,
  Iter columns_begin, Iter columns_end) :
        stream_from{
          tx, table, separated_list(",", columns_begin, columns_end),
          from_table, 1}
{}

template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
{
  if (m_finished)
    return *this;
  constexpr auto tup_size{std::tuple_size_v<Tuple>};
  m_fields.reserve(tup_size);
  parse_line();
  if (m_finished)
    return *this;

  if (std::size(m_fields) != tup_size)
    throw usage_error{internal::concat(
      "Tried to extract ", tup_size, " field(s) from a stream of ",
      std::size(m_fields), ".")};

  extract_fields(t, std::make_index_sequence<tup_size>{});
  return *this;
}

template<typename Tuple, std::size_t index>
inline void stream_from::extract_value(Tuple &t) const
{
  using field_type = strip_t<decltype(std::get<index>(t))>;
  using nullity = nullness<field_type>;
  assert(index < std::size(m_fields));
  if constexpr (nullity::always_null)
  {
    if (m_fields[index].data() != nullptr)
      throw conversion_error{"Streaming non-null value into null field."};
  }
  else if (m_fields[index].data() == nullptr)
  {
    if constexpr (nullity::has_null)
      std::get<index>(t) = nullity::null();
    else
      internal::throw_null_conversion(type_name<field_type>);
  }
  else
  {
    // Don't ever try to convert a non-null value to nullptr_t!
    std::get<index>(t) = from_string<field_type>(m_fields[index]);
  }
}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>#ifndef VSMC_HELPER_BASE_HPP
#define VSMC_HELPER_BASE_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/helper/single_particle.hpp>

namespace vsmc { namespace internal {

/// \brief Particle::value_type subtype
/// \ingroup Helper
///
/// \tparam Dim The dimension of the state parameter vector
/// \tparam T The type of the value of the state parameter vector
template <unsigned Dim, typename T>
class StateBase
{
    public :

    /// The type of the number of particles
    typedef VSMC_SIZE_TYPE size_type;

    /// The type of state parameters
    typedef T state_type;

    /// The type of the matrix of states
    typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> state_mat_type;

    /// Construct a StateBase object with given number of particles
    explicit StateBase (size_type N) : size_(N), state_(Dim, N) {}

    virtual ~StateBase () {}

    /// The dimension of the problem
    static unsigned dim ()
    {
        return Dim;
    }

    /// The number of particles
    size_type size () const
    {
        return size_;
    }

    /// \brief Read and write access to a signle particle state
    ///
    /// \param id The position of the particle
    /// \param pos The position of the parameter in the state array
    ///
    /// \return A reference to the parameter at position pos of the states
    /// array of the particle at position id
    state_type &state (size_type id, unsigned pos)
    {
        return state_(pos, id);
    }

    /// Read only access to a signle particle state
    const state_type &state (size_type id, unsigned pos) const
    {
        return state_(pos, id);
    }

    /// \brief Read and write access to the array of a single particle states
    ///
    /// \param id The position of the particle, 0 to size() - 1
    state_type *state (size_type id)
    {
        return state_.col(id).data();
    }

    /// Read only access to the array of a single particle states
    const state_type *state (size_type id) const
    {
        return state_.col(id).data();
    }

    /// \brief Read and write access to the matrix of all particle states
    ///
    /// \note The matrix is of column marjor as it's the default of Eigen.
    /// Therefore state()(pos, id) == state(id, pos). Best avoid this feature.
    state_mat_type &state ()
    {
        return state_;
    }

    /// Read only access to the matrix of all particle states
    const state_mat_type &state () const
    {
        return state_;
    }

    private :

    size_type size_;
    state_mat_type state_;
}; // class StateBase

template <typename T, typename Derived>
class InitializeBase
{

    public :

    unsigned initialize_state (SingleParticle<T> part)
    {
        return initialize_state_dispatch<Derived>(part, 0);
    }

    void initialize_param (Particle<T> &particle, void *param)
    {
        initialize_param_dispatch<Derived>(particle, param, 0);
    }

    void post_processor (Particle<T> &particle)
    {
        post_processor_dispatch<Derived>(particle, 0);
    }

    void pre_processor (Particle<T> &particle)
    {
        pre_processor_dispatch<Derived>(particle, 0);
    }

    private :

    template <typename D, unsigned (D::*) (SingleParticle<T>)>
    class initialize_state_sfinae_ {};

    template <typename D, void (D::*) (Particle<T> &, void *)>
    class initialize_param_sfinae_ {};

    template <typename D, void (D::*) (Particle<T> &)>
    class processor_sfinae_ {};

    template <typename D>
    unsigned initialize_state_dispatch (SingleParticle<T> part,
            initialize_state_sfinae_<D, &D::initialize_state> *)
    {
        return static_cast<Derived *>(this)->initialize_state(part);
    }

    template <typename D>
    void initialize_param_dispatch (Particle<T> &particle, void *param,
            initialize_param_sfinae_<D, &D::initialize_param> *)
    {
        static_cast<Derived *>(this)->initialize_param(particle, param);
    }

    template <typename D>
    void pre_processor_dispatch (Particle<T> &particle,
            processor_sfinae_<D, &D::pre_processor> *)
    {
        static_cast<Derived *>(this)->pre_processor(particle);
    }

    template <typename D>
    void post_processor_dispatch (Particle<T> &particle,
            processor_sfinae_<D, &D::post_processor> *)
    {
        static_cast<Derived *>(this)->post_processor(particle);
    }

    template <typename D>
    unsigned initialize_state_dispatch (SingleParticle<T>, ...)
    {
        return 0;
    }

    template <typename D>
    void initialize_param_dispatch (Particle<T>, void *, ...) {}

    template <typename D>
    void pre_processor_dispatch (Particle<T> &, ...) {}

    template <typename D>
    void post_processor_dispatch (Particle<T> &, ...) {}
}; // class InitializeBase

template <typename T>
class InitializeBase<T, internal::VBase>
{
    public :

    virtual unsigned initialize_state (SingleParticle<T>) {return 0;}
    virtual void initialize_param (Particle<T> &, void *) {}
    virtual void post_processor (Particle<T> &) {}
    virtual void pre_processor (Particle<T> &) {}
}; // class InitializeBase<T, internal::VBase>

template <typename T, typename Derived>
class MoveBase
{

    public :

    unsigned move_state (unsigned iter, SingleParticle<T> part)
    {
        return move_state_dispatch<Derived>(iter, part, 0);
    }

    void post_processor (unsigned iter, Particle<T> &particle)
    {
        post_processor_dispatch<Derived>(iter, particle, 0);
    }

    void pre_processor (unsigned iter, Particle<T> &particle)
    {
        pre_processor_dispatch<Derived>(iter, particle, 0);
    }

    private :

    template <typename D, unsigned (D::*) (unsigned, SingleParticle<T>)>
    class move_state_sfinae_ {};

    template <typename D, void (D::*) (unsigned, Particle<T> &)>
    class processor_sfinae_ {};

    template <typename D>
    unsigned move_state_dispatch (unsigned iter, SingleParticle<T> part,
            move_state_sfinae_<D, &D::move_state> *)
    {
        return static_cast<Derived *>(this)->move_state(iter, part);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, Particle<T> &particle,
            processor_sfinae_<D, &D::pre_processor> *)
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, Particle<T> &particle,
            processor_sfinae_<D, &D::post_processor> *)
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    template <typename D>
    unsigned move_state_dispatch (unsigned, SingleParticle<T>, ...)
    {
        return 0;
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, Particle<T> &, ...) {}

    template <typename D>
    void post_processor_dispatch (unsigned iter, Particle<T> &, ...) {}
}; // class MoveBase

template <typename T>
class MoveBase<T, internal::VBase>
{
    public :

    virtual unsigned move_state (unsigned, SingleParticle<T>) {return 0;}
    virtual void post_processor (unsigned, Particle<T> &) {}
    virtual void pre_processor (unsigned, Particle<T> &) {}
}; // class MoveBase<T, internal::VBase>

template <typename T, typename Derived>
class MonitorBase
{
    public :

    void monitor_state (unsigned iter, ConstSingleParticle<T> part,
            double *res)
    {
        monitor_state_dispatch<Derived>(iter, part, res, 0);
    }

    void pre_processor (unsigned iter, const Particle<T> &particle)
    {
        pre_processor_dispatch<Derived>(iter, particle, 0);
    }

    void post_processor (unsigned iter, const Particle<T> &particle)
    {
        post_processor_dispatch<Derived>(iter, particle, 0);
    }

    private :

    template <typename D, void (D::*) (unsigned, ConstSingleParticle<T>,
            double *)>
    class monitor_state_sfinae_ {};

    template <typename D, void (D::*) (unsigned, const Particle<T> &)>
    class processor_sfinae_ {};

    template <typename D>
    void monitor_state_dispatch (unsigned iter, ConstSingleParticle<T> part,
            double *res, monitor_state_sfinae_<D, &D::monitor_state> *)
    {
        static_cast<Derived *>(this)->monitor_state(iter, part, res);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &particle,
            processor_sfinae_<D, &D::pre_processor> *)
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &particle,
            processor_sfinae_<D, &D::post_processor> *)
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    template <typename D>
    void monitor_state_dispatch (unsigned, ConstSingleParticle<T>,
            double *, ...) {}

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &, ...) {}

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &, ...) {}
}; // class MonitorBase

template <typename T>
class MonitorBase<T, internal::VBase>
{
    public :

    virtual void monitor_state (unsigned, ConstSingleParticle<T>,
            double *) {}
    virtual void post_processor (unsigned, const Particle<T> &) {}
    virtual void pre_processor (unsigned, const Particle<T> &) {}
}; // class MonitorBase<T, internal::VBase>

template <typename T, typename Derived>
class PathBase
{
    public :

    double path_state (unsigned iter, ConstSingleParticle<T> part)
    {
        return path_state_dispatch<Derived>(iter, part, 0);
    }

    double path_width (unsigned iter, Particle<T> &particle)
    {
        return path_width_dispatch<Derived>(iter, particle, 0);
    }

    void pre_processor (unsigned iter, const Particle<T> &particle)
    {
        pre_processor_dispatch<Derived>(iter, particle, 0);
    }

    void post_processor (unsigned iter, const Particle<T> &particle)
    {
        post_processor_dispatch<Derived>(iter, particle, 0);
    }

    private :

    template <typename D, double (D::*) (unsigned, ConstSingleParticle<T>)>
    class path_state_sfinae_ {};

    template <typename D, double (D::*) (unsigned, const Particle<T> &)>
    class path_width_sfinae_ {};

    template <typename D, void (D::*) (unsigned, const Particle<T> &)>
    class processor_sfinae_ {};

    template <typename D>
    double path_state_dispatch (unsigned iter, ConstSingleParticle<T> part,
            path_state_sfinae_<D, &D::path_state> *)
    {
        return static_cast<Derived *>(this)->path_state(iter, part);
    }

    template <typename D>
    double path_width_dispatch (unsigned iter, const Particle<T> &particle,
            path_width_sfinae_<D, &D::path_state> *)
    {
        return static_cast<Derived *>(this)->path_width(iter, particle);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &particle,
            processor_sfinae_<D, &D::pre_processor> *)
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &particle,
            processor_sfinae_<D, &D::post_processor> *)
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    template <typename D>
    double path_state_dispatch (unsigned, ConstSingleParticle<T>, ...)
    {
        return 0;
    }

    template <typename D>
    double path_width_dispatch (unsigned, const Particle<T> &)
    {
        return 0;
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &, ...) {}

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &, ...) {}
}; // class PathBase

template <typename T>
class PathBase<T, internal::VBase>
{
    public :

    virtual double path_state (unsigned, ConstSingleParticle<T>) {return 0;}
    virtual double path_width (unsigned, const Particle<T> &) {return 0;}
    virtual void post_processor (unsigned, const Particle<T> &) {}
    virtual void pre_processor (unsigned, const Particle<T> &) {}
}; // class MonitorBase<T, internal::VBase>

} } // namespace vsmc::internal

#endif // VSMC_HELPER_BASE_HPP
<commit_msg>simplify dispatch logic<commit_after>#ifndef VSMC_HELPER_BASE_HPP
#define VSMC_HELPER_BASE_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/helper/single_particle.hpp>

namespace vsmc { namespace internal {

/// \brief Particle::value_type subtype
/// \ingroup Helper
///
/// \tparam Dim The dimension of the state parameter vector
/// \tparam T The type of the value of the state parameter vector
template <unsigned Dim, typename T>
class StateBase
{
    public :

    /// The type of the number of particles
    typedef VSMC_SIZE_TYPE size_type;

    /// The type of state parameters
    typedef T state_type;

    /// The type of the matrix of states
    typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> state_mat_type;

    /// Construct a StateBase object with given number of particles
    explicit StateBase (size_type N) : size_(N), state_(Dim, N) {}

    virtual ~StateBase () {}

    /// The dimension of the problem
    static unsigned dim ()
    {
        return Dim;
    }

    /// The number of particles
    size_type size () const
    {
        return size_;
    }

    /// \brief Read and write access to a signle particle state
    ///
    /// \param id The position of the particle
    /// \param pos The position of the parameter in the state array
    ///
    /// \return A reference to the parameter at position pos of the states
    /// array of the particle at position id
    state_type &state (size_type id, unsigned pos)
    {
        return state_(pos, id);
    }

    /// Read only access to a signle particle state
    const state_type &state (size_type id, unsigned pos) const
    {
        return state_(pos, id);
    }

    /// \brief Read and write access to the array of a single particle states
    ///
    /// \param id The position of the particle, 0 to size() - 1
    state_type *state (size_type id)
    {
        return state_.col(id).data();
    }

    /// Read only access to the array of a single particle states
    const state_type *state (size_type id) const
    {
        return state_.col(id).data();
    }

    /// \brief Read and write access to the matrix of all particle states
    ///
    /// \note The matrix is of column marjor as it's the default of Eigen.
    /// Therefore state()(pos, id) == state(id, pos). Best avoid this feature.
    state_mat_type &state ()
    {
        return state_;
    }

    /// Read only access to the matrix of all particle states
    const state_mat_type &state () const
    {
        return state_;
    }

    private :

    size_type size_;
    state_mat_type state_;
}; // class StateBase

template <typename T, typename Derived>
class InitializeBase
{

    public :

    unsigned initialize_state (SingleParticle<T> part)
    {
        return initialize_state_dispatch(part, &Derived::initialize_state);
    }

    void initialize_param (Particle<T> &particle, void *param)
    {
        initialize_param_dispatch(particle, param, &Derived::initialize_param);
    }

    void post_processor (Particle<T> &particle)
    {
        post_processor_dispatch(particle, &Derived::pre_processor);
    }

    void pre_processor (Particle<T> &particle)
    {
        pre_processor_dispatch(particle, &Derived::post_processor);
    }

    private :

    template <typename D>
    unsigned initialize_state_dispatch (SingleParticle<T> part,
            unsigned (D::*) (SingleParticle<T>))
    {
        return static_cast<Derived *>(this)->initialize_state(part);
    }

    template <typename D>
    void initialize_param_dispatch (Particle<T> &particle, void *param,
            void (D::*) (Particle<T> &, void *))
    {
        static_cast<Derived *>(this)->initialize_param(particle, param);
    }

    template <typename D>
    void pre_processor_dispatch (Particle<T> &particle,
            void (D::*) (Particle<T> &))
    {
        static_cast<Derived *>(this)->pre_processor(particle);
    }

    template <typename D>
    void post_processor_dispatch (Particle<T> &particle,
            void (D::*) (Particle<T> &))
    {
        static_cast<Derived *>(this)->post_processor(particle);
    }

    unsigned initialize_state_dispatch (SingleParticle<T> part,
            unsigned (InitializeBase::*) (SingleParticle<T>)) {return 0;}

    void initialize_param_dispatch (Particle<T> &particle, void *param,
            void (InitializeBase::*) (Particle<T> &, void *)) {}

    void pre_processor_dispatch (Particle<T> &particle,
            void (InitializeBase::*) (Particle<T> &)) {}

    void post_processor_dispatch (Particle<T> &particle,
            void (InitializeBase::*) (Particle<T> &)) {}
}; // class InitializeBase<T, Derived>

template <typename T>
class InitializeBase<T, internal::VBase>
{
    public :

    virtual unsigned initialize_state (SingleParticle<T>) {return 0;}
    virtual void initialize_param (Particle<T> &, void *) {}
    virtual void post_processor (Particle<T> &) {}
    virtual void pre_processor (Particle<T> &) {}
}; // class InitializeBase<T>

template <typename T, typename Derived>
class MoveBase
{
    public :

    unsigned move_state (unsigned iter, SingleParticle<T> part)
    {
        return move_state_dispatch(iter, part, &Derived::move_state);
    }

    void pre_processor (unsigned iter, Particle<T> &particle)
    {
        pre_processor_dispatch(iter, particle, &Derived::pre_processor);
    }

    void post_processor (unsigned iter, Particle<T> &particle)
    {
        post_processor_dispatch(iter, particle, &Derived::post_processor);
    }

    private :

    template <typename D>
    unsigned move_state_dispatch (unsigned iter, SingleParticle<T> part,
            unsigned (D::*) (unsigned, SingleParticle<T>))
    {
        return static_cast<Derived *>(this)->move_state(iter, part);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, Particle<T> &particle,
            void (D::*) (unsigned, Particle<T> &))
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, Particle<T> &particle,
            void (D::*) (unsigned, Particle<T> &))
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    unsigned move_state_dispatch (unsigned, SingleParticle<T>,
            unsigned (MoveBase::*) (unsigned, SingleParticle<T>)) {return 0;}

    void pre_processor_dispatch (unsigned iter, Particle<T> &,
            void (MoveBase::*) (unsigned, Particle<T> &)) {}

    void post_processor_dispatch (unsigned iter, Particle<T> &,
            void (MoveBase::*) (unsigned, Particle<T> &)) {}
}; // class MoveBase<T, Derived>

template <typename T>
class MoveBase<T, internal::VBase>
{
    public :

    virtual unsigned move_state (unsigned, SingleParticle<T>) {return 0;}
    virtual void post_processor (unsigned, Particle<T> &) {}
    virtual void pre_processor (unsigned, Particle<T> &) {}
}; // class MoveBase<T>

template <typename T, typename Derived>
class MonitorBase
{
    public :

    void monitor_state (unsigned iter, ConstSingleParticle<T> part,
            double *res)
    {
        monitor_state_dispatch(iter, part, res, &Derived::monitor_state);
    }

    void pre_processor (unsigned iter, const Particle<T> &particle)
    {
        pre_processor_dispatch(iter, particle, &Derived::pre_processor);
    }

    void post_processor (unsigned iter, const Particle<T> &particle)
    {
        post_processor_dispatch(iter, particle, &Derived::post_processor);
    }

    private :

    template <typename D>
    void monitor_state_dispatch (unsigned iter, ConstSingleParticle<T> part,
            double *res,
            void (D::*) (unsigned, ConstSingleParticle<T>, double *))
    {
        static_cast<Derived *>(this)->monitor_state(iter, part, res);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &particle,
            void (D::*) (unsigned, const Particle<T> &))
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &particle,
            void (D::*) (unsigned, const Particle<T> &))
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    void monitor_state_dispatch (unsigned, ConstSingleParticle<T>, double *res,
            void (MonitorBase::*) (unsigned, ConstSingleParticle<T>, double *))
    {}

    void pre_processor_dispatch (unsigned iter, const Particle<T> &,
            void (MonitorBase::*) (unsigned, const Particle<T> &)) {}

    void post_processor_dispatch (unsigned iter, const Particle<T> &,
            void (MonitorBase::*) (unsigned, const Particle<T> &)) {}
}; // class MonitorBase<T, Derived>

template <typename T>
class MonitorBase<T, internal::VBase>
{
    public :

    virtual void monitor_state (unsigned, ConstSingleParticle<T>,
            double *) {}
    virtual void post_processor (unsigned, const Particle<T> &) {}
    virtual void pre_processor (unsigned, const Particle<T> &) {}
}; // class MonitorBase<T>

template <typename T, typename Derived>
class PathBase
{
    public :

    double path_state (unsigned iter, ConstSingleParticle<T> part)
    {
        return path_state_dispatch(iter, part, &Derived::path_state);
    }

    double path_width (unsigned iter, Particle<T> &particle)
    {
        return path_width_dispatch(iter, particle, &Derived::path_width);
    }

    void pre_processor (unsigned iter, const Particle<T> &particle)
    {
        pre_processor_dispatch(iter, particle, &Derived::pre_processor);
    }

    void post_processor (unsigned iter, const Particle<T> &particle)
    {
        post_processor_dispatch(iter, particle, &Derived::post_processor);
    }

    private :

    template <typename D>
    double path_state_dispatch (unsigned iter, ConstSingleParticle<T> part,
            double (D::*) (unsigned, ConstSingleParticle<T>))
    {
        return static_cast<Derived *>(this)->path_state(iter, part);
    }

    template <typename D>
    double path_width_dispatch (unsigned iter, const Particle<T> &particle,
            double (D::*) (unsigned, const Particle<T> &))
    {
        return static_cast<Derived *>(this)->path_width(iter, particle);
    }

    template <typename D>
    void pre_processor_dispatch (unsigned iter, const Particle<T> &particle,
            void (D::*) (unsigned, const Particle<T> &))
    {
        static_cast<Derived *>(this)->pre_processor(iter, particle);
    }

    template <typename D>
    void post_processor_dispatch (unsigned iter, const Particle<T> &particle,
            void (D::*) (unsigned, const Particle<T> &))
    {
        static_cast<Derived *>(this)->post_processor(iter, particle);
    }

    double path_state_dispatch (unsigned, ConstSingleParticle<T>,
            double (PathBase::*) (unsigned, ConstSingleParticle<T>)) {return 0;}

    double path_width_dispatch (unsigned, const Particle<T> &,
            double (PathBase::*) (unsigned, const Particle<T> &)) {return 0;}

    void pre_processor_dispatch (unsigned iter, const Particle<T> &,
            void (PathBase::*) (unsigned, const Particle<T> &)) {}

    void post_processor_dispatch (unsigned iter, const Particle<T> &,
            void (PathBase::*) (unsigned, const Particle<T> &)) {}
}; // class PathBase<T, Derived>

template <typename T>
class PathBase<T, internal::VBase>
{
    public :

    virtual double path_state (unsigned, ConstSingleParticle<T>) {return 0;}
    virtual double path_width (unsigned, const Particle<T> &) {return 0;}
    virtual void post_processor (unsigned, const Particle<T> &) {}
    virtual void pre_processor (unsigned, const Particle<T> &) {}
}; // class MonitorBase<T>

} } // namespace vsmc::internal

#endif // VSMC_HELPER_BASE_HPP
<|endoftext|>