<commit_before>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "CppSound.hpp"
#include "Shell.hpp"
#include "System.hpp"
#include <iostream>
#include <fstream>
#include <time.h>
#include "csdl.h"

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN 1
#  include <windows.h>
#endif

namespace csound
{

  void        (*Py_Initialize_)(void) = 0;
  void        (*Py_Finalize_)(void) = 0;
  void        (*PySys_SetArgv_)(int, char **) = 0;
  PyObject_   *(*PyImport_ImportModule_)(char *) = 0;
  void        (*PyErr_Print_)(void) = 0;
  PyObject_   *(*PyObject_GetAttrString_)(PyObject_ *, char *) = 0;
  int         (*PyRun_SimpleFileEx_)(FILE *, const char *, int) = 0;
  int         (*PyRun_SimpleString_)(const char *) = 0;
  PyObject_   *(*PyObject_CallMethod_)(PyObject_ *,
                                       char *, char *, ...) = 0;
  long        (*PyLong_AsLong_)(PyObject_ *) = 0;

  void *Shell::pythonLibrary = 0;
  const char *Shell::pythonLibraryPathList[] = {
#ifdef WIN32
    "python24.dll",
    "python23.dll",
#elif defined(MACOSX)
    // hope that one of these will work
    "/System/Library/Frameworks/Python.Framework/Versions/Current/Python",
    "/System/Library/Frameworks/Python.framework/Versions/Current/Python",
    "/System/Library/Frameworks/Python.Framework/Versions/2.4/Python",
    "/System/Library/Frameworks/Python.framework/Versions/2.4/Python",
    "/System/Library/Frameworks/Python.Framework/Versions/2.3/Python",
    "/System/Library/Frameworks/Python.framework/Versions/2.3/Python",
    "/usr/lib/libpython2.4.dylib",
    "/usr/lib/libpython2.3.dylib",
    "/Library/Frameworks/Python.Framework/Versions/Current/Python",
    "/Library/Frameworks/Python.framework/Versions/Current/Python",
    "/Library/Frameworks/Python.Framework/Versions/2.4/Python",
    "/Library/Frameworks/Python.framework/Versions/2.4/Python",
    "/Library/Frameworks/Python.Framework/Versions/2.3/Python",
    "/Library/Frameworks/Python.framework/Versions/2.3/Python",
    "/usr/local/lib/libpython2.4.dylib",
    "/usr/local/lib/libpython2.3.dylib",
#else
    "libpython2.4.so",
    "libpython2.3.so",
#endif
    (char*) 0
  };

  Shell::Shell()
  {
  }

  Shell::~Shell()
  {
  }

  static bool pythonFuncWarning(void **pythonLibrary,
                                const char *funcName)
  {
    csound::System::warn("Failed to find '%s' function. "
                         "Python scripting is not enabled.\n", funcName);
    csoundCloseLibrary(*pythonLibrary);
    *pythonLibrary = (void *) 0;
    return false;
  }

  void Shell::open()
  {
    // nothing to do if already loaded
    if (pythonLibrary) {
      return;
    }
    int     result = CSOUND_ERROR;
#ifdef WIN32
    // avoid pop-up window about missing DLL file
    SetErrorMode((unsigned int) SEM_NOOPENFILEERRORBOX);
#endif
    for (const char **sp = &(pythonLibraryPathList[0]); *sp != (char*) 0; sp++) {
      if ((result = csoundOpenLibrary(&pythonLibrary, *sp)) == CSOUND_SUCCESS) {
        break;
      }
    }
#ifdef WIN32
    SetErrorMode((unsigned int) 0);
#endif
    if (result != CSOUND_SUCCESS) {
      csound::System::warn("Python not found, disabling scripting. "
                           "Check your PATH or Python installation.\n");
      pythonLibrary = (void*) 0;
      return;
    }
    Py_Initialize_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "Py_Initialize");
    if (!Py_Initialize_) {
      pythonFuncWarning(&pythonLibrary, "Py_Initialize");
      return;
    }
    Py_Finalize_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "Py_Finalize");
    if (!Py_Finalize_) {
      pythonFuncWarning(&pythonLibrary, "Py_Finalize");
      return;
    }
    PySys_SetArgv_ =
      (void (*)(int, char **))
      csoundGetLibrarySymbol(pythonLibrary, "PySys_SetArgv");
    if (!PySys_SetArgv_) {
      pythonFuncWarning(&pythonLibrary, "PySys_SetArgv");
      return;
    }
    PyImport_ImportModule_ =
      (PyObject_* (*)(char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyImport_ImportModule");
    if (!PyImport_ImportModule_) {
      pythonFuncWarning(&pythonLibrary,
                        "PyImport_ImportModule");
      return;
    }
    PyRun_SimpleFileEx_ =
      (int (*)(FILE *, const char *, int))
      csoundGetLibrarySymbol(pythonLibrary, "PyRun_SimpleFileEx");
    if (!PyRun_SimpleFileEx_) {
      pythonFuncWarning(&pythonLibrary, "PyRun_SimpleFileEx");
      return;
    }
    PyRun_SimpleString_ =
      (int (*)(const char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyRun_SimpleString");
    if (!PyRun_SimpleString_) {
      pythonFuncWarning(&pythonLibrary, "PyRun_SimpleString");
      return;
    }
    PyErr_Print_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "PyErr_Print");
    if (!PyErr_Print_) {
      pythonFuncWarning(&pythonLibrary, "PyErr_Print");
      return;
    }
    PyObject_GetAttrString_ =
      (PyObject_ *(*)(PyObject_ *, char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyObject_GetAttrString");
    if (!PyObject_GetAttrString_) {
      pythonFuncWarning(&pythonLibrary,
                        "PyObject_GetAttrString");
      return;
    }
    PyObject_CallMethod_ =
      (PyObject_ * (*)(PyObject_ *, char *, char *, ...))
      csoundGetLibrarySymbol(pythonLibrary, "PyObject_CallMethod");
    if (!PyObject_CallMethod_) {
      pythonFuncWarning(&pythonLibrary, "PyObject_CallMethod");
      return;
    }
    PyLong_AsLong_ =
      (long (*)(PyObject_ *))
      csoundGetLibrarySymbol(pythonLibrary, "PyLong_AsLong");
    if (!PyLong_AsLong_) {
      pythonFuncWarning(&pythonLibrary, "PyLong_AsLong");
      return;
    }
    Py_Initialize_();
  }

  void Shell::close()
  {
    // Should be able to Py_Finalize here, but it doesn't work in VST.
  }

  void Shell::main(int argc, char **argv)
  {
    PySys_SetArgv_(argc, argv);
  }

  void Shell::initialize()
  {
    clear();
    setFilename(generateFilename());
  }

  void Shell::clear()
  {
    filename.erase();
    script.erase();
  }

  std::string Shell::generateFilename()
  {
    time_t time_ = 0;
    time(&time_);
    struct tm* tm_ = gmtime(&time_);
    char buffer[0x100];
    strftime(buffer, 0x100, "csound.%Y-%m-%d.%H-%M-%S.py", tm_);
    return buffer;
  }

  void Shell::setFilename(std::string filename)
  {
    this->filename = filename;
  }

  std::string Shell::getFilename() const
  {
    return filename;
  }

  std::string Shell::getOutputSoundfileName() const
  {
    std::string outputFilename = getFilename();
    outputFilename.append(".wav");
    return filename;
  }

  std::string Shell::getMidiFilename() const
  {
    std::string midiFilename = getFilename();
    midiFilename.append(".mid");
    return filename;
  }

  std::string Shell::getScript() const
  {
    return script;
  }

  void Shell::setScript(std::string script)
  {
    this->script = script;
  }

  void Shell::load(std::string filename)
  {
    clear();
    loadAppend(filename);
  }

  void Shell::loadAppend(std::string filename)
  {
    std::ifstream stream;
    stream.open(filename.c_str(), std::ios_base::binary);
    char c;
    while(!stream.eof())
      {
        stream.get(c);
        script.push_back(c);
      }
  }

  void Shell::save(std::string filename) const
  {
    std::ofstream stream;
    if(filename.length() > 0)
      {
        stream.open(filename.c_str(), std::ios_base::binary);
        for(std::string::const_iterator it = script.begin(); it != script.end(); ++it)
          {
            stream.put(*it);
          }
      }
  }

  void Shell::save() const
  {
    save(getFilename());
  }

  int Shell::runScript()
  {
    return runScript(script);
  }

  int Shell::runScript(std::string script_)
  {
    csound::System::message("BEGAN Shell::runScript()...\n");
    int result = 0;
    try
      {
        char *script__ = const_cast<char *>(script_.c_str());
        csound::System::message("==============================================================================================================\n");
        result = PyRun_SimpleString_(script__);
        if(result)
          {
            PyErr_Print_();
          }
      }
    catch(...)
      {
        csound::System::error("Unidentified exception in silence::Shell::run().\n");
      }
    csound::System::message("==============================================================================================================\n");
    csound::System::message("PyRun_SimpleString returned %d.\n", result);
    csound::System::message("ENDED Shell::runScript().\n");
    return result;
  }

  void Shell::stop()
  {
    //PyErr_SetString(PyExc_KeyboardInterrupt, "Shell::stop() was called.");
  }
}
<commit_msg>Added timing to Shell::runScript to time Python code.<commit_after>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "CppSound.hpp"
#include "Shell.hpp"
#include "System.hpp"
#include <iostream>
#include <fstream>
#include <ctime>
#include "csdl.h"

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN 1
#  include <windows.h>
#endif

namespace csound
{

  void        (*Py_Initialize_)(void) = 0;
  void        (*Py_Finalize_)(void) = 0;
  void        (*PySys_SetArgv_)(int, char **) = 0;
  PyObject_   *(*PyImport_ImportModule_)(char *) = 0;
  void        (*PyErr_Print_)(void) = 0;
  PyObject_   *(*PyObject_GetAttrString_)(PyObject_ *, char *) = 0;
  int         (*PyRun_SimpleFileEx_)(FILE *, const char *, int) = 0;
  int         (*PyRun_SimpleString_)(const char *) = 0;
  PyObject_   *(*PyObject_CallMethod_)(PyObject_ *,
                                       char *, char *, ...) = 0;
  long        (*PyLong_AsLong_)(PyObject_ *) = 0;

  void *Shell::pythonLibrary = 0;
  const char *Shell::pythonLibraryPathList[] = {
#ifdef WIN32
    "python24.dll",
    "python23.dll",
#elif defined(MACOSX)
    // hope that one of these will work
    "/System/Library/Frameworks/Python.Framework/Versions/Current/Python",
    "/System/Library/Frameworks/Python.framework/Versions/Current/Python",
    "/System/Library/Frameworks/Python.Framework/Versions/2.4/Python",
    "/System/Library/Frameworks/Python.framework/Versions/2.4/Python",
    "/System/Library/Frameworks/Python.Framework/Versions/2.3/Python",
    "/System/Library/Frameworks/Python.framework/Versions/2.3/Python",
    "/usr/lib/libpython2.4.dylib",
    "/usr/lib/libpython2.3.dylib",
    "/Library/Frameworks/Python.Framework/Versions/Current/Python",
    "/Library/Frameworks/Python.framework/Versions/Current/Python",
    "/Library/Frameworks/Python.Framework/Versions/2.4/Python",
    "/Library/Frameworks/Python.framework/Versions/2.4/Python",
    "/Library/Frameworks/Python.Framework/Versions/2.3/Python",
    "/Library/Frameworks/Python.framework/Versions/2.3/Python",
    "/usr/local/lib/libpython2.4.dylib",
    "/usr/local/lib/libpython2.3.dylib",
#else
    "libpython2.4.so",
    "libpython2.3.so",
#endif
    (char*) 0
  };

  Shell::Shell()
  {
  }

  Shell::~Shell()
  {
  }

  static bool pythonFuncWarning(void **pythonLibrary,
                                const char *funcName)
  {
    csound::System::warn("Failed to find '%s' function. "
                         "Python scripting is not enabled.\n", funcName);
    csoundCloseLibrary(*pythonLibrary);
    *pythonLibrary = (void *) 0;
    return false;
  }

  void Shell::open()
  {
    // nothing to do if already loaded
    if (pythonLibrary) {
      return;
    }
    int     result = CSOUND_ERROR;
#ifdef WIN32
    // avoid pop-up window about missing DLL file
    SetErrorMode((unsigned int) SEM_NOOPENFILEERRORBOX);
#endif
    for (const char **sp = &(pythonLibraryPathList[0]); *sp != (char*) 0; sp++) {
      if ((result = csoundOpenLibrary(&pythonLibrary, *sp)) == CSOUND_SUCCESS) {
        break;
      }
    }
#ifdef WIN32
    SetErrorMode((unsigned int) 0);
#endif
    if (result != CSOUND_SUCCESS) {
      csound::System::warn("Python not found, disabling scripting. "
                           "Check your PATH or Python installation.\n");
      pythonLibrary = (void*) 0;
      return;
    }
    Py_Initialize_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "Py_Initialize");
    if (!Py_Initialize_) {
      pythonFuncWarning(&pythonLibrary, "Py_Initialize");
      return;
    }
    Py_Finalize_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "Py_Finalize");
    if (!Py_Finalize_) {
      pythonFuncWarning(&pythonLibrary, "Py_Finalize");
      return;
    }
    PySys_SetArgv_ =
      (void (*)(int, char **))
      csoundGetLibrarySymbol(pythonLibrary, "PySys_SetArgv");
    if (!PySys_SetArgv_) {
      pythonFuncWarning(&pythonLibrary, "PySys_SetArgv");
      return;
    }
    PyImport_ImportModule_ =
      (PyObject_* (*)(char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyImport_ImportModule");
    if (!PyImport_ImportModule_) {
      pythonFuncWarning(&pythonLibrary,
                        "PyImport_ImportModule");
      return;
    }
    PyRun_SimpleFileEx_ =
      (int (*)(FILE *, const char *, int))
      csoundGetLibrarySymbol(pythonLibrary, "PyRun_SimpleFileEx");
    if (!PyRun_SimpleFileEx_) {
      pythonFuncWarning(&pythonLibrary, "PyRun_SimpleFileEx");
      return;
    }
    PyRun_SimpleString_ =
      (int (*)(const char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyRun_SimpleString");
    if (!PyRun_SimpleString_) {
      pythonFuncWarning(&pythonLibrary, "PyRun_SimpleString");
      return;
    }
    PyErr_Print_ =
      (void (*)(void))
      csoundGetLibrarySymbol(pythonLibrary, "PyErr_Print");
    if (!PyErr_Print_) {
      pythonFuncWarning(&pythonLibrary, "PyErr_Print");
      return;
    }
    PyObject_GetAttrString_ =
      (PyObject_ *(*)(PyObject_ *, char *))
      csoundGetLibrarySymbol(pythonLibrary, "PyObject_GetAttrString");
    if (!PyObject_GetAttrString_) {
      pythonFuncWarning(&pythonLibrary,
                        "PyObject_GetAttrString");
      return;
    }
    PyObject_CallMethod_ =
      (PyObject_ * (*)(PyObject_ *, char *, char *, ...))
      csoundGetLibrarySymbol(pythonLibrary, "PyObject_CallMethod");
    if (!PyObject_CallMethod_) {
      pythonFuncWarning(&pythonLibrary, "PyObject_CallMethod");
      return;
    }
    PyLong_AsLong_ =
      (long (*)(PyObject_ *))
      csoundGetLibrarySymbol(pythonLibrary, "PyLong_AsLong");
    if (!PyLong_AsLong_) {
      pythonFuncWarning(&pythonLibrary, "PyLong_AsLong");
      return;
    }
    Py_Initialize_();
  }

  void Shell::close()
  {
    // Should be able to Py_Finalize here, but it doesn't work in VST.
  }

  void Shell::main(int argc, char **argv)
  {
    PySys_SetArgv_(argc, argv);
  }

  void Shell::initialize()
  {
    clear();
    setFilename(generateFilename());
  }

  void Shell::clear()
  {
    filename.erase();
    script.erase();
  }

  std::string Shell::generateFilename()
  {
    time_t time_ = 0;
    time(&time_);
    struct tm* tm_ = std::gmtime(&time_);
    char buffer[0x100];
    strftime(buffer, 0x100, "csound.%Y-%m-%d.%H-%M-%S.py", tm_);
    return buffer;
  }

  void Shell::setFilename(std::string filename)
  {
    this->filename = filename;
  }

  std::string Shell::getFilename() const
  {
    return filename;
  }

  std::string Shell::getOutputSoundfileName() const
  {
    std::string outputFilename = getFilename();
    outputFilename.append(".wav");
    return filename;
  }

  std::string Shell::getMidiFilename() const
  {
    std::string midiFilename = getFilename();
    midiFilename.append(".mid");
    return filename;
  }

  std::string Shell::getScript() const
  {
    return script;
  }

  void Shell::setScript(std::string script)
  {
    this->script = script;
  }

  void Shell::load(std::string filename)
  {
    clear();
    loadAppend(filename);
  }

  void Shell::loadAppend(std::string filename)
  {
    std::ifstream stream;
    stream.open(filename.c_str(), std::ios_base::binary);
    char c;
    while(!stream.eof())
      {
        stream.get(c);
        script.push_back(c);
      }
  }

  void Shell::save(std::string filename) const
  {
    std::ofstream stream;
    if(filename.length() > 0)
      {
        stream.open(filename.c_str(), std::ios_base::binary);
        for(std::string::const_iterator it = script.begin(); it != script.end(); ++it)
          {
            stream.put(*it);
          }
      }
  }

  void Shell::save() const
  {
    save(getFilename());
  }

  int Shell::runScript()
  {
    return runScript(script);
  }

  int Shell::runScript(std::string script_)
  {
    csound::System::message("BEGAN Shell::runScript()...\n");
    clock_t began = std::clock();
    int result = 0;
    try
      {
        char *script__ = const_cast<char *>(script_.c_str());
        csound::System::message("==============================================================================================================\n");
        result = PyRun_SimpleString_(script__);
        if(result)
          {
            PyErr_Print_();
          }
      }
    catch(...)
      {
        csound::System::error("Unidentified exception in silence::Shell::run().\n");
      }
    csound::System::message("==============================================================================================================\n");
    clock_t ended = std::clock();
    double elapsed = double(ended - began) / double(CLOCKS_PER_SEC);
    csound::System::message("PyRun_SimpleString returned %d after %.3f seconds.\n", result, elapsed);
    csound::System::message("ENDED Shell::runScript().\n");
    return result;
  }

  void Shell::stop()
  {
    //PyErr_SetString(PyExc_KeyboardInterrupt, "Shell::stop() was called.");
  }
}
<|endoftext|>


<commit_before>/*
 * EventBuilder.cpp
 *
 *  Created on: Jul 12, 2011
 *      Author: augcampos
 */

#include "asteriskcpp/manager/EventBuilder.h"
#include <stdlib.h>
#include <map>
#include "asteriskcpp/utils/StringUtils.h"

#include "asteriskcpp/manager/events/AgentCallbackLoginEvent.h"
#include "asteriskcpp/manager/events/AgentCallbackLogoffEvent.h"
#include "asteriskcpp/manager/events/AgentCalledEvent.h"
#include "asteriskcpp/manager/events/AgentCompleteEvent.h"
#include "asteriskcpp/manager/events/AgentConnectEvent.h"
#include "asteriskcpp/manager/events/AgentDumpEvent.h"
#include "asteriskcpp/manager/events/AgentLoginEvent.h"
#include "asteriskcpp/manager/events/AgentLogoffEvent.h"
#include "asteriskcpp/manager/events/AgentRingNoAnswer.h"
#include "asteriskcpp/manager/events/AgentsCompleteEvent.h"
#include "asteriskcpp/manager/events/AgiExecEvent.h"
#include "asteriskcpp/manager/events/AlarmClearEvent.h"
#include "asteriskcpp/manager/events/AlarmEvent.h"
#include "asteriskcpp/manager/events/AsyncAgiEvent.h"
#include "asteriskcpp/manager/events/BridgeEvent.h"
#include "asteriskcpp/manager/events/BridgeExecEvent.h"
#include "asteriskcpp/manager/events/CdrEvent.h"
#include "asteriskcpp/manager/events/ChannelReloadEvent.h"
#include "asteriskcpp/manager/events/ChannelUpdateEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeEndEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeJoinEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeLeaveEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListCompleteEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListRoomsCompleteEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListRoomsEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeStartEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeTalkingEvent.h"
#include "asteriskcpp/manager/events/ConnectEvent.h"
#include "asteriskcpp/manager/events/CoreShowChannelEvent.h"
#include "asteriskcpp/manager/events/CoreShowChannelsCompleteEvent.h"
#include "asteriskcpp/manager/events/DbGetResponseEvent.h"
#include "asteriskcpp/manager/events/DialEvent.h"
#include "asteriskcpp/manager/events/DisconnectEvent.h"
#include "asteriskcpp/manager/events/DndStateEvent.h"
#include "asteriskcpp/manager/events/DtmfEvent.h"
#include "asteriskcpp/manager/events/ExtensionStatusEvent.h"
#include "asteriskcpp/manager/events/FaxDocumentStatusEvent.h"
#include "asteriskcpp/manager/events/FaxReceivedEvent.h"
#include "asteriskcpp/manager/events/FaxStatusEvent.h"
#include "asteriskcpp/manager/events/FullyBootedEvent.h"
#include "asteriskcpp/manager/events/HangupEvent.h"
#include "asteriskcpp/manager/events/HoldEvent.h"
#include "asteriskcpp/manager/events/HoldedCallEvent.h"
#include "asteriskcpp/manager/events/JabberEventEvent.h"
#include "asteriskcpp/manager/events/JitterBufStatsEvent.h"
#include "asteriskcpp/manager/events/JoinEvent.h"
#include "asteriskcpp/manager/events/LeaveEvent.h"
#include "asteriskcpp/manager/events/LinkEvent.h"
#include "asteriskcpp/manager/events/ListDialplanEvent.h"
#include "asteriskcpp/manager/events/LogChannelEvent.h"
#include "asteriskcpp/manager/events/MasqueradeEvent.h"
#include "asteriskcpp/manager/events/MeetMeEndEvent.h"
#include "asteriskcpp/manager/events/MeetMeJoinEvent.h"

namespace asteriskcpp {

	EventBuilder::EventBuilder() {
		RegisterClass<AgentCallbackLoginEvent>();
		RegisterClass<AgentCallbackLogoffEvent>();
		RegisterClass<AgentCalledEvent>();
		RegisterClass<AgentCompleteEvent>();
		RegisterClass<AgentConnectEvent>();
		RegisterClass<AgentDumpEvent>();
		RegisterClass<AgentLoginEvent>();
		RegisterClass<AgentLogoffEvent>();
		RegisterClass<AgentRingNoAnswer>();
		RegisterClass<AgentsCompleteEvent>();
		RegisterClass<AgiExecEvent>();
		RegisterClass<AlarmClearEvent>();
		RegisterClass<AlarmEvent>();
		RegisterClass<AsyncAgiEvent>();
		RegisterClass<BridgeEvent>();
		RegisterClass<BridgeExecEvent>();
		RegisterClass<CdrEvent>();
		RegisterClass<ChannelReloadEvent>();
		RegisterClass<ChannelUpdateEvent>();
		RegisterClass<ConfbridgeEndEvent>();
		RegisterClass<ConfbridgeJoinEvent>();
		RegisterClass<ConfbridgeLeaveEvent>();
		RegisterClass<ConfbridgeListCompleteEvent>();
		RegisterClass<ConfbridgeListEvent>();
		RegisterClass<ConfbridgeListRoomsCompleteEvent>();
		RegisterClass<ConfbridgeListRoomsEvent>();
		RegisterClass<ConfbridgeStartEvent>();
		RegisterClass<ConfbridgeTalkingEvent>();
		RegisterClass<ConnectEvent>();
		RegisterClass<CoreShowChannelEvent>();
		RegisterClass<CoreShowChannelsCompleteEvent>();
		RegisterClass<DbGetResponseEvent>();
		RegisterClass<DialEvent>();
		RegisterClass<DisconnectEvent>();
		RegisterClass<DndStateEvent>();
		RegisterClass<DtmfEvent>();
		RegisterClass<ExtensionStatusEvent>();
		RegisterClass<FaxDocumentStatusEvent>();
		RegisterClass<FaxReceivedEvent>();
		RegisterClass<FaxStatusEvent>();
		RegisterClass<FullyBootedEvent>();
		RegisterClass<HangupEvent>();
		RegisterClass<HoldEvent>();
		RegisterClass<HoldedCallEvent>();
		RegisterClass<JabberEventEvent>();
		RegisterClass<JitterBufStatsEvent>();
		RegisterClass<JoinEvent>();
		RegisterClass<LeaveEvent>();
		RegisterClass<LinkEvent>();
		RegisterClass<ListDialplanEvent>();
		RegisterClass<LogChannelEvent>();
		RegisterClass<MasqueradeEvent>();
		RegisterClass<MeetMeEndEvent>();
		RegisterClass<MeetMeJoinEvent>();

	}

	EventBuilder::~EventBuilder() {

	}

	static std::string extractEventName(const std::string& eventStr) {
		size_t endl = eventStr.find("\r\n");
		if (endl != eventStr.npos) {
			size_t sep = eventStr.find("Event: ");
			if (sep != eventStr.npos) {
				return (eventStr.substr(sep + 7, endl - (sep + 7)));
			}
		}
		return ("");
	}

	ManagerEvent* EventBuilder::buildEvent(const std::string& eventStr) {

		std::string eventName = extractEventName(eventStr);
		if (!eventName.empty()) {

			EnventFactoryMapType::const_iterator it = eventFactoryMap.find(eventName);
			if (it != eventFactoryMap.end()) {
				return ((it->second)->create(eventStr));
			} else {
				LOG_WARN_STR("EVENT:INVALID OR NOT IMPLEMENTED \n"+ str2Log(eventStr))
				return (new ManagerEvent(eventStr));
			}
		}

		return (NULL);
	}

} /* namespace asterisk_cpp */

<commit_msg>register new class on builder<commit_after>/*
 * EventBuilder.cpp
 *
 *  Created on: Jul 12, 2011
 *      Author: augcampos
 */

#include "asteriskcpp/manager/EventBuilder.h"
#include <stdlib.h>
#include <map>
#include "asteriskcpp/utils/StringUtils.h"

#include "asteriskcpp/manager/events/AgentCallbackLoginEvent.h"
#include "asteriskcpp/manager/events/AgentCallbackLogoffEvent.h"
#include "asteriskcpp/manager/events/AgentCalledEvent.h"
#include "asteriskcpp/manager/events/AgentCompleteEvent.h"
#include "asteriskcpp/manager/events/AgentConnectEvent.h"
#include "asteriskcpp/manager/events/AgentDumpEvent.h"
#include "asteriskcpp/manager/events/AgentLoginEvent.h"
#include "asteriskcpp/manager/events/AgentLogoffEvent.h"
#include "asteriskcpp/manager/events/AgentRingNoAnswer.h"
#include "asteriskcpp/manager/events/AgentsCompleteEvent.h"
#include "asteriskcpp/manager/events/AgentsEvent.h"
#include "asteriskcpp/manager/events/AgiExecEvent.h"
#include "asteriskcpp/manager/events/AlarmClearEvent.h"
#include "asteriskcpp/manager/events/AlarmEvent.h"
#include "asteriskcpp/manager/events/AsyncAgiEvent.h"
#include "asteriskcpp/manager/events/BridgeEvent.h"
#include "asteriskcpp/manager/events/BridgeExecEvent.h"
#include "asteriskcpp/manager/events/CdrEvent.h"
#include "asteriskcpp/manager/events/ChannelReloadEvent.h"
#include "asteriskcpp/manager/events/ChannelUpdateEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeEndEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeJoinEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeLeaveEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListCompleteEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListRoomsCompleteEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeListRoomsEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeStartEvent.h"
#include "asteriskcpp/manager/events/ConfbridgeTalkingEvent.h"
#include "asteriskcpp/manager/events/ConnectEvent.h"
#include "asteriskcpp/manager/events/CoreShowChannelEvent.h"
#include "asteriskcpp/manager/events/CoreShowChannelsCompleteEvent.h"
#include "asteriskcpp/manager/events/DbGetResponseEvent.h"
#include "asteriskcpp/manager/events/DialEvent.h"
#include "asteriskcpp/manager/events/DisconnectEvent.h"
#include "asteriskcpp/manager/events/DndStateEvent.h"
#include "asteriskcpp/manager/events/DtmfEvent.h"
#include "asteriskcpp/manager/events/ExtensionStatusEvent.h"
#include "asteriskcpp/manager/events/FaxDocumentStatusEvent.h"
#include "asteriskcpp/manager/events/FaxReceivedEvent.h"
#include "asteriskcpp/manager/events/FaxStatusEvent.h"
#include "asteriskcpp/manager/events/FullyBootedEvent.h"
#include "asteriskcpp/manager/events/HangupEvent.h"
#include "asteriskcpp/manager/events/HoldEvent.h"
#include "asteriskcpp/manager/events/HoldedCallEvent.h"
#include "asteriskcpp/manager/events/JabberEventEvent.h"
#include "asteriskcpp/manager/events/JitterBufStatsEvent.h"
#include "asteriskcpp/manager/events/JoinEvent.h"
#include "asteriskcpp/manager/events/LeaveEvent.h"
#include "asteriskcpp/manager/events/LinkEvent.h"
#include "asteriskcpp/manager/events/ListDialplanEvent.h"
#include "asteriskcpp/manager/events/LogChannelEvent.h"
#include "asteriskcpp/manager/events/MasqueradeEvent.h"
#include "asteriskcpp/manager/events/MeetMeEndEvent.h"
#include "asteriskcpp/manager/events/MeetMeJoinEvent.h"

namespace asteriskcpp {

	EventBuilder::EventBuilder() {
		RegisterClass<AgentCallbackLoginEvent>();
		RegisterClass<AgentCallbackLogoffEvent>();
		RegisterClass<AgentCalledEvent>();
		RegisterClass<AgentCompleteEvent>();
		RegisterClass<AgentConnectEvent>();
		RegisterClass<AgentDumpEvent>();
		RegisterClass<AgentLoginEvent>();
		RegisterClass<AgentLogoffEvent>();
		RegisterClass<AgentRingNoAnswer>();
		RegisterClass<AgentsCompleteEvent>();
		RegisterClass<AgentsEvent>();
		RegisterClass<AgiExecEvent>();
		RegisterClass<AlarmClearEvent>();
		RegisterClass<AlarmEvent>();
		RegisterClass<AsyncAgiEvent>();
		RegisterClass<BridgeEvent>();
		RegisterClass<BridgeExecEvent>();
		RegisterClass<CdrEvent>();
		RegisterClass<ChannelReloadEvent>();
		RegisterClass<ChannelUpdateEvent>();
		RegisterClass<ConfbridgeEndEvent>();
		RegisterClass<ConfbridgeJoinEvent>();
		RegisterClass<ConfbridgeLeaveEvent>();
		RegisterClass<ConfbridgeListCompleteEvent>();
		RegisterClass<ConfbridgeListEvent>();
		RegisterClass<ConfbridgeListRoomsCompleteEvent>();
		RegisterClass<ConfbridgeListRoomsEvent>();
		RegisterClass<ConfbridgeStartEvent>();
		RegisterClass<ConfbridgeTalkingEvent>();
		RegisterClass<ConnectEvent>();
		RegisterClass<CoreShowChannelEvent>();
		RegisterClass<CoreShowChannelsCompleteEvent>();
		RegisterClass<DbGetResponseEvent>();
		RegisterClass<DialEvent>();
		RegisterClass<DisconnectEvent>();
		RegisterClass<DndStateEvent>();
		RegisterClass<DtmfEvent>();
		RegisterClass<ExtensionStatusEvent>();
		RegisterClass<FaxDocumentStatusEvent>();
		RegisterClass<FaxReceivedEvent>();
		RegisterClass<FaxStatusEvent>();
		RegisterClass<FullyBootedEvent>();
		RegisterClass<HangupEvent>();
		RegisterClass<HoldEvent>();
		RegisterClass<HoldedCallEvent>();
		RegisterClass<JabberEventEvent>();
		RegisterClass<JitterBufStatsEvent>();
		RegisterClass<JoinEvent>();
		RegisterClass<LeaveEvent>();
		RegisterClass<LinkEvent>();
		RegisterClass<ListDialplanEvent>();
		RegisterClass<LogChannelEvent>();
		RegisterClass<MasqueradeEvent>();
		RegisterClass<MeetMeEndEvent>();
		RegisterClass<MeetMeJoinEvent>();

	}

	EventBuilder::~EventBuilder() {

	}

	static std::string extractEventName(const std::string& eventStr) {
		size_t endl = eventStr.find("\r\n");
		if (endl != eventStr.npos) {
			size_t sep = eventStr.find("Event: ");
			if (sep != eventStr.npos) {
				return (eventStr.substr(sep + 7, endl - (sep + 7)));
			}
		}
		return ("");
	}

	ManagerEvent* EventBuilder::buildEvent(const std::string& eventStr) {

		std::string eventName = extractEventName(eventStr);
		if (!eventName.empty()) {

			EnventFactoryMapType::const_iterator it = eventFactoryMap.find(eventName);
			if (it != eventFactoryMap.end()) {
				return ((it->second)->create(eventStr));
			} else {
				LOG_WARN_STR("EVENT:INVALID OR NOT IMPLEMENTED \n"+ str2Log(eventStr))
				return (new ManagerEvent(eventStr));
			}
		}

		return (NULL);
	}

} /* namespace asterisk_cpp */

<|endoftext|>


<commit_before><commit_msg>replace '\n' to space in extended help text<commit_after><|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "net/AsyncHttp.h"
#include "common/StringConverter.h"
#include "net/URI.h"
#include "common/RhodesApp.h"
#include "common/RhoAppAdapter.h"

namespace rho
{
using namespace rho::common;
namespace net
{

IMPLEMENT_LOGCLASS(CAsyncHttp, "AsyncHttp");
CAsyncHttp* CAsyncHttp::m_pInstance = 0;

/*static*/ CAsyncHttp* CAsyncHttp::Create()
{
    if ( m_pInstance )
        return m_pInstance;

    m_pInstance = new CAsyncHttp( );
    return m_pInstance;
}

/*static*/void CAsyncHttp::Destroy()
{
    if ( m_pInstance )
        delete m_pInstance;

    m_pInstance = 0;
}

CAsyncHttp::CAsyncHttp(boolean bInternal) : CThreadQueue(bInternal)
{
	CThreadQueue::setLogCategory(getLogCategory());

    setPollInterval(QUEUE_POLL_INTERVAL_INFINITE);

	//if(bInternal)
	//	start(epNormal);
}

CAsyncHttp::~CAsyncHttp(void)
{
    stop(-1);
    LOG(INFO) + "Thread shutdown";
}

unsigned long CAsyncHttp::addHttpCommand(IQueueCommand* pCmd)
{
	if (!isLogThread() && ((CHttpCommand*)pCmd)->m_strCallback.length()==0)
    {
        processCommandBase(pCmd);
        unsigned long ret = ((CHttpCommand*)pCmd)->getRetValue();
        delete pCmd;
        return ret;
    }
	else if(isLogThread())
		start(epNormal);
	else
		start(epLow);

	CThreadQueue::addQueueCommand(pCmd);

    return ((CHttpCommand*)pCmd)->getRetValue();
}

void CAsyncHttp::cancelRequest(const char* szCallback)
{
    if (!szCallback || !*szCallback )
    {
        LOG(INFO) + "Cancel callback should not be empty. Use * for cancel all";
        return;
    }

    synchronized(getCommandLock());
    CHttpCommand* pCmd = (CHttpCommand*)getCurCommand();

    if ( pCmd != null && ( *szCallback == '*' || pCmd->m_strCallback.compare(szCallback) == 0) )
        pCmd->cancel();

    if ( *szCallback == '*' )
        getCommands().clear();
    else
    {
        for (int i = getCommands().size()-1; i >= 0; i--)
        {
            CHttpCommand* pCmd1 = (CHttpCommand*)getCommands().get(i);

            if ( pCmd1 != null && pCmd1->m_strCallback.compare(szCallback) == 0 )
                getCommands().remove(i);
        }

    }
}

void CAsyncHttp::processCommand(IQueueCommand* pCmd)
{
    ((CHttpCommand*)pCmd)->execute();
}

extern "C" void header_iter(const char* szName, const char* szValue, void* pHash)
{
    ((Hashtable<String,String>*)pHash)->put(szName, szValue);
}

CAsyncHttp::CHttpCommand::CHttpCommand(String strCmd, rho_param *p) : m_params(p)
{
    m_eCmd = translateCommand(strCmd);
    m_strCallback = m_params.getString("callback");
    m_strCallbackParams = m_params.getString("callback_param");

    m_params.getHash("headers", m_mapHeaders);

    if(m_params.has("ssl_verify_peer"))
        m_NetRequest.setSslVerifyPeer(m_params.getBool("ssl_verify_peer"));
}

void CAsyncHttp::CHttpCommand::execute()
{
    NetResponse resp;
    switch( m_eCmd )
    {
    case hcGet:
        resp = getNet().doRequest( m_params.getString("http_command", "GET").c_str(),
            m_params.getString("url"), m_params.getString("body"), null, &m_mapHeaders);
        break;
	case hcPost:{
        resp = getNet().doRequest(m_params.getString("http_command", "POST").c_str(),
			m_params.getString("url"), m_params.getString("body"), null, &m_mapHeaders);}
        break;

    case hcDownload:
        resp = getNet().pullFile(m_params.getString("url"), m_params.getString("filename"), null, &m_mapHeaders);
        break;

    case hcUpload:
        {
            VectorPtr<net::CMultipartItem*> arMultipartItems;

            CRhoParamArray arParams( m_params, "multipart");
            if ( arParams.size() > 0 )
            {
                for( int i = 0; i < arParams.size(); i++)
                {
                    CRhoParams oItem = arParams.getItem(i);

                    net::CMultipartItem* pItem = new net::CMultipartItem();
                    String strFilePath = oItem.getString("filename");
                    if ( strFilePath.length() == 0 )
                    {
                        pItem->m_strBody = oItem.getString("body");
                        pItem->m_strContentType = oItem.getString("content_type", "");
                    }
                    else
                    {
                        pItem->m_strFilePath = strFilePath;
                        pItem->m_strContentType = oItem.getString("content_type", "application/octet-stream");
                    }

                    pItem->m_strName = oItem.getString("name");
                    pItem->m_strFileName = oItem.getString("filename_base");
                    arMultipartItems.addElement(pItem);
                }
            }else
            {
                net::CMultipartItem* pItem = new net::CMultipartItem();
                pItem->m_strFilePath = m_params.getString("filename");
                pItem->m_strContentType = m_params.getString("file_content_type", "application/octet-stream");
                pItem->m_strName = m_params.getString("name");
                pItem->m_strFileName = m_params.getString("filename_base");
                arMultipartItems.addElement(pItem);

                String strBody = m_params.getString("body");
                if ( strBody.length() > 0 )
                {
                    net::CMultipartItem* pItem2 = new net::CMultipartItem();
                    pItem2->m_strBody = strBody;
                    pItem2->m_strContentType = m_mapHeaders.get("content-type");
                    arMultipartItems.addElement(pItem2);
                }
            }

            resp = getNet().pushMultipartData( m_params.getString("url"), arMultipartItems, null, &m_mapHeaders );
            break;
        }
    default: ;
    }

    if ( !m_NetRequest.isCancelled())
        callNotify(resp,0);

    m_params.free_params();
}

unsigned long CAsyncHttp::CHttpCommand::getRetValue()
{
	if ( m_strCallback.length() == 0 )
		return atoi(m_strCallback.c_str());//rho_ruby_create_string(m_strCallback.c_str());

    return rho_ruby_get_NIL();
}

String CAsyncHttp::CHttpCommand::makeHeadersString()
{
    String strRes = "";

    for ( Hashtable<String,String>::iterator it = m_mapHeaders.begin();  it != m_mapHeaders.end(); ++it )
    {
        if ( strRes.length() > 0)
            strRes += "&";

        strRes += "headers[";
        URI::urlEncode(it->first,strRes);
        strRes += "]=";
        URI::urlEncode(it->second,strRes);
    }

    return strRes;
}

void CAsyncHttp::CHttpCommand::callNotify(NetResponse& resp, int nError )
{
	m_strResBody = "rho_callback=1";
    m_strResBody += "&status=";
    if ( nError > 0 )
    {
    	m_strResBody += "error&error_code=" + nError;
    }else
    {
        if ( resp.isSuccess() )
        {
    	    m_strResBody += "ok";
            if ( resp.isResponseRecieved())
	            m_strResBody += "&http_error=" + convertToStringA(resp.getRespCode());
        }
        else
        {
    	    m_strResBody += "error&error_code=";
            m_strResBody += convertToStringA(RhoAppAdapter.getErrorFromResponse(resp));
            if ( resp.isResponseRecieved())
	            m_strResBody += "&http_error=" + convertToStringA(resp.getRespCode());
        }

        String cookies = resp.getCookies();
        if (cookies.length()>0)
            m_strResBody += "&cookies=" + URI::urlEncode(cookies);

        String strHeaders = makeHeadersString();
        if (strHeaders.length() > 0 )
            m_strResBody += "&" + strHeaders;

        m_strResBody += "&" + RHODESAPP().addCallbackObject(
            new CAsyncHttpResponse(resp, m_mapHeaders.get("content-type")), "body");
    }

    if ( m_strCallbackParams.length() > 0 )
        m_strResBody += "&" + m_strCallbackParams;

    if ( m_strCallback.length() > 0 )
    {
        String strFullUrl = m_NetRequest.resolveUrl(m_strCallback);
        getNet().pushData( strFullUrl, m_strResBody, null );
    }
}

CAsyncHttp::CAsyncHttpResponse::~CAsyncHttpResponse(){}

extern "C" VALUE rjson_tokener_parse(const char *str, char** pszError );
unsigned long CAsyncHttp::CAsyncHttpResponse::getObjectValue()
{
    if (m_NetResponse.isSuccess())
    {
        if ( m_strContentType.find("application/json") != String::npos )
        {
            char* szError = 0;
            unsigned long valBody = rjson_tokener_parse(m_NetResponse.getCharData(), &szError);
            if ( valBody != 0 )
                return valBody;

            LOG(ERROR) + "Incorrect json body.Error:" + (szError ? szError : "");
            if ( szError )
                free(szError);
        }
    }

    return rho_ruby_create_string(m_NetResponse.getCharData());
}

} // namespace net
} // namespace rho

extern "C" {

using namespace rho::net;

void rho_asynchttp_cancel(const char* cancel_callback)
{
    if ( CAsyncHttp::getInstance() != null )
        CAsyncHttp::getInstance()->cancelRequest(cancel_callback);
}

unsigned long rho_asynchttp_request(const char* command, rho_param *p)
{
    CAsyncHttp::Create();

    return CAsyncHttp::getInstance()->addHttpCommand(new CAsyncHttp::CHttpCommand( command, p ));
}

}
<commit_msg>fixed bug i did before<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "net/AsyncHttp.h"
#include "common/StringConverter.h"
#include "net/URI.h"
#include "common/RhodesApp.h"
#include "common/RhoAppAdapter.h"

namespace rho
{
using namespace rho::common;
namespace net
{

IMPLEMENT_LOGCLASS(CAsyncHttp, "AsyncHttp");
CAsyncHttp* CAsyncHttp::m_pInstance = 0;

/*static*/ CAsyncHttp* CAsyncHttp::Create()
{
    if ( m_pInstance )
        return m_pInstance;

    m_pInstance = new CAsyncHttp( );
    return m_pInstance;
}

/*static*/void CAsyncHttp::Destroy()
{
    if ( m_pInstance )
        delete m_pInstance;

    m_pInstance = 0;
}

CAsyncHttp::CAsyncHttp(boolean bInternal) : CThreadQueue(bInternal)
{
	CThreadQueue::setLogCategory(getLogCategory());

    setPollInterval(QUEUE_POLL_INTERVAL_INFINITE);

	//if(bInternal)
	//	start(epNormal);
}

CAsyncHttp::~CAsyncHttp(void)
{
    stop(-1);
    LOG(INFO) + "Thread shutdown";
}

unsigned long CAsyncHttp::addHttpCommand(IQueueCommand* pCmd)
{
	if (!isLogThread() && ((CHttpCommand*)pCmd)->m_strCallback.length()==0)
    {
        processCommandBase(pCmd);
        unsigned long ret = ((CHttpCommand*)pCmd)->getRetValue();
        delete pCmd;
        return ret;
    }
	else if(isLogThread())
		start(epNormal);
	else
		start(epLow);

	CThreadQueue::addQueueCommand(pCmd);

    return ((CHttpCommand*)pCmd)->getRetValue();
}

void CAsyncHttp::cancelRequest(const char* szCallback)
{
    if (!szCallback || !*szCallback )
    {
        LOG(INFO) + "Cancel callback should not be empty. Use * for cancel all";
        return;
    }

    synchronized(getCommandLock());
    CHttpCommand* pCmd = (CHttpCommand*)getCurCommand();

    if ( pCmd != null && ( *szCallback == '*' || pCmd->m_strCallback.compare(szCallback) == 0) )
        pCmd->cancel();

    if ( *szCallback == '*' )
        getCommands().clear();
    else
    {
        for (int i = getCommands().size()-1; i >= 0; i--)
        {
            CHttpCommand* pCmd1 = (CHttpCommand*)getCommands().get(i);

            if ( pCmd1 != null && pCmd1->m_strCallback.compare(szCallback) == 0 )
                getCommands().remove(i);
        }

    }
}

void CAsyncHttp::processCommand(IQueueCommand* pCmd)
{
    ((CHttpCommand*)pCmd)->execute();
}

extern "C" void header_iter(const char* szName, const char* szValue, void* pHash)
{
    ((Hashtable<String,String>*)pHash)->put(szName, szValue);
}

CAsyncHttp::CHttpCommand::CHttpCommand(String strCmd, rho_param *p) : m_params(p)
{
    m_eCmd = translateCommand(strCmd);
    m_strCallback = m_params.getString("callback");
    m_strCallbackParams = m_params.getString("callback_param");

    m_params.getHash("headers", m_mapHeaders);

    if(m_params.has("ssl_verify_peer"))
        m_NetRequest.setSslVerifyPeer(m_params.getBool("ssl_verify_peer"));
}

void CAsyncHttp::CHttpCommand::execute()
{
    NetResponse resp;
    switch( m_eCmd )
    {
    case hcGet:
        resp = getNet().doRequest( m_params.getString("http_command", "GET").c_str(),
            m_params.getString("url"), m_params.getString("body"), null, &m_mapHeaders);
        break;
	case hcPost:{
        resp = getNet().doRequest(m_params.getString("http_command", "POST").c_str(),
			m_params.getString("url"), m_params.getString("body"), null, &m_mapHeaders);}
        break;

    case hcDownload:
        resp = getNet().pullFile(m_params.getString("url"), m_params.getString("filename"), null, &m_mapHeaders);
        break;

    case hcUpload:
        {
            VectorPtr<net::CMultipartItem*> arMultipartItems;

            CRhoParamArray arParams( m_params, "multipart");
            if ( arParams.size() > 0 )
            {
                for( int i = 0; i < arParams.size(); i++)
                {
                    CRhoParams oItem = arParams.getItem(i);

                    net::CMultipartItem* pItem = new net::CMultipartItem();
                    String strFilePath = oItem.getString("filename");
                    if ( strFilePath.length() == 0 )
                    {
                        pItem->m_strBody = oItem.getString("body");
                        pItem->m_strContentType = oItem.getString("content_type", "");
                    }
                    else
                    {
                        pItem->m_strFilePath = strFilePath;
                        pItem->m_strContentType = oItem.getString("content_type", "application/octet-stream");
                    }

                    pItem->m_strName = oItem.getString("name");
                    pItem->m_strFileName = oItem.getString("filename_base");
                    arMultipartItems.addElement(pItem);
                }
            }else
            {
                net::CMultipartItem* pItem = new net::CMultipartItem();
                pItem->m_strFilePath = m_params.getString("filename");
                pItem->m_strContentType = m_params.getString("file_content_type", "application/octet-stream");
                pItem->m_strName = m_params.getString("name");
                pItem->m_strFileName = m_params.getString("filename_base");
                arMultipartItems.addElement(pItem);

                String strBody = m_params.getString("body");
                if ( strBody.length() > 0 )
                {
                    net::CMultipartItem* pItem2 = new net::CMultipartItem();
                    pItem2->m_strBody = strBody;
                    pItem2->m_strContentType = m_mapHeaders.get("content-type");
                    arMultipartItems.addElement(pItem2);
                }
            }

            resp = getNet().pushMultipartData( m_params.getString("url"), arMultipartItems, null, &m_mapHeaders );
            break;
        }
    default: ;
    }

    if ( !m_NetRequest.isCancelled())
        callNotify(resp,0);

    m_params.free_params();
}

unsigned long CAsyncHttp::CHttpCommand::getRetValue()
{
	if ( m_strCallback.length() == 0 )
		return atoi(m_strResBody.c_str());//rho_ruby_create_string(m_strCallback.c_str());

    return rho_ruby_get_NIL();
}

String CAsyncHttp::CHttpCommand::makeHeadersString()
{
    String strRes = "";

    for ( Hashtable<String,String>::iterator it = m_mapHeaders.begin();  it != m_mapHeaders.end(); ++it )
    {
        if ( strRes.length() > 0)
            strRes += "&";

        strRes += "headers[";
        URI::urlEncode(it->first,strRes);
        strRes += "]=";
        URI::urlEncode(it->second,strRes);
    }

    return strRes;
}

void CAsyncHttp::CHttpCommand::callNotify(NetResponse& resp, int nError )
{
	m_strResBody = "rho_callback=1";
    m_strResBody += "&status=";
    if ( nError > 0 )
    {
    	m_strResBody += "error&error_code=" + nError;
    }else
    {
        if ( resp.isSuccess() )
        {
    	    m_strResBody += "ok";
            if ( resp.isResponseRecieved())
	            m_strResBody += "&http_error=" + convertToStringA(resp.getRespCode());
        }
        else
        {
    	    m_strResBody += "error&error_code=";
            m_strResBody += convertToStringA(RhoAppAdapter.getErrorFromResponse(resp));
            if ( resp.isResponseRecieved())
	            m_strResBody += "&http_error=" + convertToStringA(resp.getRespCode());
        }

        String cookies = resp.getCookies();
        if (cookies.length()>0)
            m_strResBody += "&cookies=" + URI::urlEncode(cookies);

        String strHeaders = makeHeadersString();
        if (strHeaders.length() > 0 )
            m_strResBody += "&" + strHeaders;

        m_strResBody += "&" + RHODESAPP().addCallbackObject(
            new CAsyncHttpResponse(resp, m_mapHeaders.get("content-type")), "body");
    }

    if ( m_strCallbackParams.length() > 0 )
        m_strResBody += "&" + m_strCallbackParams;

    if ( m_strCallback.length() > 0 )
    {
        String strFullUrl = m_NetRequest.resolveUrl(m_strCallback);
        getNet().pushData( strFullUrl, m_strResBody, null );
    }
}

CAsyncHttp::CAsyncHttpResponse::~CAsyncHttpResponse(){}

extern "C" VALUE rjson_tokener_parse(const char *str, char** pszError );
unsigned long CAsyncHttp::CAsyncHttpResponse::getObjectValue()
{
    if (m_NetResponse.isSuccess())
    {
        if ( m_strContentType.find("application/json") != String::npos )
        {
            char* szError = 0;
            unsigned long valBody = rjson_tokener_parse(m_NetResponse.getCharData(), &szError);
            if ( valBody != 0 )
                return valBody;

            LOG(ERROR) + "Incorrect json body.Error:" + (szError ? szError : "");
            if ( szError )
                free(szError);
        }
    }

    return rho_ruby_create_string(m_NetResponse.getCharData());
}

} // namespace net
} // namespace rho

extern "C" {

using namespace rho::net;

void rho_asynchttp_cancel(const char* cancel_callback)
{
    if ( CAsyncHttp::getInstance() != null )
        CAsyncHttp::getInstance()->cancelRequest(cancel_callback);
}

unsigned long rho_asynchttp_request(const char* command, rho_param *p)
{
    CAsyncHttp::Create();

    return CAsyncHttp::getInstance()->addHttpCommand(new CAsyncHttp::CHttpCommand( command, p ));
}

}
<|endoftext|>


<commit_before>/*
 * SessionTeX.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionTeX.hpp"

#include <string>

#include <core/Log.hpp>
#include <core/Error.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>

#include <r/RExec.hpp>
#include <r/RRoutines.hpp>

#include <session/SessionModuleContext.hpp>

using namespace core;

namespace session {
namespace modules {
namespace tex {

namespace {

FilePath pdfPathForTexPath(const FilePath& texPath)
{
   return texPath.parent().complete(texPath.stem() + ".pdf");
}

void callSweave(const std::string& rBinDir,
                const std::string& file)
{
   // build R exe path and args
#ifdef _WIN32
   std::string path = FilePath(rBinDir).complete("Rterm.exe").absolutePath();
   core::system::Options args;
   std::string sweaveCmd = "\"Sweave('" + file + "')\"";
   args.push_back(std::make_pair("-e", sweaveCmd));
   args.push_back(std::make_pair("--silent", ""));
#else
   std::string path = FilePath(rBinDir).complete("R").absolutePath();
   core::system::Options args;
   args.push_back(std::make_pair("CMD", "Sweave"));
   args.push_back(std::make_pair(file, ""));
#endif

   // call sweave
   Error error = module_context::executeInterruptableChild(path, args);
   if (error)
      LOG_ERROR(error);
}

SEXP rs_callSweave(SEXP rBinDirSEXP, SEXP fileSEXP)
{
   // call sweave
   callSweave(r::sexp::asString(rBinDirSEXP),
              r::sexp::asString(fileSEXP));

   // check for interrupts (likely since sweave can be long running)
   r::exec::checkUserInterrupt();

   return R_NilValue;
}

SEXP rs_validateTexFile(SEXP texFileSEXP)
{
   // used to protect return value
   r::sexp::Protect rProtect;

   // get path to TeX file and read its contents
   std::string texFile = r::sexp::asString(texFileSEXP);
   FilePath texFilePath = module_context::safeCurrentPath().complete(texFile);
   if (!texFilePath.exists())
      return r::sexp::create(false, &rProtect);

   std::string contents;
   Error error = readStringFromFile(texFilePath, &contents);
   if (error)
   {
      LOG_ERROR(error);
      return r::sexp::create(false, &rProtect);
   }

   // return based on whether it contains an \end{document}
   bool hasEndDoc = contents.find("\\end{document}") != std::string::npos;
   return r::sexp::create(hasEndDoc, &rProtect);
}

SEXP rs_viewPdf(SEXP texPathSEXP)
{
   FilePath pdfPath = pdfPathForTexPath(FilePath(r::sexp::asString(texPathSEXP)));
   module_context::showFile(pdfPath, "_rstudio_compile_pdf");
   return R_NilValue;
}

} // anonymous namespace

Error initialize()
{
   // On Mac OS make sure the path is updated to find MacTeX or
   // MacPorts texlive
#ifdef __APPLE__
   if (session::options().programMode() == kSessionProgramModeDesktop)
   {
      FilePath macportsTex("/opt/local/bin/tex");
      if (macportsTex.exists())
         core::system::addToSystemPath(macportsTex, true); // prepend
      FilePath mactexTex("/usr/texbin");
      if (mactexTex.exists())
         core::system::addToSystemPath(mactexTex);
   }
#endif

   // install core Sweave/TeX routines
   R_CallMethodDef callSweaveMethodDef;
   callSweaveMethodDef.name = "rs_callSweave" ;
   callSweaveMethodDef.fun = (DL_FUNC) rs_callSweave ;
   callSweaveMethodDef.numArgs = 2;
   r::routines::addCallMethod(callSweaveMethodDef);

   R_CallMethodDef validateTexFileMethodDef;
   validateTexFileMethodDef.name = "rs_validateTexFile" ;
   validateTexFileMethodDef.fun = (DL_FUNC) rs_validateTexFile ;
   validateTexFileMethodDef.numArgs = 1;
   r::routines::addCallMethod(validateTexFileMethodDef);

   R_CallMethodDef viewPdfMethodDef ;
   viewPdfMethodDef.name = "rs_viewPdf" ;
   viewPdfMethodDef.fun = (DL_FUNC) rs_viewPdf ;
   viewPdfMethodDef.numArgs = 1;
   r::routines::addCallMethod(viewPdfMethodDef);

   // source TeX R helpers
   return module_context::sourceModuleRFile("SessionTeX.R");
}

} // namespace tex
} // namespace modules
} // namesapce session

<commit_msg>revise osx tex path munging to only work if the path isn't already there<commit_after>/*
 * SessionTeX.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionTeX.hpp"

#include <string>

#include <boost/regex.hpp>

#include <core/Log.hpp>
#include <core/Error.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>

#include <r/RExec.hpp>
#include <r/RRoutines.hpp>

#include <session/SessionModuleContext.hpp>

using namespace core;

namespace session {
namespace modules {
namespace tex {

namespace {

FilePath pdfPathForTexPath(const FilePath& texPath)
{
   return texPath.parent().complete(texPath.stem() + ".pdf");
}

void callSweave(const std::string& rBinDir,
                const std::string& file)
{
   // build R exe path and args
#ifdef _WIN32
   std::string path = FilePath(rBinDir).complete("Rterm.exe").absolutePath();
   core::system::Options args;
   std::string sweaveCmd = "\"Sweave('" + file + "')\"";
   args.push_back(std::make_pair("-e", sweaveCmd));
   args.push_back(std::make_pair("--silent", ""));
#else
   std::string path = FilePath(rBinDir).complete("R").absolutePath();
   core::system::Options args;
   args.push_back(std::make_pair("CMD", "Sweave"));
   args.push_back(std::make_pair(file, ""));
#endif

   // call sweave
   Error error = module_context::executeInterruptableChild(path, args);
   if (error)
      LOG_ERROR(error);
}

SEXP rs_callSweave(SEXP rBinDirSEXP, SEXP fileSEXP)
{
   // call sweave
   callSweave(r::sexp::asString(rBinDirSEXP),
              r::sexp::asString(fileSEXP));

   // check for interrupts (likely since sweave can be long running)
   r::exec::checkUserInterrupt();

   return R_NilValue;
}

SEXP rs_validateTexFile(SEXP texFileSEXP)
{
   // used to protect return value
   r::sexp::Protect rProtect;

   // get path to TeX file and read its contents
   std::string texFile = r::sexp::asString(texFileSEXP);
   FilePath texFilePath = module_context::safeCurrentPath().complete(texFile);
   if (!texFilePath.exists())
      return r::sexp::create(false, &rProtect);

   std::string contents;
   Error error = readStringFromFile(texFilePath, &contents);
   if (error)
   {
      LOG_ERROR(error);
      return r::sexp::create(false, &rProtect);
   }

   // return based on whether it contains an \end{document}
   bool hasEndDoc = contents.find("\\end{document}") != std::string::npos;
   return r::sexp::create(hasEndDoc, &rProtect);
}

SEXP rs_viewPdf(SEXP texPathSEXP)
{
   FilePath pdfPath = pdfPathForTexPath(FilePath(r::sexp::asString(texPathSEXP)));
   module_context::showFile(pdfPath, "_rstudio_compile_pdf");
   return R_NilValue;
}

} // anonymous namespace

Error initialize()
{
   // On Mac OS make sure the path is updated to find MacTeX or
   // MacPorts texlive
#ifdef __APPLE__
   if (session::options().programMode() == kSessionProgramModeDesktop)
   {
      // get path
      std::string path = core::system::getenv("PATH");

      // do we need to add /opt/local/bin?
      FilePath optLocalBinPath("/opt/local/bin");
      if (!regex_search(path, boost::regex("(^|:)/opt/local/bin/?($|:)"))
          && optLocalBinPath.exists())
      {
         // add opt/local/bin to path (prepend so we find macports texi2dvi
         // first if it is installed there)
         core::system::addToSystemPath(optLocalBinPath, true);
      }

      // do we need to add /usr/texbin?
      FilePath texbinPath("/usr/texbin");
      if (!regex_match(path, boost::regex("(^|:)/usr/texbin/?($|:)"))
          && texbinPath.exists())
      {
         core::system::addToSystemPath(texbinPath);
      }
   }
#endif

   // install core Sweave/TeX routines
   R_CallMethodDef callSweaveMethodDef;
   callSweaveMethodDef.name = "rs_callSweave" ;
   callSweaveMethodDef.fun = (DL_FUNC) rs_callSweave ;
   callSweaveMethodDef.numArgs = 2;
   r::routines::addCallMethod(callSweaveMethodDef);

   R_CallMethodDef validateTexFileMethodDef;
   validateTexFileMethodDef.name = "rs_validateTexFile" ;
   validateTexFileMethodDef.fun = (DL_FUNC) rs_validateTexFile ;
   validateTexFileMethodDef.numArgs = 1;
   r::routines::addCallMethod(validateTexFileMethodDef);

   R_CallMethodDef viewPdfMethodDef ;
   viewPdfMethodDef.name = "rs_viewPdf" ;
   viewPdfMethodDef.fun = (DL_FUNC) rs_viewPdf ;
   viewPdfMethodDef.numArgs = 1;
   r::routines::addCallMethod(viewPdfMethodDef);

   // source TeX R helpers
   return module_context::sourceModuleRFile("SessionTeX.R");
}

} // namespace tex
} // namespace modules
} // namesapce session

<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/operator.h"

namespace paddle {
namespace operators {
class RNNMemoryHelperOp : public framework::OperatorBase {
 public:
  RNNMemoryHelperOp(const std::string &type,
                    const framework::VariableNameMap &inputs,
                    const framework::VariableNameMap &outputs,
                    const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}

 private:
  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    auto mem_var_name = Input("X");
    auto *mem_var = scope.FindVar(mem_var_name);
    PADDLE_ENFORCE(mem_var != nullptr,
                   "Cannot find mem_var in scope, mem_var_name is %s",
                   mem_var_name);

    auto out_name = this->Output("Out");
    auto *out_var = scope.FindVar(out_name);
    PADDLE_ENFORCE(out_var != nullptr,
                   "Cannot find out_var in scope, out_var_name is %s",
                   out_name);

    auto *out_tensor = out_var->GetMutable<framework::LoDTensor>();
    auto &mem_tensor = mem_var->Get<framework::LoDTensor>();
    out_tensor->ShareDataWith(mem_tensor);
    out_tensor->set_lod(mem_tensor.lod());
  }
};

class RNNMemoryHelperOpShapeInference : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"), "");
    PADDLE_ENFORCE(ctx->HasOutput("Out"), "");
    ctx->SetOutputDim("Out", ctx->GetInputDim("X"));
    ctx->ShareLoD("X", /*->*/ "Out");
  }
};

class RNNMemoryHelperOpInfoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("X", "");
    AddOutput("Out", "");
    AddAttr<int>("dtype",
                 "(int, default 5 (FP32)) "
                 "Output data type")
        .SetDefault(framework::proto::VarType::FP32);
    AddComment("");
  }
};

class RNNMemoryHelperGradOp : public framework::OperatorBase {
 public:
  RNNMemoryHelperGradOp(const std::string &type,
                        const framework::VariableNameMap &inputs,
                        const framework::VariableNameMap &outputs,
                        const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}

 private:
  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    auto out_grad_var_name = Input(framework::GradVarName("Out"));
    auto *out_grad_var = scope.FindVar(out_grad_var_name);

    auto in_grad_var_name = Output(framework::GradVarName("X"));
    auto *in_grad_var = scope.FindVar(in_grad_var_name);
    PADDLE_ENFORCE(in_grad_var != nullptr,
                   "Cannot find in_grad_var in scope, name is %s",
                   in_grad_var_name);

    if (out_grad_var == nullptr) {
      VLOG(5) << "Using fill constant 0 as starting gradient";
      auto in_var_name = Input("X");
      auto *in_var = scope.FindVar(in_var_name);
      auto &in_var_tensor = in_var->Get<framework::LoDTensor>();

      framework::AttributeMap attrs;
      attrs["dtype"] = framework::ToDataType(in_var_tensor.type());
      attrs["shape"] = framework::vectorize2int(in_var_tensor.dims());
      attrs["value"] = 0.0f;

      auto zero_op = framework::OpRegistry::CreateOp(
          "fill_constant", {}, {{"Out", {in_grad_var_name}}}, attrs);
      zero_op->Run(scope, dev_place);
    } else {
      auto &out_grad_tensor = out_grad_var->Get<framework::LoDTensor>();
      auto *in_grad_tensor = in_grad_var->GetMutable<framework::LoDTensor>();
      in_grad_tensor->ShareDataWith(out_grad_tensor);
      in_grad_tensor->set_lod(out_grad_tensor.lod());
    }
  }
};

class RNNMemoryHelperGradOpInfoMaker
    : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput(framework::GradVarName("Out"), "");
    AddInput("X", "");
    AddInput("Out", "");
    AddOutput(framework::GradVarName("X"), "");
    AddAttr<int>("dtype",
                 "(int, default 5 (FP32)) "
                 "Output data type")
        .SetDefault(framework::proto::VarType::FP32);
    AddComment("");
  }
};

class RNNMemoryHelperGradOpShapeInference : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *ctx) const override {
    auto x_grad_name = framework::GradVarName("X");
    PADDLE_ENFORCE(ctx->HasOutput(x_grad_name), "");
    PADDLE_ENFORCE(ctx->HasInput("X"), "");
    ctx->SetOutputDim(x_grad_name, ctx->GetInputDim("X"));
    ctx->ShareLoD("X", /*->*/ x_grad_name);
  }
};

}  // namespace operators
}  // namespace paddle

REGISTER_OPERATOR(rnn_memory_helper, paddle::operators::RNNMemoryHelperOp,
                  paddle::operators::RNNMemoryHelperOpInfoMaker,
                  paddle::operators::RNNMemoryHelperOpShapeInference,
                  paddle::framework::DefaultGradOpDescMaker<true>);
REGISTER_OPERATOR(rnn_memory_helper_grad,
                  paddle::operators::RNNMemoryHelperGradOp,
                  paddle::operators::RNNMemoryHelperGradOpInfoMaker,
                  paddle::operators::RNNMemoryHelperGradOpShapeInference);
<commit_msg>Add error info & remove data sharing between input and output in rnn_memory_helper_op<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/operator.h"

namespace paddle {
namespace operators {
class RNNMemoryHelperOp : public framework::OperatorBase {
 public:
  RNNMemoryHelperOp(const std::string &type,
                    const framework::VariableNameMap &inputs,
                    const framework::VariableNameMap &outputs,
                    const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}

 private:
  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    auto mem_var_name = Input("X");
    auto *mem_var = scope.FindVar(mem_var_name);
    PADDLE_ENFORCE(mem_var != nullptr,
                   "Cannot find mem_var in scope, mem_var_name is %s",
                   mem_var_name);

    auto out_name = this->Output("Out");
    auto *out_var = scope.FindVar(out_name);
    PADDLE_ENFORCE(out_var != nullptr,
                   "Cannot find out_var in scope, out_var_name is %s",
                   out_name);

    auto *out_tensor = out_var->GetMutable<framework::LoDTensor>();
    auto &mem_tensor = mem_var->Get<framework::LoDTensor>();
    framework::TensorCopySync(mem_tensor, dev_place, out_tensor);
    out_tensor->set_lod(mem_tensor.lod());
  }
};

class RNNMemoryHelperOpShapeInference : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"),
                   "Input(X) of rnn_memory_helper op should not be null.");
    PADDLE_ENFORCE(ctx->HasOutput("Out"),
                   "Output of rnn_memory_helper op should not be null.");
    ctx->SetOutputDim("Out", ctx->GetInputDim("X"));
    ctx->ShareLoD("X", /*->*/ "Out");
  }
};

class RNNMemoryHelperOpInfoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("X", "");
    AddOutput("Out", "");
    AddAttr<int>("dtype",
                 "(int, default 5 (FP32)) "
                 "Output data type")
        .SetDefault(framework::proto::VarType::FP32);
    AddComment("");
  }
};

class RNNMemoryHelperGradOp : public framework::OperatorBase {
 public:
  RNNMemoryHelperGradOp(const std::string &type,
                        const framework::VariableNameMap &inputs,
                        const framework::VariableNameMap &outputs,
                        const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}

 private:
  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    auto out_grad_var_name = Input(framework::GradVarName("Out"));
    auto *out_grad_var = scope.FindVar(out_grad_var_name);

    auto in_grad_var_name = Output(framework::GradVarName("X"));
    auto *in_grad_var = scope.FindVar(in_grad_var_name);
    PADDLE_ENFORCE(in_grad_var != nullptr,
                   "Cannot find in_grad_var in scope, name is %s",
                   in_grad_var_name);

    if (out_grad_var == nullptr) {
      VLOG(5) << "Using fill constant 0 as starting gradient";
      auto in_var_name = Input("X");
      auto *in_var = scope.FindVar(in_var_name);
      auto &in_var_tensor = in_var->Get<framework::LoDTensor>();

      framework::AttributeMap attrs;
      attrs["dtype"] = framework::ToDataType(in_var_tensor.type());
      attrs["shape"] = framework::vectorize2int(in_var_tensor.dims());
      attrs["value"] = 0.0f;

      auto zero_op = framework::OpRegistry::CreateOp(
          "fill_constant", {}, {{"Out", {in_grad_var_name}}}, attrs);
      zero_op->Run(scope, dev_place);
    } else {
      auto &out_grad_tensor = out_grad_var->Get<framework::LoDTensor>();
      auto *in_grad_tensor = in_grad_var->GetMutable<framework::LoDTensor>();
      framework::TensorCopySync(out_grad_tensor, dev_place, in_grad_tensor);
      in_grad_tensor->set_lod(out_grad_tensor.lod());
    }
  }
};

class RNNMemoryHelperGradOpInfoMaker
    : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput(framework::GradVarName("Out"), "");
    AddInput("X", "");
    AddInput("Out", "");
    AddOutput(framework::GradVarName("X"), "");
    AddAttr<int>("dtype",
                 "(int, default 5 (FP32)) "
                 "Output data type")
        .SetDefault(framework::proto::VarType::FP32);
    AddComment("");
  }
};

class RNNMemoryHelperGradOpShapeInference : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *ctx) const override {
    auto x_grad_name = framework::GradVarName("X");
    PADDLE_ENFORCE(ctx->HasOutput(x_grad_name),
                   "Gradient of Input(X) in rnn_memory_helper_grad of should "
                   "not be null.");
    PADDLE_ENFORCE(ctx->HasInput("X"),
                   "Input(X) of rnn_memory_helper_grad of should not be null.");
    ctx->SetOutputDim(x_grad_name, ctx->GetInputDim("X"));
    ctx->ShareLoD("X", /*->*/ x_grad_name);
  }
};

}  // namespace operators
}  // namespace paddle

REGISTER_OPERATOR(rnn_memory_helper, paddle::operators::RNNMemoryHelperOp,
                  paddle::operators::RNNMemoryHelperOpInfoMaker,
                  paddle::operators::RNNMemoryHelperOpShapeInference,
                  paddle::framework::DefaultGradOpDescMaker<true>);
REGISTER_OPERATOR(rnn_memory_helper_grad,
                  paddle::operators::RNNMemoryHelperGradOp,
                  paddle::operators::RNNMemoryHelperGradOpInfoMaker,
                  paddle::operators::RNNMemoryHelperGradOpShapeInference);
<|endoftext|>


<commit_before>#include "../src/include/Player.hpp"
#define BOOST_TEST_MODULE Test_player
#include <boost/test/unit_test.hpp>

/* Fixture: player initialized with 42 lives */
struct PlayerTester {
    Player * p;
    PlayerTester() { p = new Player(42); }
    ~PlayerTester() { delete p; }
};

BOOST_AUTO_TEST_SUITE( Player_constructors )

BOOST_AUTO_TEST_CASE( Player_defaultContructor )
{
    Player p;
    BOOST_CHECK_EQUAL( p.getLifes(), 3 );
}

BOOST_AUTO_TEST_CASE( Player_contructor )
{
    Player p(42);
    BOOST_CHECK_EQUAL( p.getLifes(), 42);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE( Player_removeLife )

BOOST_FIXTURE_TEST_CASE( Player_removeLifes_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLifes(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_removeLifes_default, PlayerTester )
{
    p->removeLifes();
    BOOST_CHECK_EQUAL( p->getLifes(), 41);
}

BOOST_FIXTURE_TEST_CASE( Player_removeLifes_int, PlayerTester )
{
    p->removeLifes(42);
    BOOST_CHECK_EQUAL( p->getLifes(), 42);
}

/*
  BOOST_FIXTURE_TEST_CASE( Player_removeLife_below_zero, PlayerTester )
  {
  p->removeLife(43);
  }
*/

BOOST_AUTO_TEST_SUITE_END() // Player_removeLife

BOOST_AUTO_TEST_SUITE( Player_addLifes )

BOOST_FIXTURE_TEST_CASE( Player_addLifes_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLifes(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_addLifes_default, PlayerTester )
{
    p->addLifes();
    BOOST_CHECK_EQUAL( p->getLifes(), 43);
}

BOOST_FIXTURE_TEST_CASE( Player_addLifes_int, PlayerTester )
{
    p->addLifes(42);
    BOOST_CHECK_EQUAL( p->getLifes(), 84);
}

/*
  BOOST_FIXTURE_TEST_CASE( Player_addLife_overflow, PlayerTester )
  {
  }
*/
BOOST_AUTO_TEST_SUITE_END() // Player_addLife

BOOST_AUTO_TEST_SUITE( Player_setLifes )

BOOST_FIXTURE_TEST_CASE( Player_setLifes_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLifes(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_setLifes_int, PlayerTester )
{
    p->setLifes(1);
    BOOST_CHECK_EQUAL( p->getLifes(), 1);
}

BOOST_AUTO_TEST_SUITE_END() //Player_setLife

/* TODO: same with score */

/* TODO: draw */
<commit_msg>Lifes -> Lives<commit_after>#include "../src/include/Player.hpp"
#define BOOST_TEST_MODULE Test_player
#include <boost/test/unit_test.hpp>

/* Fixture: player initialized with 42 lives */
struct PlayerTester {
    Player * p;
    PlayerTester() { p = new Player(42); }
    ~PlayerTester() { delete p; }
};

BOOST_AUTO_TEST_SUITE( Player_constructors )

BOOST_AUTO_TEST_CASE( Player_defaultContructor )
{
    Player p;
    BOOST_CHECK_EQUAL( p.getLives(), 3 );
}

BOOST_AUTO_TEST_CASE( Player_contructor )
{
    Player p(42);
    BOOST_CHECK_EQUAL( p.getLives(), 42);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE( Player_removeLife )

BOOST_FIXTURE_TEST_CASE( Player_removeLives_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLives(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_removeLives_default, PlayerTester )
{
    p->removeLives();
    BOOST_CHECK_EQUAL( p->getLives(), 41);
}

BOOST_FIXTURE_TEST_CASE( Player_removeLives_int, PlayerTester )
{
    p->removeLives(42);
    BOOST_CHECK_EQUAL( p->getLives(), 0);
}

BOOST_FIXTURE_TEST_CASE( Player_removeLife_below_zero, PlayerTester )
{
    p->removeLife(43);
    BOOST_CHECK_EQUAL( p->getLives(), 0);
}

BOOST_AUTO_TEST_SUITE_END() // Player_removeLife

BOOST_AUTO_TEST_SUITE( Player_addLives )

BOOST_FIXTURE_TEST_CASE( Player_addLives_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLives(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_addLives_default, PlayerTester )
{
    p->addLives();
    BOOST_CHECK_EQUAL( p->getLives(), 43);
}

BOOST_FIXTURE_TEST_CASE( Player_addLives_int, PlayerTester )
{
    p->addLives(42);
    BOOST_CHECK_EQUAL( p->getLives(), 84);
}

/*
  BOOST_FIXTURE_TEST_CASE( Player_addLife_overflow, PlayerTester )
  {
  }
*/
BOOST_AUTO_TEST_SUITE_END() // Player_addLife

BOOST_AUTO_TEST_SUITE( Player_setLives )

BOOST_FIXTURE_TEST_CASE( Player_setLives_init_fixture, PlayerTester )
{
    BOOST_REQUIRE_EQUAL( p->getLives(), 42);
}

BOOST_FIXTURE_TEST_CASE( Player_setLives_int, PlayerTester )
{
    p->setLives(1);
    BOOST_CHECK_EQUAL( p->getLives(), 1);
}

BOOST_AUTO_TEST_SUITE_END() //Player_setLife

/* TODO: same with score */

/* TODO: draw */
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <noise/RasterValues.h>

class TestRasterValues : public ::testing::Test
{
protected:
    TestRasterValues()
    {

    };
    ~TestRasterValues() {};
};

TEST_F(TestRasterValues, TestRasterValuesBuild)
{

}<commit_msg>Test RasterValues<commit_after>#include <gtest/gtest.h>

#include <noise/RasterValues.h>
#include <noise/module/WangscapeModules.h>

class TestRasterValues : public ::testing::Test
{
protected:
    noise::module::GradientX gradientXModule;
    noise::module::GradientY gradientYModule;
    noise::module::Const constModule;
    TestRasterValues()
    {
        constModule.SetConstValue(10.);
    };
    ~TestRasterValues() {};
};

TEST_F(TestRasterValues, TestRasterValuesConstructors)
{
    noise::RasterValues<double> rv1(10,20);
    EXPECT_EQ(10, rv1.sizeX());
    EXPECT_EQ(20, rv1.sizeY());

    noise::RasterValues<double> rv2(20, 10, {-1., -2., 3., 4.});
    EXPECT_EQ(20, rv2.sizeX());
    EXPECT_EQ(10, rv2.sizeY());
    EXPECT_EQ(-1., rv2.bounds().left);
    EXPECT_EQ(-2., rv2.bounds().top);
    EXPECT_EQ(3., rv2.bounds().width);
    EXPECT_EQ(4., rv2.bounds().height);

    noise::RasterValues<double> rv3(5, 5, {0, 0, 1, 1}, constModule);
    EXPECT_EQ(5, rv3.sizeX());
    EXPECT_EQ(5, rv3.sizeY());
    EXPECT_EQ(0., rv3.bounds().left);
    EXPECT_EQ(0., rv3.bounds().top);
    EXPECT_EQ(1., rv3.bounds().width);
    EXPECT_EQ(1., rv3.bounds().height);
    for (size_t x = 0; x < 5; x++)
    {
        for (size_t y = 0; y < 5; y++)
        {
            EXPECT_EQ(10., rv3.get(x, y));
        }
    }
}

TEST_F(TestRasterValues, TestRasterValuesOutOfRange)
{
    noise::RasterValues<double> rv(10, 10);

    EXPECT_ANY_THROW(rv.get(-1, -1););
    EXPECT_ANY_THROW(rv.get(0, -1););
    EXPECT_ANY_THROW(rv.get(9, -1););
    EXPECT_ANY_THROW(rv.get(10, -1););

    EXPECT_ANY_THROW(rv.get(-1, 0););
    EXPECT_ANY_THROW(rv.get(10, 0););

    EXPECT_ANY_THROW(rv.get(-1, 9););
    EXPECT_ANY_THROW(rv.get(10, 9););

    EXPECT_ANY_THROW(rv.get(-1, 10););
    EXPECT_ANY_THROW(rv.get(0, 10););
    EXPECT_ANY_THROW(rv.get(9, 10););
    EXPECT_ANY_THROW(rv.get(10, 10););
}

TEST_F(TestRasterValues, TestRasterValuesBuild)
{
    noise::RasterValues<double> rv(10, 10, {-1, -1, 2, 2});
    rv.build(gradientXModule);
    EXPECT_NEAR(-0.9, rv.get(0, 0), 0.0001);
    EXPECT_NEAR(-0.9, rv.get(0, 9), 0.0001);
    EXPECT_NEAR(0.9, rv.get(9, 0), 0.0001);
    EXPECT_NEAR(0.9, rv.get(9, 9), 0.0001);
    rv.build(gradientYModule);
    EXPECT_NEAR(-0.9, rv.get(0, 0), 0.0001);
    EXPECT_NEAR(-0.9, rv.get(9, 0), 0.0001);
    EXPECT_NEAR(0.9, rv.get(0, 9), 0.0001);
    EXPECT_NEAR(0.9, rv.get(9, 9), 0.0001);

}<|endoftext|>


<commit_before>///
/// @file  P2.cpp
/// @brief 2nd partial sieve function.
///        P2(x, y) counts the numbers <= x that have exactly 2 prime
///        factors each exceeding the a-th prime.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <BitSieve.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {
namespace P2 {

class ReversePrimeIterator
{
public:
  ReversePrimeIterator(int64_t stop, int64_t start) :
    iter_(stop, start),
    prime_(stop)
  { }
  int64_t previous_prime()
  {
    int64_t NO_PREV_PRIME = -1;
    if (prime_ <= 2)
      return NO_PREV_PRIME;
    prime_ = iter_.previous_prime();
    return prime_;
  }
private:
  primesieve::iterator iter_;
  int64_t prime_;
};

/// For each prime calculate its first multiple >= low
vector<int64_t> generate_next_multiples(int64_t low, int64_t size, vector<int32_t>& primes)
{
  vector<int64_t> next;

  next.reserve(size);
  next.push_back(0);

  for (int64_t b = 1; b < size; b++)
  {
    int64_t prime = primes[b];
    int64_t next_multiple = ceil_div(low, prime) * prime;
    next_multiple += prime * (~next_multiple & 1);
    next_multiple = max(prime * prime, next_multiple);
    next.push_back(next_multiple);
  }

  return next;
}

template <typename T>
T P2_thread(T x,
            int64_t y,
            int64_t segment_size,
            int64_t segments_per_thread,
            int64_t thread_num,
            int64_t low,
            int64_t limit,
            int64_t& pix,
            int64_t& pix_count,
            vector<int32_t>& primes)
{
  pix = 0;
  pix_count = 0;
  low += thread_num * segments_per_thread * segment_size;
  limit = min(low + segments_per_thread * segment_size, limit);
  int64_t size = pi_bsearch(primes, isqrt(limit)) + 1;
  int64_t start = (int64_t) max((int64_t) (x / limit + 1), y);
  int64_t stop  = (int64_t) min(x / low, isqrt(x));
  T P2_thread = 0;

  // P2_thread = \sum_{i=pi[start]}^{pi[stop]} pi(x / primes[i]) - pi(low - 1)
  // We use a reverse prime iterator to calculate P2_thread
  ReversePrimeIterator prime_iter(stop + 1, start);
  int64_t prime = prime_iter.previous_prime();
  int64_t xp = (int64_t) (x / prime);

  vector<int64_t> next = generate_next_multiples(low, size, primes);
  BitSieve sieve(segment_size);

  // segmented sieve of Eratosthenes
  for (; low < limit; low += segment_size)
  {
    // current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t sqrt = isqrt(high - 1);
    int64_t j = 0;

    sieve.fill(low, high);

    // cross-off multiples
    for (int64_t i = 2; i < size && primes[i] <= sqrt; i++)
    {
      int64_t k;
      int64_t p2 = primes[i] * 2;
      for (k = next[i]; k < high; k += p2)
        sieve.unset(k - low);
      next[i] = k;
    }

    while (prime >= start &&
           xp < high)
    {
      pix += sieve.count(j, xp - low);
      j = xp - low + 1;
      pix_count++;
      P2_thread += pix;
      prime = prime_iter.previous_prime();
      xp = (int64_t) (x / prime);
    }

    pix += sieve.count(j, (high - 1) - low);
  }

  return P2_thread;
}

void balanceLoad(int64_t* segments_per_thread, double seconds1, double time1)
{
  double time2 = get_wtime();
  double seconds = time2 - seconds1;
  double time = time2 - time1;
  double increase_threshold = in_between(0.5, time / 10, 20);

  if (seconds < increase_threshold)
    *segments_per_thread += *segments_per_thread * 3;
  else if (*segments_per_thread >= 4)
    *segments_per_thread -= *segments_per_thread / 4;
}

/// P2(x, y) counts the numbers <= x that have exactly 2 prime
/// factors each exceeding the a-th prime, a = pi(y).
/// Space complexity: O((x / y)^(1/2)).
///
template <typename T>
T P2(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, 1);
  T b = pi_legendre((int64_t) isqrt(x), 1);

  if (x < 4 || a >= b)
    return 0;

  if (print_status())
  {
    cout << endl;
    cout << "=== P2(x, y) ===" << endl;
    cout << "Computation of the 2nd partial sieve function" << endl;
  }

  double time = get_wtime();
  int64_t low = 2;
  int64_t limit = (int64_t)(x / max<int64_t>(1, y));
  int64_t segment_size = max<int64_t>(1 << 12, isqrt(limit));
  int64_t segments_per_thread = 1;
  threads = validate_threads(threads, limit);

  vector<int32_t> primes = generate_primes(isqrt(limit));
  aligned_vector<int64_t> pix(threads);
  aligned_vector<int64_t> pix_counts(threads);

  // \sum_{i=a+1}^{b} pi(x / primes[i]) - (i - 1)
  // initialize with \sum_{i=a+1}^{b} -i + 1
  T sum = (a - 2) * (a + 1) / 2 - (b - 2) * (b + 1) / 2;
  T pix_total = 0;

  while (low < limit)
  {
    int64_t segments = ceil_div(limit - low, segment_size);
    threads = in_between(1, threads, segments);
    segments_per_thread = in_between(1, segments_per_thread, ceil_div(segments, threads));
    double seconds = get_wtime();

    #pragma omp parallel for \
        num_threads(threads) reduction(+: sum)
    for (int i = 0; i < threads; i++)
      sum += P2_thread(x, y, segment_size, segments_per_thread, i,
         low, limit, pix[i], pix_counts[i], primes);

    low += segments_per_thread * threads * segment_size;
    balanceLoad(&segments_per_thread, seconds, time);

    // Add missing sum contributions in order
    for (int i = 0; i < threads; i++)
    {
      sum += pix_total * pix_counts[i];
      pix_total += pix[i];
    }

    if (print_status())
      cout << "\rStatus: " << get_percent(low, limit) << '%' << flush;
  }

  if (print_status())
    print_result("P2", sum, time);

  return sum;
}

} // namespace P2
} // namespace

namespace primecount {

int64_t P2(int64_t x, int64_t y, int threads)
{
  return P2::P2(x, y, threads);
}

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads)
{
  return P2::P2(x, y, threads);
}

#endif

/// P2_lehmer(x, a) counts the numbers <= x that have exactly 2 prime
/// factors each exceeding the a-th prime. This implementation is
/// optimized for small values of a < pi(x^(1/3)) which requires
/// sieving up to a large limit (x / primes[a]). Sieving is done in
/// parallel using primesieve (segmented sieve of Eratosthenes).
/// Space complexity: O(pi(sqrt(x))).
///
int64_t P2_lehmer(int64_t x, int64_t a, int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== P2_lehmer(x, a) ===" << endl;
    cout << "Computation of the 2nd partial sieve function" << endl;
  }

  double time = get_wtime();
  vector<int32_t> primes = generate_primes(isqrt(x));
  vector<int64_t> counts(primes.size());

  int64_t b = pi_bsearch(primes, isqrt(x));
  int64_t sum = 0;
  int64_t pix = 0;

  #pragma omp parallel for schedule(dynamic) \
      num_threads(validate_threads(threads, b, 1000))
  for (int64_t i = b; i > a; i--)
  {
    int64_t prev = (i == b) ? 0 : x / primes[i + 1] + 1;
    int64_t xi = x / primes[i];
    counts[i] = primesieve::count_primes(prev, xi);
  }

  for (int64_t i = b; i > a; i--)
  {
    pix += counts[i];
    sum += pix - (i - 1);
  }

  if (print_status())
    print_result("P2", sum, time);

  return sum;
}

} // namespace primecount
<commit_msg>Use unsigned x<commit_after>///
/// @file  P2.cpp
/// @brief 2nd partial sieve function.
///        P2(x, y) counts the numbers <= x that have exactly 2 prime
///        factors each exceeding the a-th prime.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <BitSieve.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {
namespace P2 {

class ReversePrimeIterator
{
public:
  ReversePrimeIterator(int64_t stop, int64_t start) :
    iter_(stop, start),
    prime_(stop)
  { }
  int64_t previous_prime()
  {
    int64_t NO_PREV_PRIME = -1;
    if (prime_ <= 2)
      return NO_PREV_PRIME;
    prime_ = iter_.previous_prime();
    return prime_;
  }
private:
  primesieve::iterator iter_;
  int64_t prime_;
};

/// For each prime calculate its first multiple >= low
vector<int64_t> generate_next_multiples(int64_t low, int64_t size, vector<int32_t>& primes)
{
  vector<int64_t> next;

  next.reserve(size);
  next.push_back(0);

  for (int64_t b = 1; b < size; b++)
  {
    int64_t prime = primes[b];
    int64_t next_multiple = ceil_div(low, prime) * prime;
    next_multiple += prime * (~next_multiple & 1);
    next_multiple = max(prime * prime, next_multiple);
    next.push_back(next_multiple);
  }

  return next;
}

template <typename T>
T P2_thread(T x,
            int64_t y,
            int64_t segment_size,
            int64_t segments_per_thread,
            int64_t thread_num,
            int64_t low,
            int64_t limit,
            int64_t& pix,
            int64_t& pix_count,
            vector<int32_t>& primes)
{
  pix = 0;
  pix_count = 0;
  low += thread_num * segments_per_thread * segment_size;
  limit = min(low + segments_per_thread * segment_size, limit);
  int64_t size = pi_bsearch(primes, isqrt(limit)) + 1;
  int64_t start = (int64_t) max((int64_t) (x / limit + 1), y);
  int64_t stop  = (int64_t) min(x / low, isqrt(x));
  T P2_thread = 0;

  // P2_thread = \sum_{i=pi[start]}^{pi[stop]} pi(x / primes[i]) - pi(low - 1)
  // We use a reverse prime iterator to calculate P2_thread
  ReversePrimeIterator prime_iter(stop + 1, start);
  int64_t prime = prime_iter.previous_prime();
  int64_t xp = (int64_t) (x / prime);

  vector<int64_t> next = generate_next_multiples(low, size, primes);
  BitSieve sieve(segment_size);

  // segmented sieve of Eratosthenes
  for (; low < limit; low += segment_size)
  {
    // current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t sqrt = isqrt(high - 1);
    int64_t j = 0;

    sieve.fill(low, high);

    // cross-off multiples
    for (int64_t i = 2; i < size && primes[i] <= sqrt; i++)
    {
      int64_t k;
      int64_t p2 = primes[i] * 2;
      for (k = next[i]; k < high; k += p2)
        sieve.unset(k - low);
      next[i] = k;
    }

    while (prime >= start &&
           xp < high)
    {
      pix += sieve.count(j, xp - low);
      j = xp - low + 1;
      pix_count++;
      P2_thread += pix;
      prime = prime_iter.previous_prime();
      xp = (int64_t) (x / prime);
    }

    pix += sieve.count(j, (high - 1) - low);
  }

  return P2_thread;
}

void balanceLoad(int64_t* segments_per_thread, double seconds1, double time1)
{
  double time2 = get_wtime();
  double seconds = time2 - seconds1;
  double time = time2 - time1;
  double increase_threshold = in_between(0.5, time / 10, 20);

  if (seconds < increase_threshold)
    *segments_per_thread += *segments_per_thread * 3;
  else if (*segments_per_thread >= 4)
    *segments_per_thread -= *segments_per_thread / 4;
}

/// P2(x, y) counts the numbers <= x that have exactly 2 prime
/// factors each exceeding the a-th prime, a = pi(y).
/// Space complexity: O((x / y)^(1/2)).
///
template <typename T>
T P2(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, 1);
  T b = pi_legendre((int64_t) isqrt(x), 1);

  if (x < 4 || a >= b)
    return 0;

  if (print_status())
  {
    cout << endl;
    cout << "=== P2(x, y) ===" << endl;
    cout << "Computation of the 2nd partial sieve function" << endl;
  }

  double time = get_wtime();
  int64_t low = 2;
  int64_t limit = (int64_t)(x / max<int64_t>(1, y));
  int64_t segment_size = max<int64_t>(1 << 12, isqrt(limit));
  int64_t segments_per_thread = 1;
  threads = validate_threads(threads, limit);

  vector<int32_t> primes = generate_primes(isqrt(limit));
  aligned_vector<int64_t> pix(threads);
  aligned_vector<int64_t> pix_counts(threads);

  // \sum_{i=a+1}^{b} pi(x / primes[i]) - (i - 1)
  // initialize with \sum_{i=a+1}^{b} -i + 1
  T sum = (a - 2) * (a + 1) / 2 - (b - 2) * (b + 1) / 2;
  T pix_total = 0;

  while (low < limit)
  {
    int64_t segments = ceil_div(limit - low, segment_size);
    threads = in_between(1, threads, segments);
    segments_per_thread = in_between(1, segments_per_thread, ceil_div(segments, threads));
    double seconds = get_wtime();

    #pragma omp parallel for \
        num_threads(threads) reduction(+: sum)
    for (int i = 0; i < threads; i++)
      sum += P2_thread(x, y, segment_size, segments_per_thread, i,
         low, limit, pix[i], pix_counts[i], primes);

    low += segments_per_thread * threads * segment_size;
    balanceLoad(&segments_per_thread, seconds, time);

    // Add missing sum contributions in order
    for (int i = 0; i < threads; i++)
    {
      sum += pix_total * pix_counts[i];
      pix_total += pix[i];
    }

    if (print_status())
      cout << "\rStatus: " << get_percent(low, limit) << '%' << flush;
  }

  if (print_status())
    print_result("P2", sum, time);

  return sum;
}

} // namespace P2
} // namespace

namespace primecount {

int64_t P2(int64_t x, int64_t y, int threads)
{
  assert(x >= 0);
  return P2::P2((uint64_t) x, y, threads);
}

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads)
{
  assert(x >= 0);
  return P2::P2((uint128_t) x, y, threads);
}

#endif

/// P2_lehmer(x, a) counts the numbers <= x that have exactly 2 prime
/// factors each exceeding the a-th prime. This implementation is
/// optimized for small values of a < pi(x^(1/3)) which requires
/// sieving up to a large limit (x / primes[a]). Sieving is done in
/// parallel using primesieve (segmented sieve of Eratosthenes).
/// Space complexity: O(pi(sqrt(x))).
///
int64_t P2_lehmer(int64_t x, int64_t a, int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== P2_lehmer(x, a) ===" << endl;
    cout << "Computation of the 2nd partial sieve function" << endl;
  }

  double time = get_wtime();
  vector<int32_t> primes = generate_primes(isqrt(x));
  vector<int64_t> counts(primes.size());

  int64_t b = pi_bsearch(primes, isqrt(x));
  int64_t sum = 0;
  int64_t pix = 0;

  #pragma omp parallel for schedule(dynamic) \
      num_threads(validate_threads(threads, b, 1000))
  for (int64_t i = b; i > a; i--)
  {
    int64_t prev = (i == b) ? 0 : x / primes[i + 1] + 1;
    int64_t xi = x / primes[i];
    counts[i] = primesieve::count_primes(prev, xi);
  }

  for (int64_t i = b; i > a; i--)
  {
    pix += counts[i];
    sum += pix - (i - 1);
  }

  if (print_status())
    print_result("P2", sum, time);

  return sum;
}

} // namespace primecount
<|endoftext|>