<commit_before>#include "../base/SRC_FIRST.hpp"
#include "renderer.hpp"
#include "data_traits.hpp"
#include "utils.hpp"
#include "framebuffer.hpp"
#include "renderbuffer.hpp"
#include "resource_manager.hpp"
#include "internal/opengl.hpp"
#include "../base/logging.hpp"

namespace yg
{
  namespace gl
  {
    const yg::Color Renderer::s_bgColor(192, 192, 192, 255);

    Renderer::Params::Params()
      : m_isDebugging(false),
        m_doUnbindRT(false),
        m_isSynchronized(true),
        m_renderQueue(0)
    {}

    Renderer::Renderer(Params const & params)
      : m_isDebugging(params.m_isDebugging),
        m_doUnbindRT(params.m_doUnbindRT),
        m_isSynchronized(params.m_isSynchronized),
        m_isRendering(false),
        m_width(0),
        m_height(0),
        m_env(0)
    {
      m_frameBuffer = params.m_frameBuffer;
      m_resourceManager = params.m_resourceManager;

      if (m_frameBuffer)
      {
        m_renderTarget = m_frameBuffer->renderTarget();
        m_depthBuffer = m_frameBuffer->depthBuffer();
      }

      m_renderQueue = params.m_renderQueue;
    }

    Renderer::~Renderer()
    {}

    shared_ptr<ResourceManager> const & Renderer::resourceManager() const
    {
      return m_resourceManager;
    }

    void Renderer::beginFrame()
    {
      CHECK(!m_isRendering, ("beginFrame called inside beginFrame/endFrame pair!"));
      m_isRendering = true;

      if (m_frameBuffer)
      {
        m_frameBuffer->setRenderTarget(m_renderTarget);
        m_frameBuffer->setDepthBuffer(m_depthBuffer);

        processCommand(make_shared_ptr(new ChangeFrameBuffer(m_frameBuffer)));
      }

//      checkStatus();
    }

    bool Renderer::isRendering() const
    {
      return m_isRendering;
    }

    Renderer::UnbindRenderTarget::UnbindRenderTarget(shared_ptr<RenderTarget> const & rt)
      : m_renderTarget(rt)
    {}

    void Renderer::UnbindRenderTarget::perform()
    {
      m_renderTarget->detachFromFrameBuffer();
    }

    void Renderer::unbindRenderTarget()
    {
      processCommand(make_shared_ptr(new UnbindRenderTarget(m_renderTarget)));
    }

    Renderer::DiscardFramebuffer::DiscardFramebuffer(bool doDiscardColor, bool doDiscardDepth)
        : m_doDiscardColor(doDiscardColor), m_doDiscardDepth(doDiscardDepth)
    {}

    void Renderer::DiscardFramebuffer::perform()
    {
      static bool firstReport = true;
      if (firstReport && !glDiscardFramebufferFn)
        LOG(LINFO, ("GL_EXT_discard_framebuffer is unsupported"));

      firstReport = false;

      GLenum attachements[2];
      int numAttachements = 0;
      if (m_doDiscardColor)
        attachements[numAttachements++] = GL_COLOR_ATTACHMENT0_MWM;
      if (m_doDiscardDepth)
        attachements[numAttachements++] = GL_DEPTH_ATTACHMENT_MWM;
      glDiscardFramebufferFn(GL_FRAMEBUFFER_MWM, numAttachements, attachements);
    }

    void Renderer::discardFramebuffer(bool doDiscardColor, bool doDiscardDepth)
    {
      if (glDiscardFramebufferFn)
        processCommand(make_shared_ptr(new DiscardFramebuffer(doDiscardColor, doDiscardDepth)));
    }

    void Renderer::endFrame()
    {
      CHECK(m_isRendering, ("endFrame called outside beginFrame/endFrame pair!"));

      if (m_doUnbindRT && m_renderTarget)
        unbindRenderTarget();

      if (m_isSynchronized)
        finish();

      m_isRendering = false;
    }

    shared_ptr<FrameBuffer> const & Renderer::frameBuffer() const
    {
      return m_frameBuffer;
    }

    shared_ptr<RenderTarget> const & Renderer::renderTarget() const
    {
      return m_renderTarget;
    }

    void Renderer::setRenderTarget(shared_ptr<RenderTarget> const & rt)
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_renderTarget = rt;
    }

    void Renderer::resetRenderTarget()
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_renderTarget.reset();
    }

    shared_ptr<RenderBuffer> const & Renderer::depthBuffer() const
    {
      return m_depthBuffer;
    }

    void Renderer::setDepthBuffer(shared_ptr<RenderBuffer> const & rt)
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_depthBuffer = rt;
    }

    void Renderer::resetDepthBuffer()
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_depthBuffer.reset();
    }

    Renderer::ClearCommand::ClearCommand(yg::Color const & color,
                                         bool clearRT,
                                         float depth,
                                         bool clearDepth)
      : m_color(color),
        m_clearRT(clearRT),
        m_depth(depth),
        m_clearDepth(clearDepth)
    {}

    void Renderer::ClearCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing clear command"));
      OGLCHECK(glClearColor(m_color.r / 255.0f,
                            m_color.g / 255.0f,
                            m_color.b / 255.0f,
                            m_color.a / 255.0f));
 #ifdef OMIM_GL_ES
      OGLCHECK(glClearDepthf(m_depth));
 #else
      OGLCHECK(glClearDepth(m_depth));
 #endif

      GLbitfield mask = 0;
      if (m_clearRT)
        mask |= GL_COLOR_BUFFER_BIT;
      if (m_clearDepth)
        mask |= GL_DEPTH_BUFFER_BIT;

      OGLCHECK(glDepthMask(GL_TRUE));

      OGLCHECK(glClear(mask));
    }

    void Renderer::clear(yg::Color const & c, bool clearRT, float depth, bool clearDepth)
    {
      shared_ptr<ClearCommand> command(new ClearCommand(c, clearRT, depth, clearDepth));
      processCommand(command);
    }

    void Renderer::FinishCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing FinishCommand command"));
      OGLCHECK(glFinish());
    }

    Renderer::ReadPixels::ReadPixels(m2::RectU const & r, void * data)
      : m_rect(r), m_data(data)
    {}

    void Renderer::ReadPixels::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing ReadPixels command"));

      OGLCHECK(glReadPixels(m_rect.minX(),
                            m_rect.minY(),
                            m_rect.SizeX(),
                            m_rect.SizeY(),
                            GL_RGBA,
                            GL_UNSIGNED_BYTE,
                            m_data
                            ));
    }

    void Renderer::readPixels(m2::RectU const & r, void * data, bool doForce)
    {
      processCommand(make_shared_ptr(new ReadPixels(r, data)), Packet::ECommand, doForce);
    }

    void Renderer::finish(bool doForce)
    {
      shared_ptr<Command> command(new FinishCommand());
      processCommand(make_shared_ptr(new FinishCommand()), Packet::ECommand, doForce);
    }

    Renderer::ChangeFrameBuffer::ChangeFrameBuffer(shared_ptr<FrameBuffer> const & fb)
      : m_frameBuffer(fb)
    {}

    void Renderer::ChangeFrameBuffer::perform()
    {
      if (isDebugging())
      {
        LOG(LINFO, ("performing ChangeFrameBuffer command"));
        LOG(LINFO, ("frameBufferID=", m_frameBuffer->id()));
      }

      m_frameBuffer->makeCurrent();
    }

    void Renderer::onSize(unsigned int width, unsigned int height)
    {
      if (width < 2) width = 2;
      if (height < 2) height = 2;

      m_width = width;
      m_height = height;

      if (m_frameBuffer)
        m_frameBuffer->onSize(width, height);
    }

    unsigned int Renderer::width() const
    {
      return m_width;
    }

    unsigned int Renderer::height() const
    {
      return m_height;
    }

    bool Renderer::isDebugging() const
    {
      return m_isDebugging;
    }

    void Renderer::processCommand(shared_ptr<Command> const & command, Packet::EType type, bool doForce)
    {
      if (command)
        command->m_isDebugging = renderQueue() && !doForce;

      if (renderQueue() && !doForce)
        renderQueue()->processPacket(Packet(command, type));
      else
        if (command)
          command->perform();
    }

    PacketsQueue * Renderer::renderQueue()
    {
      return m_renderQueue;
    }

    void Renderer::addFramePoint()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::EFramePoint));
    }

    void Renderer::addCheckPoint()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::ECheckPoint));
    }

    void Renderer::completeCommands()
    {
      if (m_renderQueue)
        m_renderQueue->completeCommands();
    }

    void Renderer::setEnvironment(core::CommandsQueue::Environment const * env)
    {
      m_env = env;
    }

    bool Renderer::isCancelled() const
    {
      if (m_env)
        return m_env->isCancelled();
      else
        return false;
    }

    void Renderer::setPixelPrecision(bool flag)
    {
      glUseSharpGeometryFn(flag);
    }
  }
}
<commit_msg>changes according to code review.<commit_after>#include "../base/SRC_FIRST.hpp"
#include "renderer.hpp"
#include "data_traits.hpp"
#include "utils.hpp"
#include "framebuffer.hpp"
#include "renderbuffer.hpp"
#include "resource_manager.hpp"
#include "internal/opengl.hpp"
#include "../base/logging.hpp"

namespace yg
{
  namespace gl
  {
    const yg::Color Renderer::s_bgColor(192, 192, 192, 255);

    Renderer::Params::Params()
      : m_isDebugging(false),
        m_doUnbindRT(false),
        m_isSynchronized(true),
        m_renderQueue(0)
    {}

    Renderer::Renderer(Params const & params)
      : m_isDebugging(params.m_isDebugging),
        m_doUnbindRT(params.m_doUnbindRT),
        m_isSynchronized(params.m_isSynchronized),
        m_isRendering(false),
        m_width(0),
        m_height(0),
        m_env(0)
    {
      m_frameBuffer = params.m_frameBuffer;
      m_resourceManager = params.m_resourceManager;

      if (m_frameBuffer)
      {
        m_renderTarget = m_frameBuffer->renderTarget();
        m_depthBuffer = m_frameBuffer->depthBuffer();
      }

      m_renderQueue = params.m_renderQueue;
    }

    Renderer::~Renderer()
    {}

    shared_ptr<ResourceManager> const & Renderer::resourceManager() const
    {
      return m_resourceManager;
    }

    void Renderer::beginFrame()
    {
      CHECK(!m_isRendering, ("beginFrame called inside beginFrame/endFrame pair!"));
      m_isRendering = true;

      if (m_frameBuffer)
      {
        m_frameBuffer->setRenderTarget(m_renderTarget);
        m_frameBuffer->setDepthBuffer(m_depthBuffer);

        processCommand(make_shared_ptr(new ChangeFrameBuffer(m_frameBuffer)));
      }

//      checkStatus();
    }

    bool Renderer::isRendering() const
    {
      return m_isRendering;
    }

    Renderer::UnbindRenderTarget::UnbindRenderTarget(shared_ptr<RenderTarget> const & rt)
      : m_renderTarget(rt)
    {}

    void Renderer::UnbindRenderTarget::perform()
    {
      m_renderTarget->detachFromFrameBuffer();
    }

    void Renderer::unbindRenderTarget()
    {
      processCommand(make_shared_ptr(new UnbindRenderTarget(m_renderTarget)));
    }

    Renderer::DiscardFramebuffer::DiscardFramebuffer(bool doDiscardColor, bool doDiscardDepth)
        : m_doDiscardColor(doDiscardColor), m_doDiscardDepth(doDiscardDepth)
    {}

    void Renderer::DiscardFramebuffer::perform()
    {
      GLenum attachements[2];
      int numAttachements = 0;
      if (m_doDiscardColor)
        attachements[numAttachements++] = GL_COLOR_ATTACHMENT0_MWM;
      if (m_doDiscardDepth)
        attachements[numAttachements++] = GL_DEPTH_ATTACHMENT_MWM;
      glDiscardFramebufferFn(GL_FRAMEBUFFER_MWM, numAttachements, attachements);
    }

    void Renderer::discardFramebuffer(bool doDiscardColor, bool doDiscardDepth)
    {
      static bool firstReport = true;
      if (firstReport && !glDiscardFramebufferFn)
        LOG(LINFO, ("GL_EXT_discard_framebuffer is unsupported"));

      firstReport = false;

      if (glDiscardFramebufferFn)
        processCommand(make_shared_ptr(new DiscardFramebuffer(doDiscardColor, doDiscardDepth)));
    }

    void Renderer::endFrame()
    {
      CHECK(m_isRendering, ("endFrame called outside beginFrame/endFrame pair!"));

      if (m_doUnbindRT && m_renderTarget)
        unbindRenderTarget();

      if (m_isSynchronized)
        finish();

      m_isRendering = false;
    }

    shared_ptr<FrameBuffer> const & Renderer::frameBuffer() const
    {
      return m_frameBuffer;
    }

    shared_ptr<RenderTarget> const & Renderer::renderTarget() const
    {
      return m_renderTarget;
    }

    void Renderer::setRenderTarget(shared_ptr<RenderTarget> const & rt)
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_renderTarget = rt;
    }

    void Renderer::resetRenderTarget()
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_renderTarget.reset();
    }

    shared_ptr<RenderBuffer> const & Renderer::depthBuffer() const
    {
      return m_depthBuffer;
    }

    void Renderer::setDepthBuffer(shared_ptr<RenderBuffer> const & rt)
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_depthBuffer = rt;
    }

    void Renderer::resetDepthBuffer()
    {
      CHECK(!isRendering(), ("should call this function only outside beginFrame/endFrame"));
      m_depthBuffer.reset();
    }

    Renderer::ClearCommand::ClearCommand(yg::Color const & color,
                                         bool clearRT,
                                         float depth,
                                         bool clearDepth)
      : m_color(color),
        m_clearRT(clearRT),
        m_depth(depth),
        m_clearDepth(clearDepth)
    {}

    void Renderer::ClearCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing clear command"));
      OGLCHECK(glClearColor(m_color.r / 255.0f,
                            m_color.g / 255.0f,
                            m_color.b / 255.0f,
                            m_color.a / 255.0f));
 #ifdef OMIM_GL_ES
      OGLCHECK(glClearDepthf(m_depth));
 #else
      OGLCHECK(glClearDepth(m_depth));
 #endif

      GLbitfield mask = 0;
      if (m_clearRT)
        mask |= GL_COLOR_BUFFER_BIT;
      if (m_clearDepth)
        mask |= GL_DEPTH_BUFFER_BIT;

      OGLCHECK(glDepthMask(GL_TRUE));

      OGLCHECK(glClear(mask));
    }

    void Renderer::clear(yg::Color const & c, bool clearRT, float depth, bool clearDepth)
    {
      shared_ptr<ClearCommand> command(new ClearCommand(c, clearRT, depth, clearDepth));
      processCommand(command);
    }

    void Renderer::FinishCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing FinishCommand command"));
      OGLCHECK(glFinish());
    }

    Renderer::ReadPixels::ReadPixels(m2::RectU const & r, void * data)
      : m_rect(r), m_data(data)
    {}

    void Renderer::ReadPixels::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing ReadPixels command"));

      OGLCHECK(glReadPixels(m_rect.minX(),
                            m_rect.minY(),
                            m_rect.SizeX(),
                            m_rect.SizeY(),
                            GL_RGBA,
                            GL_UNSIGNED_BYTE,
                            m_data
                            ));
    }

    void Renderer::readPixels(m2::RectU const & r, void * data, bool doForce)
    {
      processCommand(make_shared_ptr(new ReadPixels(r, data)), Packet::ECommand, doForce);
    }

    void Renderer::finish(bool doForce)
    {
      shared_ptr<Command> command(new FinishCommand());
      processCommand(make_shared_ptr(new FinishCommand()), Packet::ECommand, doForce);
    }

    Renderer::ChangeFrameBuffer::ChangeFrameBuffer(shared_ptr<FrameBuffer> const & fb)
      : m_frameBuffer(fb)
    {}

    void Renderer::ChangeFrameBuffer::perform()
    {
      if (isDebugging())
      {
        LOG(LINFO, ("performing ChangeFrameBuffer command"));
        LOG(LINFO, ("frameBufferID=", m_frameBuffer->id()));
      }

      m_frameBuffer->makeCurrent();
    }

    void Renderer::onSize(unsigned int width, unsigned int height)
    {
      if (width < 2) width = 2;
      if (height < 2) height = 2;

      m_width = width;
      m_height = height;

      if (m_frameBuffer)
        m_frameBuffer->onSize(width, height);
    }

    unsigned int Renderer::width() const
    {
      return m_width;
    }

    unsigned int Renderer::height() const
    {
      return m_height;
    }

    bool Renderer::isDebugging() const
    {
      return m_isDebugging;
    }

    void Renderer::processCommand(shared_ptr<Command> const & command, Packet::EType type, bool doForce)
    {
      if (command)
        command->m_isDebugging = renderQueue() && !doForce;

      if (renderQueue() && !doForce)
        renderQueue()->processPacket(Packet(command, type));
      else
        if (command)
          command->perform();
    }

    PacketsQueue * Renderer::renderQueue()
    {
      return m_renderQueue;
    }

    void Renderer::addFramePoint()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::EFramePoint));
    }

    void Renderer::addCheckPoint()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::ECheckPoint));
    }

    void Renderer::completeCommands()
    {
      if (m_renderQueue)
        m_renderQueue->completeCommands();
    }

    void Renderer::setEnvironment(core::CommandsQueue::Environment const * env)
    {
      m_env = env;
    }

    bool Renderer::isCancelled() const
    {
      if (m_env)
        return m_env->isCancelled();
      else
        return false;
    }

    void Renderer::setPixelPrecision(bool flag)
    {
      glUseSharpGeometryFn(flag);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "of_html.hh"
#include "coverage.hh"
#include "helper.hh"
#include "model.hh"

#include <map>
#include <sstream>

std::string OutputFormat_Html::header()
{
  std::string script(
    "\n");
  std::string ret(""+script+"");
  ret+="";
  ret+="
\n
UC	\nverdict	\n";
  for(unsigned i=0;i<covnames.size();i++) {
    ret=ret+""+covnames[i]+"	\n";
  }
  ret=ret+"
\n";
  return ret;
}

std::string OutputFormat_Html::footer() {
  return "
";
}

std::string OutputFormat_Html::format_covs()
{
  std::string ret("
\n");

  //testname
  ret=ret+""+testnames.back()+"	";

  //verdict
  ret=ret+""+test_verdict+"	\n";

  for(unsigned i=0;i<covnames.size();i++) {
    ret=ret+""+to_string(covs[i]->getCoverage())+
      "	\n";
  }
  return ret+"
\n";
}

/* We might want to have more than one comparator for
   different orders */

bool vcmp (const std::vector<std::pair<int,std::vector<int> > >& lhs,
           const std::vector<std::pair<int,std::vector<int> > >& rhs)
{
  if (lhs.size()==rhs.size()) {
    return lhs<rhs;
  }
  return lhs.size()<rhs.size();
}

std::string OutputFormat_Html::report()
{
  std::ostringstream html;

  html << "
"
       << "
Name	trace
\n";

  std::vector<std::string>& an(model->getActionNames());

  for(unsigned i=0;i<reportnames.size();i++) {

    bool(*cmprp)(const std::vector<std::pair<int,std::vector<int> > >&,
                 const std::vector<std::pair<int,std::vector<int> > >&) = vcmp;

    std::vector<std::vector<std::pair<int,std::vector<int> > > >& traces(rcovs[i]->traces);
    std::map<std::vector<std::pair<int,std::vector<int> > > , int, bool(*)(const std::vector<std::pair<int,std::vector<int> > >&,const std::vector<std::pair<int,std::vector<int> > >&) > cnt(cmprp);

    for(unsigned j=0;j<traces.size();j++) {
      cnt[traces[j]]++;
    }

    html << "
<a href=\"javascript:showHide('ID"
         << to_string(i)
         << "')\">

"
         << reportnames[i]
         << "

Number of executed tests:"
         << to_string((unsigned)traces.size())
         << "

unique tests:"
         << to_string(unsigned(cnt.size()))
         << "

	"
            "\n<div id=\"ID"
         << to_string(i)
         << "\">\n"
         << "
";

    for(std::map<std::vector<std::pair<int,std::vector<int> > >,int>::iterator j=cnt.begin();
        j!=cnt.end();j++) {

      html << "\n"
           << "
\n"
           << "
Count:"
           << to_string((unsigned)j->second)
           << "
"
           << "\n
\n";

      const std::vector<std::pair<int,std::vector<int> > >& t(j->first);
      for(unsigned k=0; k<t.size();k++) {
        html << "
"
             << an[t[k].first];
      }
      html << "
\n"
           << "

	";
    }

    /*
    for(unsigned j=0;j<traces.size();j++) {
      ret=ret+"";
      ret=ret+"\n
\n";
      std::vector<int>& t(traces[j]);
      for(unsigned k=0; k<t.size();k++) {
        ret=ret+"
"+an[t[k]];
      }
      ret=ret+"
\n";
      ret=ret+"	";
    }
    */
    html << "
\n"
         << "
\n
";

  }
  html << "
";
  return html.str();
}

FACTORY_DEFAULT_CREATOR(OutputFormat, OutputFormat_Html, "html")
<commit_msg>Print total time spent in the usecase<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "of_html.hh"
#include "coverage.hh"
#include "helper.hh"
#include "model.hh"

#include <map>
#include <sstream>

std::string OutputFormat_Html::header()
{
  std::string script(
    "\n");
  std::string ret(""+script+"");
  ret+="";
  ret+="
\n
UC	\nverdict	\n";
  for(unsigned i=0;i<covnames.size();i++) {
    ret=ret+""+covnames[i]+"	\n";
  }
  ret=ret+"
\n";
  return ret;
}

std::string OutputFormat_Html::footer() {
  return "
";
}

std::string OutputFormat_Html::format_covs()
{
  std::string ret("
\n");

  //testname
  ret=ret+""+testnames.back()+"	";

  //verdict
  ret=ret+""+test_verdict+"	\n";

  for(unsigned i=0;i<covnames.size();i++) {
    ret=ret+""+to_string(covs[i]->getCoverage())+
      "	\n";
  }
  return ret+"
\n";
}

/* We might want to have more than one comparator for
   different orders */

bool vcmp (const std::vector<std::pair<int,std::vector<int> > >& lhs,
           const std::vector<std::pair<int,std::vector<int> > >& rhs)
{
  if (lhs.size()==rhs.size()) {
    return lhs<rhs;
  }
  return lhs.size()<rhs.size();
}

std::string OutputFormat_Html::report()
{
  std::ostringstream html;

  html << "
"
       << "
Name	trace
\n";

  std::vector<std::string>& an(model->getActionNames());

  for(unsigned i=0;i<reportnames.size();i++) {

    bool(*cmprp)(const std::vector<std::pair<int,std::vector<int> > >&,
                 const std::vector<std::pair<int,std::vector<int> > >&) = vcmp;

    std::vector<std::vector<std::pair<int,std::vector<int> > > >& traces(rcovs[i]->traces);
    std::map<std::vector<std::pair<int,std::vector<int> > > , int, bool(*)(const std::vector<std::pair<int,std::vector<int> > >&,const std::vector<std::pair<int,std::vector<int> > >&) > cnt(cmprp);

    for(unsigned j=0;j<traces.size();j++) {
      cnt[traces[j]]++;
    }

    struct timeval time_tmp;
    struct timeval time_consumed={0,0};

    for(unsigned j=0;j<rcovs[i]->times.size();j++) {
      struct timeval t1=rcovs[i]->times[j].second;
      struct timeval t2=rcovs[i]->times[j].first;
      timersub(&t1,&t2,
	       &time_tmp);
      timeradd(&time_consumed,&time_tmp,&time_consumed);
    }

    html << "
<a href=\"javascript:showHide('ID"
         << to_string(i)
         << "')\">

"
         << reportnames[i]
         << "

Number of executed tests:"
         << to_string((unsigned)traces.size())
         << "

unique tests:"
         << to_string(unsigned(cnt.size()))

         << "

time used:"
	 << to_string(time_consumed)
         << "

	"
            "\n<div id=\"ID"
         << to_string(i)
         << "\">\n"
         << "
";

    for(std::map<std::vector<std::pair<int,std::vector<int> > >,int>::iterator j=cnt.begin();
        j!=cnt.end();j++) {

      html << "\n"
           << "
\n"
           << "
Count:"
           << to_string((unsigned)j->second)
           << "
"
           << "\n
\n";

      const std::vector<std::pair<int,std::vector<int> > >& t(j->first);
      for(unsigned k=0; k<t.size();k++) {
        html << "
"
             << an[t[k].first];
      }
      html << "
\n"
           << "

	";
    }

    /*
    for(unsigned j=0;j<traces.size();j++) {
      ret=ret+"";
      ret=ret+"\n
\n";
      std::vector<int>& t(traces[j]);
      for(unsigned k=0; k<t.size();k++) {
        ret=ret+"
"+an[t[k]];
      }
      ret=ret+"
\n";
      ret=ret+"	";
    }
    */
    html << "
\n"
         << "
\n
";

  }
  html << "
";
  return html.str();
}

FACTORY_DEFAULT_CREATOR(OutputFormat, OutputFormat_Html, "html")
<|endoftext|>


<commit_before>#include <Python.h>
#include <vector>
#include <string>
#include <libopenf4.h>

static PyObject *calcurate_groebner_basis(PyObject *self, PyObject *args) {
  PyObject *vname_obj, *polynomial_obj;
  unsigned long long int modulo;
  std::vector<std::string> variableName;
  std::vector<std::string> polynomialArray;
  std::vector<std::string> basis;
  PyObject *iter_vn, *iter_pol, *ret_pollist;

  if (!PyArg_ParseTuple(args, "KOO", &modulo, &vname_obj, &polynomial_obj)) return NULL;

  // Variable Name Iteration
  iter_vn = PyObject_GetIter(vname_obj);
  if (!iter_vn) return NULL;

  while (true) {
    PyObject *next = PyIter_Next(iter_vn);
    if (!next) {
      break;
    }

    if (!PyString_Check(next)) {
      return NULL;
    }
    std::string vname = std::string(PyString_AsString(next));
    variableName.push_back(vname);
  }

  // Polynomial Iteration
  iter_pol = PyObject_GetIter(polynomial_obj);
  if (!iter_pol) return NULL;

  while (true) {
    PyObject *next = PyIter_Next(iter_pol);
    if (!next) {
      break;
    }

    if (!PyString_Check(next)) {
      return NULL;
    }
    std::string polynomial = std::string(PyString_AsString(next));
    polynomialArray.push_back(polynomial);
  }

  basis = groebnerBasisF4(modulo, variableName.size(), variableName, polynomialArray, 1, 0);

  // Construct List
  ret_pollist = PyList_New(0);

  for (std::vector<std::string>::iterator it = basis.begin(); it != basis.end(); ++it) {
    std::string v = *it;
    PyObject *str = PyString_FromString(v.c_str());
    PyList_Append(ret_pollist, str);
    puts(v.c_str());
  }

  return ret_pollist;
}

static PyMethodDef Openf4Py_Methods [] = {
  {"calcurate_groebner_basis", calcurate_groebner_basis, METH_VARARGS, "Calcurate Groebner Basis\n\tcalcurate_groebner_basis(modulo, list_of_variable_names, list_of_polynomials)"},
  {NULL, NULL, 0, NULL}
};

extern "C" PyMODINIT_FUNC initopenf4(void)
{
    (void) Py_InitModule("openf4", Openf4Py_Methods);
}
<commit_msg>Remove Debug print<commit_after>#include <Python.h>
#include <vector>
#include <string>
#include <libopenf4.h>

static PyObject *calcurate_groebner_basis(PyObject *self, PyObject *args) {
  PyObject *vname_obj, *polynomial_obj;
  unsigned long long int modulo;
  std::vector<std::string> variableName;
  std::vector<std::string> polynomialArray;
  std::vector<std::string> basis;
  PyObject *iter_vn, *iter_pol, *ret_pollist;

  if (!PyArg_ParseTuple(args, "KOO", &modulo, &vname_obj, &polynomial_obj)) return NULL;

  // Variable Name Iteration
  iter_vn = PyObject_GetIter(vname_obj);
  if (!iter_vn) return NULL;

  while (true) {
    PyObject *next = PyIter_Next(iter_vn);
    if (!next) {
      break;
    }

    if (!PyString_Check(next)) {
      return NULL;
    }
    std::string vname = std::string(PyString_AsString(next));
    variableName.push_back(vname);
  }

  // Polynomial Iteration
  iter_pol = PyObject_GetIter(polynomial_obj);
  if (!iter_pol) return NULL;

  while (true) {
    PyObject *next = PyIter_Next(iter_pol);
    if (!next) {
      break;
    }

    if (!PyString_Check(next)) {
      return NULL;
    }
    std::string polynomial = std::string(PyString_AsString(next));
    polynomialArray.push_back(polynomial);
  }

  basis = groebnerBasisF4(modulo, variableName.size(), variableName, polynomialArray, 1, 0);

  // Construct List
  ret_pollist = PyList_New(0);

  for (std::vector<std::string>::iterator it = basis.begin(); it != basis.end(); ++it) {
    std::string v = *it;
    PyObject *str = PyString_FromString(v.c_str());
    PyList_Append(ret_pollist, str);
  }

  return ret_pollist;
}

static PyMethodDef Openf4Py_Methods [] = {
  {"calcurate_groebner_basis", calcurate_groebner_basis, METH_VARARGS, "Calcurate Groebner Basis\n\tcalcurate_groebner_basis(modulo, list_of_variable_names, list_of_polynomials)"},
  {NULL, NULL, 0, NULL}
};

extern "C" PyMODINIT_FUNC initopenf4(void)
{
    (void) Py_InitModule("openf4", Openf4Py_Methods);
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium 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 3
of the License, or (at your option) any later version.

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_RUNTIME
#define __BOHRIUM_BRIDGE_CPP_RUNTIME
#include <iostream>
#include <sstream>

namespace bh {

// Runtime : Definition
Runtime& Runtime::instance()
{
    static Runtime instance;
    return instance;
}

void stop()
{
}

Runtime::Runtime() : random_id(0), ext_in_queue(0), queue_size(0)
{
    bh_error err;
    char err_msg[100];

    bh_component **components;          // Bohrium component setup
    int64_t component_count;

    self = bh_component_setup(NULL);
    bh_component_children(self, &component_count, &components);

    if (component_count != 1 || components[0]->type != BH_VEM) {
        fprintf(stderr, "Error in the configuration: the bridge must "
                        "have exactly one child of type VEM\n");
        exit(-1);
    }
    child = components[0];
    free(components);

    err = child->init(child);           // Initialize child
    if (err) {
        fprintf(stderr, "Error in child->init()\n");
        exit(-1);
    }

    //
    // Register extensions
    //
    err = child->reg_func("bh_random", &random_id);
    if (err != BH_SUCCESS) {
        sprintf(err_msg, "Fatal error in the initialization of the user"
                        "-defined random operation: %s.\n",
                        bh_error_text(err));
        throw std::runtime_error(err_msg);
    }
    if (random_id <= 0) {
        sprintf(err_msg, "Fatal error in the initialization of the user"
                        "-defined random operation: invalid ID returned"
                        " (%ld).\n", (long)random_id);
        throw std::runtime_error(err_msg);
    }
}

Runtime::~Runtime()
{
    flush();

    child->shutdown();
    bh_component_free(self);
    bh_component_free(child);
}

size_t Runtime::get_queue_size()
{
    return queue_size;
}

/**
 * De-allocate all bh_base associated with BH_DISCARD instruction in the queue.
 *
 * @param count The max number of instructions to look at.
 * @return The number of bh_base that got de-allocated.
 */
inline
size_t Runtime::deallocate_meta(size_t count)
{
    size_t deallocated = 0;
    if (count > BH_CPP_QUEUE_MAX) {
        throw std::runtime_error("Trying to de-allocate more than physically possible.");
    }
    while(!garbage.empty()) {
        delete garbage.front();
        ++deallocated;
        garbage.pop_front();
    }
    return deallocated;
}

/**
 * De-allocate all meta-data associated with any USERFUNCs in the instruction queue.
 *
 * @return The number of USERFUNCs that got de-allocated.
 */
inline
size_t Runtime::deallocate_ext()
{
    size_t deallocated = 0;

    if (ext_in_queue>0) {
        for(size_t i=0; i<ext_in_queue; i++) {
            if (ext_queue[i]->id == random_id) {
                free((bh_random_type*)ext_queue[i]);
                deallocated++;
            } else {
                throw std::runtime_error("Cannot de-allocate extension...");
            }
        }
        ext_in_queue = 0;
    }
    return deallocated;
}

/**
 * Sends the instruction-list to the bohrium runtime.
 *
 * NOTE: Assumes that the list is non-empty.
 */
inline
size_t Runtime::execute()
{
    size_t cur_size = queue_size;

    bh_ir* bhir;
    bh_error status = bh_graph_create(&bhir, queue, queue_size);
    if (status == BH_SUCCESS) {
        status = child->execute(bhir);   // Send instructions to Bohrium
        queue_size = 0;                 // Reset size of the queue
    }

    bh_graph_destroy(bhir);
    bhir = NULL;

    if (status != BH_SUCCESS) {
        std::stringstream err_msg;
        err_msg << "Err: Runtime::execute() child->execute() failed: " << bh_error_text(status) << std::endl;

        throw std::runtime_error(err_msg.str());
    }

    deallocate_ext();
    deallocate_meta(cur_size);

    return cur_size;
}

/**
 * Flush the instruction-queue if it is about to get overflowed.
 *
 * This is used as a pre-condition to adding instructions to the queue.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::guard()
{
    if (queue_size >= BH_CPP_QUEUE_MAX) {
        return execute();
    }
    return 0;
}

/**
 * Flush the instruction-queue.
 *
 * This will force the runtime system to execute the queued up instructions,
 * at least if there are any queued instructions.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::flush()
{
    if (queue_size > 0) {
        return execute();
    }
    return 0;
}

/**
 * Create an unitialized intermediate operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp()
{
    multi_array<T>* operand = new multi_array<T>();
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an intermediate operand based on another operands meta-data.
 */
template <typename T, typename OtherT>
inline
multi_array<T>& Runtime::temp(multi_array<OtherT>& input)
{
    multi_array<T>* operand = new multi_array<T>(input);
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);
    operand->meta.base = base.meta.base;

    return *operand;
}

/**
 * Create an intermediate alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp_view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);
    operand->meta.base = base.meta.base;
    operand->setTemp(true);

    return *operand;
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1, multi_array<T>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1, const T& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op2);

    if (op1.getTemp()) { delete &op1; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, const T& op1, multi_array<T>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if (op1.getTemp()) { delete &op1; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, const T& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op1);
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
}

template <typename Ret, typename In>    // x = y
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // x = y < z
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1, multi_array<In>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename Ret, typename In>    // x = y < 1
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1, const In& op2)
{
    bh_instruction* instr;

    guard();
    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // reduce(), pow()
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<Ret>& op1, const In& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // x = 1 < y
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, const In& op1, multi_array<In>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if (op2.getTemp()) { delete &op2; }
}

template <typename T>           // Userfunc / extensions
inline
void Runtime::enqueue(bh_userfunc* rinstr)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode        = BH_USERFUNC;
    instr->userfunc      = (bh_userfunc *) rinstr;

    ext_queue[ext_in_queue++] = instr->userfunc;
}

template <typename T>
T scalar(multi_array<T>& op)
{
    Runtime::instance().enqueue((bh_opcode)BH_SYNC, op);
    Runtime::instance().flush();

    bh_base *op_a = op.getBase();
    T* data = (T*)(op_a->data);
    data += op.meta.start;

    T value = *data;

    if (op.getTemp()) { // If it was a temp you will never see it again
        delete &op;     // so you better clean it up!
        Runtime::instance().flush();
    }

    return value;
}

void Runtime::trash(bh_base *base_ptr)
{
    garbage.push_back(base_ptr);
}

}
#endif

<commit_msg>cppb/bhir: Modified bridge to use the new adj.mat. based bhir.<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium 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 3
of the License, or (at your option) any later version.

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_RUNTIME
#define __BOHRIUM_BRIDGE_CPP_RUNTIME
#include <iostream>
#include <sstream>

namespace bh {

// Runtime : Definition
Runtime& Runtime::instance()
{
    static Runtime instance;
    return instance;
}

void stop()
{
}

Runtime::Runtime() : random_id(0), ext_in_queue(0), queue_size(0)
{
    bh_error err;
    char err_msg[100];

    bh_component **components;          // Bohrium component setup
    int64_t component_count;

    self = bh_component_setup(NULL);
    bh_component_children(self, &component_count, &components);

    if (component_count != 1 || components[0]->type != BH_VEM) {
        fprintf(stderr, "Error in the configuration: the bridge must "
                        "have exactly one child of type VEM\n");
        exit(-1);
    }
    child = components[0];
    free(components);

    err = child->init(child);           // Initialize child
    if (err) {
        fprintf(stderr, "Error in child->init()\n");
        exit(-1);
    }

    //
    // Register extensions
    //
    err = child->reg_func("bh_random", &random_id);
    if (err != BH_SUCCESS) {
        sprintf(err_msg, "Fatal error in the initialization of the user"
                        "-defined random operation: %s.\n",
                        bh_error_text(err));
        throw std::runtime_error(err_msg);
    }
    if (random_id <= 0) {
        sprintf(err_msg, "Fatal error in the initialization of the user"
                        "-defined random operation: invalid ID returned"
                        " (%ld).\n", (long)random_id);
        throw std::runtime_error(err_msg);
    }
}

Runtime::~Runtime()
{
    flush();

    child->shutdown();
    bh_component_free(self);
    bh_component_free(child);
}

size_t Runtime::get_queue_size()
{
    return queue_size;
}

/**
 * De-allocate all bh_base associated with BH_DISCARD instruction in the queue.
 *
 * @param count The max number of instructions to look at.
 * @return The number of bh_base that got de-allocated.
 */
inline
size_t Runtime::deallocate_meta(size_t count)
{
    size_t deallocated = 0;
    if (count > BH_CPP_QUEUE_MAX) {
        throw std::runtime_error("Trying to de-allocate more than physically possible.");
    }
    while(!garbage.empty()) {
        delete garbage.front();
        ++deallocated;
        garbage.pop_front();
    }
    return deallocated;
}

/**
 * De-allocate all meta-data associated with any USERFUNCs in the instruction queue.
 *
 * @return The number of USERFUNCs that got de-allocated.
 */
inline
size_t Runtime::deallocate_ext()
{
    size_t deallocated = 0;

    if (ext_in_queue>0) {
        for(size_t i=0; i<ext_in_queue; i++) {
            if (ext_queue[i]->id == random_id) {
                free((bh_random_type*)ext_queue[i]);
                deallocated++;
            } else {
                throw std::runtime_error("Cannot de-allocate extension...");
            }
        }
        ext_in_queue = 0;
    }
    return deallocated;
}

/**
 * Sends the instruction-list to the bohrium runtime.
 *
 * NOTE: Assumes that the list is non-empty.
 */
inline
size_t Runtime::execute()
{
    size_t cur_size = queue_size;

    bh_ir bhir;
    bh_error status = bh_ir_create(&bhir, queue_size, queue);
    if (status == BH_SUCCESS) {
        status = child->execute(&bhir);   // Send instructions to Bohrium
        queue_size = 0;                 // Reset size of the queue
    }

    bh_ir_destroy(&bhir);

    if (status != BH_SUCCESS) {
        std::stringstream err_msg;
        err_msg << "Err: Runtime::execute() child->execute() failed: " << bh_error_text(status) << std::endl;

        throw std::runtime_error(err_msg.str());
    }

    deallocate_ext();
    deallocate_meta(cur_size);

    return cur_size;
}

/**
 * Flush the instruction-queue if it is about to get overflowed.
 *
 * This is used as a pre-condition to adding instructions to the queue.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::guard()
{
    if (queue_size >= BH_CPP_QUEUE_MAX) {
        return execute();
    }
    return 0;
}

/**
 * Flush the instruction-queue.
 *
 * This will force the runtime system to execute the queued up instructions,
 * at least if there are any queued instructions.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::flush()
{
    if (queue_size > 0) {
        return execute();
    }
    return 0;
}

/**
 * Create an unitialized intermediate operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp()
{
    multi_array<T>* operand = new multi_array<T>();
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an intermediate operand based on another operands meta-data.
 */
template <typename T, typename OtherT>
inline
multi_array<T>& Runtime::temp(multi_array<OtherT>& input)
{
    multi_array<T>* operand = new multi_array<T>(input);
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);
    operand->meta.base = base.meta.base;

    return *operand;
}

/**
 * Create an intermediate alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp_view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);
    operand->meta.base = base.meta.base;
    operand->setTemp(true);

    return *operand;
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1, multi_array<T>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1, const T& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op2);

    if (op1.getTemp()) { delete &op1; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, const T& op1, multi_array<T>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, multi_array<T>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if (op1.getTemp()) { delete &op1; }
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0, const T& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op1);
}

template <typename T>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<T>& op0)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
}

template <typename Ret, typename In>    // x = y
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // x = y < z
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1, multi_array<In>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename Ret, typename In>    // x = y < 1
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<In>& op1, const In& op2)
{
    bh_instruction* instr;

    guard();
    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // reduce(), pow()
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, multi_array<Ret>& op1, const In& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type( &instr->constant, op2 );

    if (op1.getTemp()) { delete &op1; }
}

template <typename Ret, typename In>    // x = 1 < y
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<Ret>& op0, const In& op1, multi_array<In>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if (op2.getTemp()) { delete &op2; }
}

template <typename T>           // Userfunc / extensions
inline
void Runtime::enqueue(bh_userfunc* rinstr)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode        = BH_USERFUNC;
    instr->userfunc      = (bh_userfunc *) rinstr;

    ext_queue[ext_in_queue++] = instr->userfunc;
}

template <typename T>
T scalar(multi_array<T>& op)
{
    Runtime::instance().enqueue((bh_opcode)BH_SYNC, op);
    Runtime::instance().flush();

    bh_base *op_a = op.getBase();
    T* data = (T*)(op_a->data);
    data += op.meta.start;

    T value = *data;

    if (op.getTemp()) { // If it was a temp you will never see it again
        delete &op;     // so you better clean it up!
        Runtime::instance().flush();
    }

    return value;
}

void Runtime::trash(bh_base *base_ptr)
{
    garbage.push_back(base_ptr);
}

}
#endif

<|endoftext|>


<commit_before>#include <packet.hpp>

using namespace MCPP::PacketImpl;

namespace MCPP {

	void BadFormat::Raise () {

		throw BadFormat();

	}

	void InsufficientBytes::Raise () {

		throw BadFormat();

	}

	void BadPacketID::Raise () {

		throw BadPacketID();

	}

	Packet::Packet (UInt32 id) noexcept : ID(id) {	}

	namespace PacketImpl {

		inline void PacketContainer::destroy_impl () noexcept {

			if (engaged) {

				engaged=false;

				if (destroy!=nullptr) destroy(storage);

			}

		}

		PacketContainer::PacketContainer () noexcept : destroy(nullptr), from_bytes(nullptr), engaged(false) {	}

		PacketContainer::~PacketContainer () noexcept {

			destroy_impl();

		}

		void PacketContainer::FromBytes (const Byte * & begin, const Byte * end) {

			if (from_bytes!=nullptr) {

				destroy_impl();

				from_bytes(begin,end,storage);

				engaged=true;

			}

		}

		Packet & PacketContainer::Get () noexcept {

			return packet;

		}

		const Packet & PacketContainer::Get () const noexcept {

			return packet;

		}

		void PacketContainer::Imbue (destroy_type destroy, from_bytes_type from_bytes) noexcept {

			destroy_impl();

			this->destroy=destroy;
			this->from_bytes=from_bytes;

		}

	}

	template <Word i, typename T>
	static typename std::enable_if<
		i>=T::Count
	>::type destroy_impl (const void *) noexcept {	}

	template <Word i, typename T>
	static typename std::enable_if<
		i<T::Count
	>::type destroy_impl (void * ptr) noexcept {

		typedef typename T::template Types<i> types;
		typedef typename types::Type type;

		reinterpret_cast<type *>(
			reinterpret_cast<void *>(
				reinterpret_cast<Byte *>(ptr)+types::Offset
			)
		)->~type();

		destroy_impl<i+1,T>(ptr);

	}

	template <typename T>
	static void destroy (void * ptr) noexcept {

		destroy_impl<0,T>(ptr);

	}

	template <Word i, typename T>
	static typename std::enable_if<
		i>=T::Count
	>::type deserialize_impl (const Byte * &, const Byte *, const void *) noexcept {	}

	template <Word i, typename T>
	static typename std::enable_if<
		i<T::Count
	>::type deserialize_impl (const Byte * & begin, const Byte * end, void * ptr) {

		typedef typename T::template Types<i> types;
		typedef typename types::Type type;

		type * p=reinterpret_cast<type *>(
			reinterpret_cast<void *>(
				reinterpret_cast<Byte *>(ptr)+types::Offset
			)
		);

		Serializer<type>::FromBytes(begin,end,p);

		try {

			deserialize_impl<i+1,T>(begin,end,ptr);

		} catch (...) {

			p->~type();

			throw;

		}

	}

	template <typename T>
	static void deserialize (const Byte * & begin, const Byte * end, void * ptr) {

		deserialize_impl<0,T>(begin,end,ptr);

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static bool check (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		typedef PacketMap<ps,pd,id> type;

		if ((ps==state) && (dir==pd) && (i==id)) {

			if (type::IsValid) {

				container.Imbue(
					destroy<type>,
					deserialize<type>
				);

				return true;

			}

			BadPacketID::Raise();

		}

		return false;

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static typename std::enable_if<
		(ps==LI) && (pd==BO) && (id==LargestID)
	>::type imbue_container (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		if (!check<ps,pd,id>(state,dir,i,container)) BadPacketID::Raise();

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static typename std::enable_if<
		!((ps==LI) && (pd==BO) && (id==LargestID))
	>::type imbue_container (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		if (!check<ps,pd,id>(state,dir,i,container)) imbue_container<
			((pd==BO) && (id==LargestID)) ? Next(ps) : ps,
			(id==LargestID) ? Next(pd) : pd,
			(id==LargestID) ? 0 : (id+1)
		>(state,dir,i,container);

	}

	PacketParser::PacketParser () noexcept : in_progress(false) {	}

	bool PacketParser::FromBytes (Vector<Byte> & buffer, ProtocolState state, ProtocolDirection direction) {

		//	Prepare iterators for deserialization
		const Byte * begin=buffer.begin();
		const Byte * end=buffer.end();

		if (in_progress) {

			//	In progress -- we're waiting for
			//	a certain number of bytes in the
			//	buffer (as specified by the length
			//	header)

			if (buffer.Count()>=waiting_for) {

				//	Sufficient bytes -- attempt to
				//	deserialize packet

				//	Get the ID
				UInt32 id=Deserialize<PacketImpl::VarInt<UInt32>>(begin,end);

				//	Prepare the parser/container
				imbue_container<HS,CB,0>(state,direction,id,container);

				//	Attempt to populate remainder
				//	of packet
				container.FromBytes(begin,end);

				//	Check to make sure we consumed
				//	as many bytes as the length
				//	header specified
				Word consumed=static_cast<Word>(begin-buffer.begin());

				if (consumed!=waiting_for) BadFormat::Raise();

				//	Put the ID in place
				container.Get().ID=id;

				//	We are finished with this packet
				in_progress=false;

				//	Delete consumed bytes from the
				//	buffer
				buffer.Delete(
					0,
					consumed
				);

			} else {

				//	Insufficient bytes

				return false;

			}

			return true;

		}

		//	Not in progress -- starting a new
		//	packet, get the length header
		//	and see where we can go from there

		try {

			//	Get the length header
			waiting_for=Deserialize<PacketImpl::VarInt<UInt32>>(begin,end);

		} catch (const InsufficientBytes &) {

			//	There's not enough bytes to
			//	get the length header

			return false;

		}

		//	We successfully acquired the
		//	length header, we are now
		//	parsing a packet
		in_progress=true;

		//	Delete consumed bytes from
		//	the buffer
		buffer.Delete(
			0,
			static_cast<Word>(begin-buffer.begin())
		);

		//	Recurse to see if we can parse the
		//	whole packet
		return FromBytes(buffer,state,direction);

	}

	Packet & PacketParser::Get () noexcept {

		return container.Get();

	}

	const Packet & PacketParser::Get () const noexcept {

		return container.Get();

	}

}
<commit_msg>PacketParser::FromBytes Clean Up<commit_after>#include <packet.hpp>

using namespace MCPP::PacketImpl;

namespace MCPP {

	void BadFormat::Raise () {

		throw BadFormat();

	}

	void InsufficientBytes::Raise () {

		throw BadFormat();

	}

	void BadPacketID::Raise () {

		throw BadPacketID();

	}

	Packet::Packet (UInt32 id) noexcept : ID(id) {	}

	namespace PacketImpl {

		inline void PacketContainer::destroy_impl () noexcept {

			if (engaged) {

				engaged=false;

				if (destroy!=nullptr) destroy(storage);

			}

		}

		PacketContainer::PacketContainer () noexcept : destroy(nullptr), from_bytes(nullptr), engaged(false) {	}

		PacketContainer::~PacketContainer () noexcept {

			destroy_impl();

		}

		void PacketContainer::FromBytes (const Byte * & begin, const Byte * end) {

			if (from_bytes!=nullptr) {

				destroy_impl();

				from_bytes(begin,end,storage);

				engaged=true;

			}

		}

		Packet & PacketContainer::Get () noexcept {

			return packet;

		}

		const Packet & PacketContainer::Get () const noexcept {

			return packet;

		}

		void PacketContainer::Imbue (destroy_type destroy, from_bytes_type from_bytes) noexcept {

			destroy_impl();

			this->destroy=destroy;
			this->from_bytes=from_bytes;

		}

	}

	template <Word i, typename T>
	static typename std::enable_if<
		i>=T::Count
	>::type destroy_impl (const void *) noexcept {	}

	template <Word i, typename T>
	static typename std::enable_if<
		i<T::Count
	>::type destroy_impl (void * ptr) noexcept {

		typedef typename T::template Types<i> types;
		typedef typename types::Type type;

		reinterpret_cast<type *>(
			reinterpret_cast<void *>(
				reinterpret_cast<Byte *>(ptr)+types::Offset
			)
		)->~type();

		destroy_impl<i+1,T>(ptr);

	}

	template <typename T>
	static void destroy (void * ptr) noexcept {

		destroy_impl<0,T>(ptr);

	}

	template <Word i, typename T>
	static typename std::enable_if<
		i>=T::Count
	>::type deserialize_impl (const Byte * &, const Byte *, const void *) noexcept {	}

	template <Word i, typename T>
	static typename std::enable_if<
		i<T::Count
	>::type deserialize_impl (const Byte * & begin, const Byte * end, void * ptr) {

		typedef typename T::template Types<i> types;
		typedef typename types::Type type;

		type * p=reinterpret_cast<type *>(
			reinterpret_cast<void *>(
				reinterpret_cast<Byte *>(ptr)+types::Offset
			)
		);

		Serializer<type>::FromBytes(begin,end,p);

		try {

			deserialize_impl<i+1,T>(begin,end,ptr);

		} catch (...) {

			p->~type();

			throw;

		}

	}

	template <typename T>
	static void deserialize (const Byte * & begin, const Byte * end, void * ptr) {

		deserialize_impl<0,T>(begin,end,ptr);

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static bool check (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		typedef PacketMap<ps,pd,id> type;

		if ((ps==state) && (dir==pd) && (i==id)) {

			if (type::IsValid) {

				container.Imbue(
					destroy<type>,
					deserialize<type>
				);

				return true;

			}

			BadPacketID::Raise();

		}

		return false;

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static typename std::enable_if<
		(ps==LI) && (pd==BO) && (id==LargestID)
	>::type imbue_container (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		if (!check<ps,pd,id>(state,dir,i,container)) BadPacketID::Raise();

	}

	template <ProtocolState ps, ProtocolDirection pd, UInt32 id>
	static typename std::enable_if<
		!((ps==LI) && (pd==BO) && (id==LargestID))
	>::type imbue_container (ProtocolState state, ProtocolDirection dir, UInt32 i, PacketContainer & container) {

		if (!check<ps,pd,id>(state,dir,i,container)) imbue_container<
			((pd==BO) && (id==LargestID)) ? Next(ps) : ps,
			(id==LargestID) ? Next(pd) : pd,
			(id==LargestID) ? 0 : (id+1)
		>(state,dir,i,container);

	}

	PacketParser::PacketParser () noexcept : in_progress(false) {	}

	bool PacketParser::FromBytes (Vector<Byte> & buffer, ProtocolState state, ProtocolDirection direction) {

		//	Prepare iterators for deserialization
		const Byte * begin=buffer.begin();

		if (in_progress) {

			//	In progress -- we're waiting for
			//	a certain number of bytes in the
			//	buffer (as specified by the length
			//	header)

			if (buffer.Count()>=waiting_for) {

				//	Sufficient bytes -- attempt to
				//	deserialize packet

				//	Set the end pointer to the number
				//	of bytes past the beginning specified
				//	in the length header
				auto end=begin+waiting_for;

				//	Get the ID
				UInt32 id=Deserialize<PacketImpl::VarInt<UInt32>>(begin,end);

				//	Prepare the parser/container
				imbue_container<HS,CB,0>(state,direction,id,container);

				//	Attempt to populate remainder
				//	of packet
				container.FromBytes(begin,end);

				//	Check to make sure we consumed
				//	as many bytes as the length
				//	header specified
				if (begin!=end) BadFormat::Raise();

				//	Put the ID in place
				container.Get().ID=id;

				//	We are finished with this packet
				in_progress=false;

				//	Delete consumed bytes from the
				//	buffer
				buffer.Delete(
					0,
					begin-buffer.begin()
				);

			} else {

				//	Insufficient bytes

				return false;

			}

			return true;

		}

		//	Not in progress -- starting a new
		//	packet, get the length header
		//	and see where we can go from there

		try {

			//	Get the length header
			waiting_for=Deserialize<PacketImpl::VarInt<UInt32>>(begin,buffer.end());

		} catch (const InsufficientBytes &) {

			//	There's not enough bytes to
			//	get the length header

			return false;

		}

		//	We successfully acquired the
		//	length header, we are now
		//	parsing a packet
		in_progress=true;

		//	Delete consumed bytes from
		//	the buffer
		buffer.Delete(
			0,
			begin-buffer.begin()
		);

		//	Recurse to see if we can parse the
		//	whole packet
		return FromBytes(buffer,state,direction);

	}

	Packet & PacketParser::Get () noexcept {

		return container.Get();

	}

	const Packet & PacketParser::Get () const noexcept {

		return container.Get();

	}

}
<|endoftext|>


<commit_before><commit_msg>Fix race condition at cros startup<commit_after><|endoftext|>


<commit_before>/*
    This file is part of KXForms.

    Copyright (c) 2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "formcreator.h"

#include "xmlbuilder.h"

#include <QDebug>

using namespace KXForms;

FormCreator::FormCreator()
{
}

QString FormCreator::create( const Schema::Document &schemaDocument )
{
  mDocument = schemaDocument;

  XmlBuilder xml( "kxforms" );

  createForm( &xml, schemaDocument.startElement() );

  foreach ( Schema::Element element, schemaDocument.usedElements() ) {
    if ( element.identifier() != schemaDocument.startElement().identifier() ) {
      createForm( &xml, element );
    }
  }

  return xml.print();
}

void FormCreator::createForm( XmlBuilder *xml, const Schema::Element &element )
{
  qDebug() << "ELEMENT" << element.name();
  XmlBuilder *form = xml->tag( "form" )->attribute( "ref", element.name() );

  foreach( Schema::Relation r, element.attributeRelations() ) {
    Schema::Attribute a = mDocument.attribute( r );
    if ( a.type() == Schema::Attribute::String ) {
      form->tag( "xf:input" )->attribute( "ref", "@" + a.name() )
        ->tag( "xf:label", humanizeString( r.target() ) );
    } else if ( a.type() == Schema::Attribute::Enumeration ) {
      XmlBuilder *select1 = form->tag( "xf:select1" );
      select1->attribute( "ref", "@" + a.name() );
      select1->tag( "xf:label", humanizeString( a.name() ) );
      foreach( QString value, a.enumerationValues() ) {
        XmlBuilder *item = select1->tag( "xf:item" );
        item->tag( "xf:label", humanizeString( value ) );
        item->tag( "xf:value", value );
      }
    } else {
      qDebug() << "Unsupported type: " << a.type();
    }
  }

  QString currentChoice;

  XmlBuilder *list = 0;

  foreach( Schema::Relation r, element.elementRelations() ) {
    qDebug() << "CHILD" << r.target();
    qDebug() << "  CHOICE: " << r.choice();
    if ( r.isList() ) {
      if ( !list || r.choice().isEmpty() || currentChoice != r.choice() ) {
        list = form->tag( "list" );
        QString label;
        if ( r.choice().contains( "+" ) ) {
          label = "Item";
        } else {
          label = humanizeString( r.target(), true );
        }
        list->tag( "xf:label", label );
      }
      list->tag( "itemclass" )->attribute( "ref", r.target() )
        ->tag( "itemlabel", r.target() );
      currentChoice = r.choice();
    } else {
      form->tag( "xf:input" )->attribute( "ref", r.target() )
        ->tag( "xf:label", humanizeString( r.target() ) );
    }
  }
}

QString FormCreator::humanizeString( const QString &str, bool pluralize )
{
  if ( str.isEmpty() ) return str;
  QString result = str[0].toUpper() + str.mid( 1 );
  if ( pluralize ) {
    if ( result.endsWith( "y" ) ) {
      result = result.left( str.length() - 1 ) + "ies";
    } else {
      result += "s";
    }
  }

  return result;
}
<commit_msg>Default to text area for element's texts.<commit_after>/*
    This file is part of KXForms.

    Copyright (c) 2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "formcreator.h"

#include "xmlbuilder.h"

#include <QDebug>

using namespace KXForms;

FormCreator::FormCreator()
{
}

QString FormCreator::create( const Schema::Document &schemaDocument )
{
  mDocument = schemaDocument;

  XmlBuilder xml( "kxforms" );

  createForm( &xml, schemaDocument.startElement() );

  foreach ( Schema::Element element, schemaDocument.usedElements() ) {
    if ( element.identifier() != schemaDocument.startElement().identifier() ) {
      createForm( &xml, element );
    }
  }

  return xml.print();
}

void FormCreator::createForm( XmlBuilder *xml, const Schema::Element &element )
{
  qDebug() << "ELEMENT" << element.name();
  XmlBuilder *form = xml->tag( "form" )->attribute( "ref", element.name() );

  foreach( Schema::Relation r, element.attributeRelations() ) {
    Schema::Attribute a = mDocument.attribute( r );
    if ( a.type() == Schema::Attribute::String ) {
      form->tag( "xf:input" )->attribute( "ref", "@" + a.name() )
        ->tag( "xf:label", humanizeString( r.target() ) );
    } else if ( a.type() == Schema::Attribute::Enumeration ) {
      XmlBuilder *select1 = form->tag( "xf:select1" );
      select1->attribute( "ref", "@" + a.name() );
      select1->tag( "xf:label", humanizeString( a.name() ) );
      foreach( QString value, a.enumerationValues() ) {
        XmlBuilder *item = select1->tag( "xf:item" );
        item->tag( "xf:label", humanizeString( value ) );
        item->tag( "xf:value", value );
      }
    } else {
      qDebug() << "Unsupported type: " << a.type();
    }
  }

  QString currentChoice;

  XmlBuilder *list = 0;

  foreach( Schema::Relation r, element.elementRelations() ) {
    qDebug() << "CHILD" << r.target();
    qDebug() << "  CHOICE: " << r.choice();
    if ( r.isList() ) {
      if ( !list || r.choice().isEmpty() || currentChoice != r.choice() ) {
        list = form->tag( "list" );
        QString label;
        if ( r.choice().contains( "+" ) ) {
          label = "Item";
        } else {
          label = humanizeString( r.target(), true );
        }
        list->tag( "xf:label", label );
      }
      list->tag( "itemclass" )->attribute( "ref", r.target() )
        ->tag( "itemlabel", r.target() );
      currentChoice = r.choice();
    } else {
      form->tag( "xf:textarea" )->attribute( "ref", r.target() )
        ->tag( "xf:label", humanizeString( r.target() ) );
    }
  }
}

QString FormCreator::humanizeString( const QString &str, bool pluralize )
{
  if ( str.isEmpty() ) return str;
  QString result = str[0].toUpper() + str.mid( 1 );
  if ( pluralize ) {
    if ( result.endsWith( "y" ) ) {
      result = result.left( str.length() - 1 ) + "ies";
    } else {
      result += "s";
    }
  }

  return result;
}
<|endoftext|>


<commit_before>#include <stflpp.h>
#include <logger.h>
#include <exception.h>
#include <cerrno>

#include <langinfo.h>
#include <utils.h>

namespace newsbeuter {

/*
 * This is a wrapper around the low-level C functions of STFL.
 * In order to make working with std::string easier, this wrapper
 * was created. This is also useful for logging all stfl-related
 * operations if necessary, and for working around bugs in STFL,
 * especially related to stuff like multithreading fuckups.
 */

stfl::form::form(const std::string& text) : f(0) {
	ipool = stfl_ipool_create(utils::translit(nl_langinfo(CODESET), "WCHAR_T").c_str());
	if (!ipool) {
		throw exception(errno);
	}
	f = stfl_create(stfl_ipool_towc(ipool, text.c_str()));
	if (!f) {
		throw exception(errno);
	}
}

stfl::form::~form() {
	if (f)
		stfl_free(f);
	if (ipool)
		stfl_ipool_destroy(ipool);
}

const char * stfl::form::run(int timeout) {
	return stfl_ipool_fromwc(ipool,stfl_run(f,timeout));
}

std::string stfl::form::get(const std::string& name) {
	const char * text = stfl_ipool_fromwc(ipool,stfl_get(f,stfl_ipool_towc(ipool,name.c_str())));
	std::string retval;
	if (text)
		retval = text;
	stfl_ipool_flush(ipool);
	return retval;
}

void stfl::form::set(const std::string& name, const std::string& value) {
	stfl_set(f, stfl_ipool_towc(ipool,name.c_str()), stfl_ipool_towc(ipool,value.c_str()));
	stfl_ipool_flush(ipool);
}

std::string stfl::form::get_focus() {
	const char * focus = stfl_ipool_fromwc(ipool,stfl_get_focus(f));
	std::string retval;
	if (focus)
		retval = focus;
	stfl_ipool_flush(ipool);
	return retval;
}

void stfl::form::set_focus(const std::string& name) {
	stfl_set_focus(f, stfl_ipool_towc(ipool,name.c_str()));
	LOG(LOG_DEBUG,"stfl::form::set_focus: %s", name);
}

void stfl::form::modify(const std::string& name, const std::string& mode, const std::string& text) {
	const wchar_t * wname, * wmode, * wtext;
	wname = stfl_ipool_towc(ipool,name.c_str());
	wmode = stfl_ipool_towc(ipool,mode.c_str());
	wtext = stfl_ipool_towc(ipool,text.c_str());
	stfl_modify(f, wname, wmode, wtext);
	stfl_ipool_flush(ipool);
}

void stfl::reset() {
	stfl_reset();
}

static std::mutex quote_mtx;

std::string stfl::quote(const std::string& text) {
	std::lock_guard<std::mutex> lock(quote_mtx);
	stfl_ipool * ipool = stfl_ipool_create(utils::translit(nl_langinfo(CODESET), "WCHAR_T").c_str());
	std::string retval = stfl_ipool_fromwc(ipool,stfl_quote(stfl_ipool_towc(ipool,text.c_str())));
	stfl_ipool_destroy(ipool);
	return retval;
}

std::string stfl::form::dump(const std::string& name, const std::string& prefix, int focus) {
	const char * text = stfl_ipool_fromwc(ipool,stfl_dump(f, stfl_ipool_towc(ipool,name.c_str()), stfl_ipool_towc(ipool,prefix.c_str()), focus));
	std::string retval;
	if (text)
		retval = text;
	stfl_ipool_flush(ipool);
	return retval;
}

/*

std::string stfl::form::lookup(const std::string& path, const std::string& newname) {
	const char * text = stfl_ipool_fromwc(ipool, stfl_lookup(f, stfl_ipool_towc(ipool,path.c_str()), stfl_ipool_towc(ipool,newname.c_str())));
	std::string retval;
	if (text)
		return retval = text;
	stfl_ipool_flush(ipool);
	return retval;
}

std::string stfl::error() {
	stfl_ipool * ipool = stfl_ipool_create(nl_langinfo(CODESET));
	std::string retval = stfl_ipool_fromwc(ipool,stfl_error());
	stfl_ipool_destroy(ipool);
	return retval;
}

void stfl::error_action(const std::string& mode) {
	stfl_ipool * ipool = stfl_ipool_create(nl_langinfo(CODESET));
	stfl_error_action(stfl_ipool_towc(ipool,mode.c_str()));
	stfl_ipool_destroy(ipool);
}
*/

}
<commit_msg>Remove dead code from stfl::form<commit_after>#include <stflpp.h>
#include <logger.h>
#include <exception.h>
#include <cerrno>

#include <langinfo.h>
#include <utils.h>

namespace newsbeuter {

/*
 * This is a wrapper around the low-level C functions of STFL.
 * In order to make working with std::string easier, this wrapper
 * was created. This is also useful for logging all stfl-related
 * operations if necessary, and for working around bugs in STFL,
 * especially related to stuff like multithreading fuckups.
 */

stfl::form::form(const std::string& text) : f(0) {
	ipool = stfl_ipool_create(utils::translit(nl_langinfo(CODESET), "WCHAR_T").c_str());
	if (!ipool) {
		throw exception(errno);
	}
	f = stfl_create(stfl_ipool_towc(ipool, text.c_str()));
	if (!f) {
		throw exception(errno);
	}
}

stfl::form::~form() {
	if (f)
		stfl_free(f);
	if (ipool)
		stfl_ipool_destroy(ipool);
}

const char * stfl::form::run(int timeout) {
	return stfl_ipool_fromwc(ipool,stfl_run(f,timeout));
}

std::string stfl::form::get(const std::string& name) {
	const char * text = stfl_ipool_fromwc(ipool,stfl_get(f,stfl_ipool_towc(ipool,name.c_str())));
	std::string retval;
	if (text)
		retval = text;
	stfl_ipool_flush(ipool);
	return retval;
}

void stfl::form::set(const std::string& name, const std::string& value) {
	stfl_set(f, stfl_ipool_towc(ipool,name.c_str()), stfl_ipool_towc(ipool,value.c_str()));
	stfl_ipool_flush(ipool);
}

std::string stfl::form::get_focus() {
	const char * focus = stfl_ipool_fromwc(ipool,stfl_get_focus(f));
	std::string retval;
	if (focus)
		retval = focus;
	stfl_ipool_flush(ipool);
	return retval;
}

void stfl::form::set_focus(const std::string& name) {
	stfl_set_focus(f, stfl_ipool_towc(ipool,name.c_str()));
	LOG(LOG_DEBUG,"stfl::form::set_focus: %s", name);
}

void stfl::form::modify(const std::string& name, const std::string& mode, const std::string& text) {
	const wchar_t * wname, * wmode, * wtext;
	wname = stfl_ipool_towc(ipool,name.c_str());
	wmode = stfl_ipool_towc(ipool,mode.c_str());
	wtext = stfl_ipool_towc(ipool,text.c_str());
	stfl_modify(f, wname, wmode, wtext);
	stfl_ipool_flush(ipool);
}

void stfl::reset() {
	stfl_reset();
}

static std::mutex quote_mtx;

std::string stfl::quote(const std::string& text) {
	std::lock_guard<std::mutex> lock(quote_mtx);
	stfl_ipool * ipool = stfl_ipool_create(utils::translit(nl_langinfo(CODESET), "WCHAR_T").c_str());
	std::string retval = stfl_ipool_fromwc(ipool,stfl_quote(stfl_ipool_towc(ipool,text.c_str())));
	stfl_ipool_destroy(ipool);
	return retval;
}

std::string stfl::form::dump(const std::string& name, const std::string& prefix, int focus) {
	const char * text = stfl_ipool_fromwc(ipool,stfl_dump(f, stfl_ipool_towc(ipool,name.c_str()), stfl_ipool_towc(ipool,prefix.c_str()), focus));
	std::string retval;
	if (text)
		retval = text;
	stfl_ipool_flush(ipool);
	return retval;
}

}
<|endoftext|>


<commit_before>#include "gdrawer.hpp"
#include <QTemporaryFile>
#include <QTextStream>
#include <QString>
#include <QRegularExpression>
#include <QProcess>
#include <QDir>
#include <QDebug>
#include <QThread>

#if defined(Q_OS_OSX)
#define FPC_PREFIX "_"
#define FPC "./fpc.sh"
#define GCC_PREFIX ""
#define GCC "./gcc.sh"
#define SO ".dylib"
#define CONVERTOR fromUtf8
#include <dlfcn.h>
#elif defined(Q_OS_LINUX)
#define FPC_PREFIX ""
#define FPC "./fpc.sh"
#define GCC_PREFIX ""
#define GCC "./gcc.sh"
#define SO ".so"
#define CONVERTOR fromUtf8
#include <dlfcn.h>
#elif defined(Q_OS_WIN)
#define FPC_PREFIX ""
#define FPC "fpc.bat"
#define SO ".dll"
#define CONVERTOR fromLocal8Bit
#include "dlfcn.h"
#else
#error "This OS is not yet supported"
#endif

Vm *createVm(const QString tmp1Name, const char *fn) {
	PascalVm *ret = new PascalVm;
	ret->lib = dlopen(tmp1Name.toUtf8().data(), RTLD_LAZY | RTLD_LOCAL);
	if (!ret->lib)
	{
		delete ret;
		throw Exception(QString("dlopen(): %1").arg(QString::CONVERTOR(dlerror())));
	}
	ret->fn = reinterpret_cast<char (*)(double, double)>(dlsym(ret->lib, fn));
	if (!ret->fn)
	{
		delete ret;
		throw Exception(QString("dlsym(): %1").arg(QString::CONVERTOR(dlerror())));
	}
	return ret;
}

Vm* getPascalVm(const QString& prog)
{
	QTemporaryFile tmp(QDir::tempPath() + "/solution.XXXXXX.pas");
	if (!tmp.open())
		throw Exception("Cannot create temp file");

	QString vars, body;
	{
		int var = prog.indexOf(QRegularExpression("(\\s|^)var(\\s|$)", QRegularExpression::CaseInsensitiveOption), 0);
		int begin = prog.indexOf(QRegularExpression("(\\s|^)begin(\\s|$|;)", QRegularExpression::CaseInsensitiveOption), var);
		int end = prog.indexOf(QRegularExpression("(\\s|^)end.(\\s|$)", QRegularExpression::CaseInsensitiveOption), begin);
		if (var == -1 || begin == -1 || end == -1)
		{
			throw Exception("Var, Begin or End were not found");
		}
		vars = prog.mid(var + 4, begin - (var + 4));
		body = prog.mid(begin + 6, end - (begin + 6));
	}

	QTextStream s(&tmp);
	s << "library solution;\n"
	  << "function __r(__x, __y: real):boolean;\n"
	  << "cdecl;\n"
	  << "var " << vars << "\n"
	  << "begin\n"
	  << "x := __x; y := __y;\n"
	  << body << ";\n"
	  << "__r := r;\n"
	  << "end;\n"
	  << "exports\n"
	  << "__r name '" << FPC_PREFIX << "pascal_run';\n"
	  << "end.\n";
	tmp.close();

	QProcess fpc;
	QString tmp1Name;
	{
		QTemporaryFile tmp1(QDir::tempPath() + "/solution.XXXXXX" SO);
		tmp1.open(); tmp1.close();
		tmp1Name = tmp1.fileName();
	}

	fpc.start(FPC, QStringList() << tmp.fileName() << tmp1Name);
	fpc.waitForFinished();
	if (fpc.exitCode())
	{
		throw Exception(QString("fpc: %1").arg(QString::CONVERTOR(fpc.readAllStandardError())));
	}

	return createVm(tmp1Name, "pascal_run");
}

Real PascalVm::execute(Ctx* _ctx) const
{
	PascalCtx *ctx = static_cast<PascalCtx*>(_ctx);
	return fn(ctx->x, ctx->y) ? Real(0, 0) : Real(1, 1);
}

PascalVm::~PascalVm()
{
	if (lib)
	{
		dlclose(lib);
	}
}

Vm* getCppVm(const QString& prog) {
	QTemporaryFile tmp(QDir::tempPath() + "/solution.XXXXXX.cpp");
	if (!tmp.open())
		throw Exception("Cannot create temp file");
	QTextStream s(&tmp);
	s << "#include <cmath>\n#include <cstdlib>\n"
	     "extern \"C\" { \n"
	     "  bool f(double, double);\n"
	     "  bool " GCC_PREFIX "cpp_run(double x, double y) {\n"
	     "    return f(x, y);\n"
	     "  }\n"
	     "#line 1\n"
      << prog
      << "\n#line 100000\n"
         "}\n";
    tmp.close();
    QProcess gcc;
    QString tmp1Name;
	{
		QTemporaryFile tmp1(QDir::tempPath() + "/solution.XXXXXX" SO);
		tmp1.open(); tmp1.close();
		tmp1Name = tmp1.fileName();
	}
	gcc.start(GCC, QStringList() << tmp.fileName() << tmp1Name);
    gcc.waitForFinished();
	if (gcc.exitCode())
	{
		throw Exception(QString("gcc: %1").arg(QString::CONVERTOR(gcc.readAllStandardError())));
	}

	return createVm(tmp1Name, "cpp_run");
}
<commit_msg>Allow includes in C++ programs<commit_after>#include "gdrawer.hpp"
#include <QTemporaryFile>
#include <QTextStream>
#include <QString>
#include <QRegularExpression>
#include <QProcess>
#include <QDir>
#include <QDebug>
#include <QThread>

#if defined(Q_OS_OSX)
#define FPC_PREFIX "_"
#define FPC "./fpc.sh"
#define GCC_PREFIX ""
#define GCC "./gcc.sh"
#define SO ".dylib"
#define CONVERTOR fromUtf8
#include <dlfcn.h>
#elif defined(Q_OS_LINUX)
#define FPC_PREFIX ""
#define FPC "./fpc.sh"
#define GCC_PREFIX ""
#define GCC "./gcc.sh"
#define SO ".so"
#define CONVERTOR fromUtf8
#include <dlfcn.h>
#elif defined(Q_OS_WIN)
#define FPC_PREFIX ""
#define FPC "fpc.bat"
#define SO ".dll"
#define CONVERTOR fromLocal8Bit
#include "dlfcn.h"
#else
#error "This OS is not yet supported"
#endif

Vm *createVm(const QString tmp1Name, const char *fn) {
	PascalVm *ret = new PascalVm;
	ret->lib = dlopen(tmp1Name.toUtf8().data(), RTLD_LAZY | RTLD_LOCAL);
	if (!ret->lib)
	{
		delete ret;
		throw Exception(QString("dlopen(): %1").arg(QString::CONVERTOR(dlerror())));
	}
	ret->fn = reinterpret_cast<char (*)(double, double)>(dlsym(ret->lib, fn));
	if (!ret->fn)
	{
		delete ret;
		throw Exception(QString("dlsym(): %1").arg(QString::CONVERTOR(dlerror())));
	}
	return ret;
}

Vm* getPascalVm(const QString& prog)
{
	QTemporaryFile tmp(QDir::tempPath() + "/solution.XXXXXX.pas");
	if (!tmp.open())
		throw Exception("Cannot create temp file");

	QString vars, body;
	{
		int var = prog.indexOf(QRegularExpression("(\\s|^)var(\\s|$)", QRegularExpression::CaseInsensitiveOption), 0);
		int begin = prog.indexOf(QRegularExpression("(\\s|^)begin(\\s|$|;)", QRegularExpression::CaseInsensitiveOption), var);
		int end = prog.indexOf(QRegularExpression("(\\s|^)end.(\\s|$)", QRegularExpression::CaseInsensitiveOption), begin);
		if (var == -1 || begin == -1 || end == -1)
		{
			throw Exception("Var, Begin or End were not found");
		}
		vars = prog.mid(var + 4, begin - (var + 4));
		body = prog.mid(begin + 6, end - (begin + 6));
	}

	QTextStream s(&tmp);
	s << "library solution;\n"
	  << "function __r(__x, __y: real):boolean;\n"
	  << "cdecl;\n"
	  << "var " << vars << "\n"
	  << "begin\n"
	  << "x := __x; y := __y;\n"
	  << body << ";\n"
	  << "__r := r;\n"
	  << "end;\n"
	  << "exports\n"
	  << "__r name '" << FPC_PREFIX << "pascal_run';\n"
	  << "end.\n";
	tmp.close();

	QProcess fpc;
	QString tmp1Name;
	{
		QTemporaryFile tmp1(QDir::tempPath() + "/solution.XXXXXX" SO);
		tmp1.open(); tmp1.close();
		tmp1Name = tmp1.fileName();
	}

	fpc.start(FPC, QStringList() << tmp.fileName() << tmp1Name);
	fpc.waitForFinished();
	if (fpc.exitCode())
	{
		throw Exception(QString("fpc: %1").arg(QString::CONVERTOR(fpc.readAllStandardError())));
	}

	return createVm(tmp1Name, "pascal_run");
}

Real PascalVm::execute(Ctx* _ctx) const
{
	PascalCtx *ctx = static_cast<PascalCtx*>(_ctx);
	return fn(ctx->x, ctx->y) ? Real(0, 0) : Real(1, 1);
}

PascalVm::~PascalVm()
{
	if (lib)
	{
		dlclose(lib);
	}
}

Vm* getCppVm(const QString& prog) {
	QTemporaryFile tmp(QDir::tempPath() + "/solution.XXXXXX.cpp");
	if (!tmp.open())
		throw Exception("Cannot create temp file");
	QTextStream s(&tmp);
	s << "#include <cmath>\n#include <cstdlib>\n"
	  << "#line 1\n"
	  << prog
	  << "\n#line 10000\n"
	     "extern \"C\" { \n"
	     "  bool " GCC_PREFIX "cpp_run(double x, double y) {\n"
	     "    return f(x, y);\n"
	     "  }\n"
         "}\n";
    tmp.close();
    QProcess gcc;
    QString tmp1Name;
	{
		QTemporaryFile tmp1(QDir::tempPath() + "/solution.XXXXXX" SO);
		tmp1.open(); tmp1.close();
		tmp1Name = tmp1.fileName();
	}
	gcc.start(GCC, QStringList() << tmp.fileName() << tmp1Name);
    gcc.waitForFinished();
	if (gcc.exitCode())
	{
		throw Exception(QString("gcc: %1").arg(QString::CONVERTOR(gcc.readAllStandardError())));
	}

	return createVm(tmp1Name, "cpp_run");
}
<|endoftext|>


<commit_before>/*
 * String hash map.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_STRMAP_HXX
#define BENG_PROXY_STRMAP_HXX

#include "util/ShallowCopy.hxx"

#include <inline/compiler.h>

#include <boost/intrusive/set.hpp>

#include <utility>

struct pool;

class StringMap {
    struct Item : boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
        const char *key, *value;

        Item(const char *_key, const char *_value)
            :key(_key), value(_value) {}

        Item(ShallowCopy, const Item &src)
            :key(src.key), value(src.value) {}

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

        class Compare {
            gcc_pure
            bool Less(const char *a, const char *b) const;

        public:
            gcc_pure
            bool operator()(const char *a, const Item &b) const {
                return Less(a, b.key);
            }

            gcc_pure
            bool operator()(const Item &a, const char *b) const {
                return Less(a.key, b);
            }

            gcc_pure
            bool operator()(const Item &a, const Item &b) const {
                return Less(a.key, b.key);
            }
        };

        class Cloner {
            struct pool &pool;

        public:
            explicit Cloner(struct pool &_pool):pool(_pool) {}

            Item *operator()(const Item &src) const;
        };

        class ShallowCloner {
            struct pool &pool;

        public:
            explicit ShallowCloner(struct pool &_pool):pool(_pool) {}

            Item *operator()(const Item &src) const;
        };
    };

    struct pool &pool;

    typedef boost::intrusive::multiset<Item,
                                       boost::intrusive::compare<Item::Compare>,
                                       boost::intrusive::constant_time_size<false>> Map;

    typedef Map::const_iterator const_iterator;

    Map map;

public:
    explicit StringMap(struct pool &_pool):pool(_pool) {}

    StringMap(struct pool &_pool, const StringMap &src);

    /**
     * Copy string pointers from #src.
     */
    StringMap(ShallowCopy, struct pool &_pool, const StringMap &src);

    StringMap(const StringMap &) = delete;

    StringMap(StringMap &&src) = default;

    StringMap &operator=(const StringMap &) = default;

    struct pool &GetPool() {
        return pool;
    }

    const_iterator begin() const {
        return map.begin();
    }

    const_iterator end() const {
        return map.end();
    }

    gcc_pure
    bool IsEmpty() const {
        return map.empty();
    }

    void Add(const char *key, const char *value);
    const char *Set(const char *key, const char *value);
    const char *Remove(const char *key);

    /**
     * Remove all values with the specified key.
     */
    void RemoveAll(const char *key);

    /**
     * Remove all existing values with the specified key and
     * (optionally, if not nullptr) add a new value.
     */
    void SecureSet(const char *key, const char *value);

    gcc_pure
    const char *Get(const char *key) const;

    gcc_pure
    bool Contains(const char *key) const {
        return Get(key) != nullptr;
    }

    gcc_pure
    std::pair<const_iterator, const_iterator> EqualRange(const char *key) const;
};

StringMap *gcc_malloc
strmap_new(struct pool *pool);

StringMap *gcc_malloc
strmap_dup(struct pool *pool, const StringMap *src);

/**
 * This variation of StringMap::Remove() allows the caller to pass
 * map=nullptr.
 */
static inline const char *
strmap_remove_checked(StringMap *map, const char *key)
{
    return map != nullptr
        ? map->Remove(key)
        : nullptr;
}

/**
 * This variation of StringMap::Get() allows the caller to pass
 * map=nullptr.
 */
gcc_pure
static inline const char *
strmap_get_checked(const StringMap *map, const char *key)
{
    return map != nullptr
        ? map->Get(key)
        : nullptr;
}

#endif
<commit_msg>strmap: add method Merge()<commit_after>/*
 * String hash map.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_STRMAP_HXX
#define BENG_PROXY_STRMAP_HXX

#include "util/ShallowCopy.hxx"

#include <inline/compiler.h>

#include <boost/intrusive/set.hpp>

#include <utility>

struct pool;

class StringMap {
    struct Item : boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
        const char *key, *value;

        Item(const char *_key, const char *_value)
            :key(_key), value(_value) {}

        Item(ShallowCopy, const Item &src)
            :key(src.key), value(src.value) {}

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

        class Compare {
            gcc_pure
            bool Less(const char *a, const char *b) const;

        public:
            gcc_pure
            bool operator()(const char *a, const Item &b) const {
                return Less(a, b.key);
            }

            gcc_pure
            bool operator()(const Item &a, const char *b) const {
                return Less(a.key, b);
            }

            gcc_pure
            bool operator()(const Item &a, const Item &b) const {
                return Less(a.key, b.key);
            }
        };

        class Cloner {
            struct pool &pool;

        public:
            explicit Cloner(struct pool &_pool):pool(_pool) {}

            Item *operator()(const Item &src) const;
        };

        class ShallowCloner {
            struct pool &pool;

        public:
            explicit ShallowCloner(struct pool &_pool):pool(_pool) {}

            Item *operator()(const Item &src) const;
        };
    };

    struct pool &pool;

    typedef boost::intrusive::multiset<Item,
                                       boost::intrusive::compare<Item::Compare>,
                                       boost::intrusive::constant_time_size<false>> Map;

    typedef Map::const_iterator const_iterator;

    Map map;

public:
    explicit StringMap(struct pool &_pool):pool(_pool) {}

    StringMap(struct pool &_pool, const StringMap &src);

    /**
     * Copy string pointers from #src.
     */
    StringMap(ShallowCopy, struct pool &_pool, const StringMap &src);

    StringMap(const StringMap &) = delete;

    StringMap(StringMap &&src) = default;

    StringMap &operator=(const StringMap &) = default;

    struct pool &GetPool() {
        return pool;
    }

    const_iterator begin() const {
        return map.begin();
    }

    const_iterator end() const {
        return map.end();
    }

    gcc_pure
    bool IsEmpty() const {
        return map.empty();
    }

    void Add(const char *key, const char *value);
    const char *Set(const char *key, const char *value);
    const char *Remove(const char *key);

    /**
     * Remove all values with the specified key.
     */
    void RemoveAll(const char *key);

    /**
     * Remove all existing values with the specified key and
     * (optionally, if not nullptr) add a new value.
     */
    void SecureSet(const char *key, const char *value);

    gcc_pure
    const char *Get(const char *key) const;

    gcc_pure
    bool Contains(const char *key) const {
        return Get(key) != nullptr;
    }

    gcc_pure
    std::pair<const_iterator, const_iterator> EqualRange(const char *key) const;

    /**
     * Move items from #src, merging it into this object.
     */
    void Merge(StringMap &&src) {
        src.map.clear_and_dispose([this](Item *item){
                map.insert(*item);
            });
    }
};

StringMap *gcc_malloc
strmap_new(struct pool *pool);

StringMap *gcc_malloc
strmap_dup(struct pool *pool, const StringMap *src);

/**
 * This variation of StringMap::Remove() allows the caller to pass
 * map=nullptr.
 */
static inline const char *
strmap_remove_checked(StringMap *map, const char *key)
{
    return map != nullptr
        ? map->Remove(key)
        : nullptr;
}

/**
 * This variation of StringMap::Get() allows the caller to pass
 * map=nullptr.
 */
gcc_pure
static inline const char *
strmap_get_checked(const StringMap *map, const char *key)
{
    return map != nullptr
        ? map->Get(key)
        : nullptr;
}

#endif
<|endoftext|>