<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief handler factory
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "HttpHandlerFactory.h"

#include "Basics/StringUtils.h"
#include "Basics/logging.h"
#include "Basics/tri-strings.h"
#include "HttpServer/HttpHandler.h"
#include "Rest/HttpRequest.h"
#include "Rest/SslInterface.h"

using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

namespace {
  sig_atomic_t MaintenanceMode = 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                MaintenanceHandler
// -----------------------------------------------------------------------------

namespace {
  class MaintenanceHandler : public HttpHandler {
    public:
      MaintenanceHandler (HttpRequest* request)
        : HttpHandler(request) {
      };

      bool isDirect () const override {
        return true;
      };

      status_t execute () override {
        _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE);

        return status_t(HANDLER_DONE);
      };

      void handleError (const Exception& error) {
        _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE);
      };
  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
                                        int32_t minCompatibility,
                                        bool allowMethodOverride,
                                        context_fptr setContext,
                                        void* setContextData)
  : _authenticationRealm(authenticationRealm),
    _minCompatibility(minCompatibility),
    _allowMethodOverride(allowMethodOverride),
    _setContext(setContext),
    _setContextData(setContextData),
    _notFound(0) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clones a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
  : _authenticationRealm(that._authenticationRealm),
    _minCompatibility(that._minCompatibility),
    _allowMethodOverride(that._allowMethodOverride),
    _setContext(that._setContext),
    _setContextData(that._setContextData),
    _constructors(that._constructors),
    _datas(that._datas),
    _prefixes(that._prefixes),
    _notFound(that._notFound) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief copies a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory& HttpHandlerFactory::operator= (HttpHandlerFactory const& that) {
  if (this != &that) {
    _authenticationRealm = that._authenticationRealm;
    _minCompatibility = that._minCompatibility;
    _allowMethodOverride = that._allowMethodOverride;
    _setContext = that._setContext;
    _setContextData = that._setContextData;
    _constructors = that._constructors;
    _datas = that._datas;
    _prefixes = that._prefixes;
    _notFound = that._notFound;
  }

  return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::~HttpHandlerFactory () {
}

// -----------------------------------------------------------------------------
// --SECTION--                                             static public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief sets maintenance mode
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::setMaintenance (bool value) {
  MaintenanceMode = value ? 1 : 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief returns header and body size restrictions
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::size_restriction_t HttpHandlerFactory::sizeRestrictions () const {
  size_restriction_t restrictions;

  restrictions.maximalHeaderSize = 1 * 1024 * 1024;  // 1 MByte
  restrictions.maximalBodySize = 512 * 1024 * 1024;  // 512 MByte
  restrictions.maximalPipelineSize = 2 * restrictions.maximalBodySize;

  return restrictions;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief authenticates a new request
///
/// wrapper method that will consider disabled authentication etc.
////////////////////////////////////////////////////////////////////////////////

HttpResponse::HttpResponseCode HttpHandlerFactory::authenticateRequest (HttpRequest* request) {
  auto context = request->getRequestContext();

  if (context == nullptr) {
    if (! setRequestContext(request)) {
      return HttpResponse::NOT_FOUND;
    }

    context = request->getRequestContext();
  }

  TRI_ASSERT(context != nullptr);

  return context->authenticate();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief set request context, wrapper method
////////////////////////////////////////////////////////////////////////////////

bool HttpHandlerFactory::setRequestContext (HttpRequest* request) {
  return _setContext(request, _setContextData);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the authentication realm
////////////////////////////////////////////////////////////////////////////////

string HttpHandlerFactory::authenticationRealm (HttpRequest* request) const {
  auto context = request->getRequestContext();

  if (context != nullptr) {
    auto realm = context->getRealm();

    if (realm != nullptr) {
      return _authenticationRealm + "/" + std::string(realm);
    }
  }
  return _authenticationRealm;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new request
////////////////////////////////////////////////////////////////////////////////

HttpRequest* HttpHandlerFactory::createRequest (ConnectionInfo const& info,
                                                char const* ptr,
                                                size_t length) {
  HttpRequest* request = new HttpRequest(info, ptr, length, _minCompatibility, _allowMethodOverride);

  if (request != nullptr) {
    setRequestContext(request);
  }

  return request;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new handler
////////////////////////////////////////////////////////////////////////////////

HttpHandler* HttpHandlerFactory::createHandler (HttpRequest* request) {
  if (MaintenanceMode) {
    return new MaintenanceHandler(request);
  }

  unordered_map<string, create_fptr> const& ii = _constructors;
  string path = request->requestPath();
  auto i = ii.find(path);
  void* data = nullptr;

  // no direct match, check prefix matches
  if (i == ii.end()) {
    LOG_TRACE("no direct handler found, trying prefixes");

    // find longest match
    string prefix;
    vector<string> const& jj = _prefixes;
    const size_t pathLength = path.size();

    for (vector<string>::const_iterator j = jj.begin();  j != jj.end();  ++j) {
      string const& p = *j;
      const size_t pSize = p.size();

      if (path.compare(0, pSize, p) == 0) {
        if (pSize < pathLength && path[pSize] == '/') {
          if (prefix.size() < pSize) {
            prefix = p;
          }
        }
      }
    }

    if (prefix.empty()) {
      LOG_TRACE("no prefix handler found, trying catch all");

      i = ii.find("/");
      if (i != ii.end()) {
        LOG_TRACE("found catch all handler '/'");

        size_t l = 1;
        size_t n = path.find_first_of('/', l);

        while (n != string::npos) {
          request->addSuffix(path.substr(l, n - l).c_str());
          l = n + 1;
          n = path.find_first_of('/', l);
        }

        if (l < path.size()) {
          request->addSuffix(path.substr(l).c_str());
        }

        path = "/";
        request->setPrefix(path.c_str());
      }
    }

    else {
      LOG_TRACE("found prefix match '%s'", prefix.c_str());

      size_t l = prefix.size() + 1;
      size_t n = path.find_first_of('/', l);

      while (n != string::npos) {
        request->addSuffix(path.substr(l, n - l).c_str());
        l = n + 1;
        n = path.find_first_of('/', l);
      }

      if (l < path.size()) {
        request->addSuffix(path.substr(l).c_str());
      }

      path = prefix;
      request->setPrefix(path.c_str());

      i = ii.find(path);
    }
  }

  // no match
  if (i == ii.end()) {
    if (_notFound != nullptr) {
      HttpHandler* notFoundHandler = _notFound(request, data);
      notFoundHandler->setServer(this);

      return notFoundHandler;
    }
    else {
      LOG_TRACE("no not-found handler, giving up");
      return nullptr;
    }
  }

  // look up data
  unordered_map<string, void*> const& jj = _datas;
  auto j = jj.find(path);

  if (j != jj.end()) {
    data = j->second;
  }

  LOG_TRACE("found handler for path '%s'", path.c_str());
  HttpHandler* handler = i->second(request, data);

  handler->setServer(this);

  return handler;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addHandler (string const& path, create_fptr func, void* data) {
  _constructors[path] = func;
  _datas[path] = data;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a prefix path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addPrefixHandler (string const& path, create_fptr func, void* data) {
  _constructors[path] = func;
  _datas[path] = data;
  _prefixes.push_back(path);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addNotFoundHandler (create_fptr func) {
  _notFound = func;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>slightly less string creation<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief handler factory
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "HttpHandlerFactory.h"

#include "Basics/StringUtils.h"
#include "Basics/logging.h"
#include "Basics/tri-strings.h"
#include "HttpServer/HttpHandler.h"
#include "Rest/HttpRequest.h"
#include "Rest/SslInterface.h"

using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

namespace {
  sig_atomic_t MaintenanceMode = 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                MaintenanceHandler
// -----------------------------------------------------------------------------

namespace {
  class MaintenanceHandler : public HttpHandler {
    public:
      MaintenanceHandler (HttpRequest* request)
        : HttpHandler(request) {
      };

      bool isDirect () const override {
        return true;
      };

      status_t execute () override {
        _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE);

        return status_t(HANDLER_DONE);
      };

      void handleError (const Exception& error) {
        _response = createResponse(HttpResponse::SERVICE_UNAVAILABLE);
      };
  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
                                        int32_t minCompatibility,
                                        bool allowMethodOverride,
                                        context_fptr setContext,
                                        void* setContextData)
  : _authenticationRealm(authenticationRealm),
    _minCompatibility(minCompatibility),
    _allowMethodOverride(allowMethodOverride),
    _setContext(setContext),
    _setContextData(setContextData),
    _notFound(nullptr) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clones a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
  : _authenticationRealm(that._authenticationRealm),
    _minCompatibility(that._minCompatibility),
    _allowMethodOverride(that._allowMethodOverride),
    _setContext(that._setContext),
    _setContextData(that._setContextData),
    _constructors(that._constructors),
    _datas(that._datas),
    _prefixes(that._prefixes),
    _notFound(that._notFound) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief copies a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory& HttpHandlerFactory::operator= (HttpHandlerFactory const& that) {
  if (this != &that) {
    _authenticationRealm = that._authenticationRealm;
    _minCompatibility = that._minCompatibility;
    _allowMethodOverride = that._allowMethodOverride;
    _setContext = that._setContext;
    _setContextData = that._setContextData;
    _constructors = that._constructors;
    _datas = that._datas;
    _prefixes = that._prefixes;
    _notFound = that._notFound;
  }

  return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a handler factory
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::~HttpHandlerFactory () {
}

// -----------------------------------------------------------------------------
// --SECTION--                                             static public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief sets maintenance mode
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::setMaintenance (bool value) {
  MaintenanceMode = value ? 1 : 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief returns header and body size restrictions
////////////////////////////////////////////////////////////////////////////////

HttpHandlerFactory::size_restriction_t HttpHandlerFactory::sizeRestrictions () const {
  size_restriction_t restrictions;

  restrictions.maximalHeaderSize = 1 * 1024 * 1024;  // 1 MByte
  restrictions.maximalBodySize = 512 * 1024 * 1024;  // 512 MByte
  restrictions.maximalPipelineSize = 2 * restrictions.maximalBodySize;

  return restrictions;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief authenticates a new request
///
/// wrapper method that will consider disabled authentication etc.
////////////////////////////////////////////////////////////////////////////////

HttpResponse::HttpResponseCode HttpHandlerFactory::authenticateRequest (HttpRequest* request) {
  auto context = request->getRequestContext();

  if (context == nullptr) {
    if (! setRequestContext(request)) {
      return HttpResponse::NOT_FOUND;
    }

    context = request->getRequestContext();
  }

  TRI_ASSERT(context != nullptr);

  return context->authenticate();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief set request context, wrapper method
////////////////////////////////////////////////////////////////////////////////

bool HttpHandlerFactory::setRequestContext (HttpRequest* request) {
  return _setContext(request, _setContextData);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the authentication realm
////////////////////////////////////////////////////////////////////////////////

string HttpHandlerFactory::authenticationRealm (HttpRequest* request) const {
  auto context = request->getRequestContext();

  if (context != nullptr) {
    auto realm = context->getRealm();

    if (realm != nullptr) {
      return _authenticationRealm + "/" + std::string(realm);
    }
  }
  return _authenticationRealm;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new request
////////////////////////////////////////////////////////////////////////////////

HttpRequest* HttpHandlerFactory::createRequest (ConnectionInfo const& info,
                                                char const* ptr,
                                                size_t length) {
  HttpRequest* request = new HttpRequest(info, ptr, length, _minCompatibility, _allowMethodOverride);

  if (request != nullptr) {
    setRequestContext(request);
  }

  return request;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new handler
////////////////////////////////////////////////////////////////////////////////

HttpHandler* HttpHandlerFactory::createHandler (HttpRequest* request) {
  if (MaintenanceMode) {
    return new MaintenanceHandler(request);
  }

  unordered_map<string, create_fptr> const& ii = _constructors;
  string path = request->requestPath();
  auto i = ii.find(path);
  void* data = nullptr;

  // no direct match, check prefix matches
  if (i == ii.end()) {
    LOG_TRACE("no direct handler found, trying prefixes");

    // find longest match
    string prefix;
    size_t const pathLength = path.size();

    for (auto const& p : _prefixes) {
      const size_t pSize = p.size();

      if (path.compare(0, pSize, p) == 0) {
        if (pSize < pathLength && path[pSize] == '/') {
          if (prefix.size() < pSize) {
            prefix = p;
          }
        }
      }
    }

    if (prefix.empty()) {
      LOG_TRACE("no prefix handler found, trying catch all");

      i = ii.find("/");
      if (i != ii.end()) {
        LOG_TRACE("found catch all handler '/'");

        size_t l = 1;
        size_t n = path.find_first_of('/', l);

        while (n != string::npos) {
          request->addSuffix(path.substr(l, n - l));
          l = n + 1;
          n = path.find_first_of('/', l);
        }

        if (l < path.size()) {
          request->addSuffix(path.substr(l));
        }

        path = "/";
        request->setPrefix(path.c_str());
      }
    }

    else {
      LOG_TRACE("found prefix match '%s'", prefix.c_str());

      size_t l = prefix.size() + 1;
      size_t n = path.find_first_of('/', l);

      while (n != string::npos) {
        request->addSuffix(path.substr(l, n - l));
        l = n + 1;
        n = path.find_first_of('/', l);
      }

      if (l < path.size()) {
        request->addSuffix(path.substr(l));
      }

      path = prefix;
      request->setPrefix(path.c_str());

      i = ii.find(path);
    }
  }

  // no match
  if (i == ii.end()) {
    if (_notFound != nullptr) {
      HttpHandler* notFoundHandler = _notFound(request, data);
      notFoundHandler->setServer(this);

      return notFoundHandler;
    }
    else {
      LOG_TRACE("no not-found handler, giving up");
      return nullptr;
    }
  }

  // look up data
  {
    auto const& it = _datas.find(path);

    if (it != _datas.end()) {
      data = (*it).second;
    }
  }

  LOG_TRACE("found handler for path '%s'", path.c_str());
  HttpHandler* handler = i->second(request, data);

  handler->setServer(this);

  return handler;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addHandler (string const& path, create_fptr func, void* data) {
  _constructors[path] = func;
  _datas[path] = data;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a prefix path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addPrefixHandler (string const& path, create_fptr func, void* data) {
  _constructors[path] = func;
  _datas[path] = data;
  _prefixes.emplace_back(path);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief adds a path and constructor to the factory
////////////////////////////////////////////////////////////////////////////////

void HttpHandlerFactory::addNotFoundHandler (create_fptr func) {
  _notFound = func;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/*
explosive-c4
Copyright (C) 2014-2022 Salvo "LtWorf" Tomaselli

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

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

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>
*/

#include <QMap>
#include <QPair>
#include <QPainter>
#include <QMouseEvent>
#include <QColor>
#include <QBrush>

#include "boardwidget.h"
#include "boardai.h"

// map cell type to pen and brush color
static QMap<cell_t, QPair<QColor, QColor> > cell_color;

BoardWidget::BoardWidget(boardwidget_t board_type) {
    QWidget();
    this->board_type = board_type;

    // initialize color table
    if (cell_color.empty()) {
        cell_color[CELL_RED]    = qMakePair(QColor("#ff4500"), Qt::red);
        cell_color[CELL_YELLOW] = qMakePair(Qt::yellow, QColor("#ffd700"));
        cell_color[CELL_EMPTY]  = qMakePair(Qt::white, Qt::white);
    }

    init();
}

void BoardWidget::init() {
    if (board!=NULL) {
        delete board;
    }
    switch (board_type) {
        case BOARD_WIDGET_LOCAL:
            board = new Board();
            break;
        case BOARD_WIDGET_AI:
            board = new BoardAI();
            break;
        case BOARD_WIDGET_NETWORK:
            //TODO something about this
            break;
    }
    connect(board,
            SIGNAL(changed(int,int)),
            this,
            SLOT(changed(int,int))
           );
    connect(board,
            SIGNAL(winner(player_t,int, int)),
            this,
            SLOT(winner(player_t, int, int))
           );
    QSize size = this->size();
    update(0,0,size.width(),size.height());
}

BoardWidget::~BoardWidget() {
    delete board;
}

void BoardWidget::winner(player_t winner, int row, int col) {
    winner_row = row;
    winner_col = col;
}

void BoardWidget::newgame() {
    winner_col = winner_row = -1;
    init();
}

void BoardWidget::paintEvent(QPaintEvent * p) {
    QWidget::paintEvent(p);
    QPainter painter(this);

    QSize size = this->size();

    painter.fillRect(0,0,size.width(),size.height(),QColor(0,0,0));

    int rows;
    int cols;
    board->get_size(&rows,&cols);

    int w_max = size.width() / cols;
    int h_max = size.height() / rows;
    diameter = w_max < h_max ? w_max : h_max;

    int hole_diam = diameter - 2;
    if (diameter > 8) {
        hole_diam = diameter*7/8;
    }
    int hole_offset = (diameter - hole_diam)/2;

    painter.setRenderHint(QPainter::Antialiasing, true);

    for (int r=0; r<rows;r++){
        for (int c=0; c<cols;c++) {
            cell_t cell = board->get_content(r,c);
            painter.setPen(QPen(cell_color[cell].first, hole_offset));
            painter.setBrush(QBrush(cell_color[cell].second, Qt::SolidPattern));

            if (c==winner_col and r==winner_row)
                painter.fillRect(diameter*c,diameter*r,diameter,diameter,QColor(255,255,255));

            painter.drawEllipse(diameter*c+hole_offset,diameter*r+hole_offset,hole_diam,hole_diam);
        }

    }

}

void BoardWidget::changed(int row, int col) {
    update(col*diameter,row*diameter,diameter,diameter);
}

void BoardWidget::mousePressEvent(QMouseEvent *ev) {
    QWidget::mousePressEvent(ev);
    int column = ev->x() / diameter;

    int rows;
    int cols;
    board->get_size(&rows,&cols);

    if (column >= cols)
        return;

    player_t t = board->get_turn();
    board->place(column,t);
}

QSize BoardWidget::minimumSizeHint() {
    int rows;
    int cols;
    board->get_size(&rows,&cols);

    return QSize(cols*30,rows*30);
}

QSize BoardWidget::sizeHint() {
    int rows;
    int cols;
    board->get_size(&rows,&cols);

    return QSize(cols*diameter,rows*diameter);
}
<commit_msg>3D-ish look for the board<commit_after>/*
explosive-c4
Copyright (C) 2014-2022 Salvo "LtWorf" Tomaselli

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

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

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>
*/

#include <QMap>
#include <QPair>
#include <QPainter>
#include <QMouseEvent>
#include <QColor>
#include <QBrush>

#include "boardwidget.h"
#include "boardai.h"

// map cell type to pen and brush color
static QMap<cell_t, QPair<QColor, QColor> > cell_color;

BoardWidget::BoardWidget(boardwidget_t board_type) {
    QWidget();
    this->board_type = board_type;

    // initialize color table
    if (cell_color.empty()) {
        cell_color[CELL_RED]    = qMakePair(QColor("#ff4500"), Qt::red);
        cell_color[CELL_YELLOW] = qMakePair(Qt::yellow, QColor("#ffd700"));
        cell_color[CELL_EMPTY]  = qMakePair(Qt::white, Qt::white);
    }

    init();
}

void BoardWidget::init() {
    if (board!=NULL) {
        delete board;
    }
    switch (board_type) {
        case BOARD_WIDGET_LOCAL:
            board = new Board();
            break;
        case BOARD_WIDGET_AI:
            board = new BoardAI();
            break;
        case BOARD_WIDGET_NETWORK:
            //TODO something about this
            break;
    }
    connect(board,
            SIGNAL(changed(int,int)),
            this,
            SLOT(changed(int,int))
           );
    connect(board,
            SIGNAL(winner(player_t,int, int)),
            this,
            SLOT(winner(player_t, int, int))
           );
    QSize size = this->size();
    update(0,0,size.width(),size.height());
}

BoardWidget::~BoardWidget() {
    delete board;
}

void BoardWidget::winner(player_t winner, int row, int col) {
    winner_row = row;
    winner_col = col;
}

void BoardWidget::newgame() {
    winner_col = winner_row = -1;
    init();
}

void BoardWidget::paintEvent(QPaintEvent * p) {
    QWidget::paintEvent(p);
    QPainter painter(this);

    QSize size = this->size();

    static const QColor board_color0 = QColor("#434343");
    static const QColor board_color1 = QColor("#333333");

    QLinearGradient board_gradient(0.73, 0.92, 0.4, 0.06);
    board_gradient.setCoordinateMode(QGradient::ObjectMode);
    board_gradient.setColorAt(0, board_color0);
    board_gradient.setColorAt(1, board_color1);

    QLinearGradient ring_gradient(board_gradient);
    ring_gradient.setColorAt(0, board_color1);
    ring_gradient.setColorAt(1, board_color0);

    painter.fillRect(0,0,size.width(),size.height(),board_gradient);

    int rows;
    int cols;
    board->get_size(&rows,&cols);

    int w_max = size.width() / cols;
    int h_max = size.height() / rows;
    diameter = w_max < h_max ? w_max : h_max;

    int hole_diam = diameter - 2;
    if (diameter > 8) {
        hole_diam = diameter*3/4;
    }
    int hole_offset = (diameter - hole_diam)/2;
    int ring_offset = hole_offset/2;
    int ring_diam = diameter - hole_offset;

    painter.setRenderHint(QPainter::Antialiasing, true);

    for (int r=0; r<rows;r++){
        for (int c=0; c<cols;c++) {
            if (c==winner_col and r==winner_row)
                painter.fillRect(diameter*c,diameter*r,diameter,diameter,QColor(255,255,255));

            cell_t cell = board->get_content(r,c);

            painter.setPen( QPen(ring_gradient, ring_offset) );
            painter.drawEllipse(diameter*c + ring_offset, diameter*r + ring_offset, ring_diam, ring_diam);

            painter.setPen(QPen(cell_color[cell].first, ring_offset));
            painter.setBrush(QBrush(cell_color[cell].second, Qt::SolidPattern));

            painter.drawEllipse(diameter*c+hole_offset,diameter*r+hole_offset,hole_diam,hole_diam);
        }

    }

}

void BoardWidget::changed(int row, int col) {
    update(col*diameter,row*diameter,diameter,diameter);
}

void BoardWidget::mousePressEvent(QMouseEvent *ev) {
    QWidget::mousePressEvent(ev);
    int column = ev->x() / diameter;

    int rows;
    int cols;
    board->get_size(&rows,&cols);

    if (column >= cols)
        return;

    player_t t = board->get_turn();
    board->place(column,t);
}

QSize BoardWidget::minimumSizeHint() {
    int rows;
    int cols;
    board->get_size(&rows,&cols);

    return QSize(cols*30,rows*30);
}

QSize BoardWidget::sizeHint() {
    int rows;
    int cols;
    board->get_size(&rows,&cols);

    return QSize(cols*diameter,rows*diameter);
}
<|endoftext|>


<commit_before>/*
 * MCSatSampleLiquidlyStrategy.cpp
 *
 *  Created on: Apr 23, 2012
 *      Author: selman.joe@gmail.com
 */

#include <vector>
#include "MCSatSampleLiquidlyStrategy.h"
#include "../logic/Domain.h"
#include "../logic/ELSyntax.h"
#include "LiquidSampler.h"
#include "../SpanInterval.h"

MCSatSampleLiquidlyStrategy::MCSatSampleLiquidlyStrategy() {
    // TODO Auto-generated constructor stub

}

MCSatSampleLiquidlyStrategy::~MCSatSampleLiquidlyStrategy() {
    // TODO Auto-generated destructor stub
}

void MCSatSampleLiquidlyStrategy::sampleSentences(const Model& m, const Domain& d, std::vector<ELSentence>& sampled) {
    // sample on an interval basis for each formula, enforcing liquid constraints
    for (Domain::formula_const_iterator it = d.formulas_begin(); it != d.formulas_end(); it++) {
        ELSentence curSentence = *it;

        if (curSentence.hasInfWeight()) {
            sampled.push_back(curSentence); // have to take it
            continue;
        }
        SISet satisfied = curSentence.dSatisfied(m, d);
        std::cout << "satisfied = " << satisfied << std::endl;

        double prob = 1.0 - exp(-(double)(curSentence.weight()));   // probability to sample an interval
        SISet where(true, d.maxInterval());

        // assume its liquid for now!!
        LiquidSampler sampler;
        for (SISet::const_iterator siIt = satisfied.begin(); siIt != satisfied.end(); siIt++) {
            std::vector<SpanInterval> samples = sampler(*siIt, prob);
            for (std::vector<SpanInterval>::const_iterator sampleIt = samples.begin();
                    sampleIt != samples.end();
                    sampleIt++) {
                where.add(*sampleIt);
            }
        }
        if (!where.empty()) {
            curSentence.setQuantification(where);
            sampled.push_back(curSentence);
        }
    }

}

MCSatSampleStrategy* MCSatSampleLiquidlyStrategy::clone() const {
    return new MCSatSampleLiquidlyStrategy();
}

<commit_msg>removed debug printing code<commit_after>/*
 * MCSatSampleLiquidlyStrategy.cpp
 *
 *  Created on: Apr 23, 2012
 *      Author: selman.joe@gmail.com
 */

#include <vector>
#include "MCSatSampleLiquidlyStrategy.h"
#include "../logic/Domain.h"
#include "../logic/ELSyntax.h"
#include "LiquidSampler.h"
#include "../SpanInterval.h"

MCSatSampleLiquidlyStrategy::MCSatSampleLiquidlyStrategy() {
    // TODO Auto-generated constructor stub

}

MCSatSampleLiquidlyStrategy::~MCSatSampleLiquidlyStrategy() {
    // TODO Auto-generated destructor stub
}

void MCSatSampleLiquidlyStrategy::sampleSentences(const Model& m, const Domain& d, std::vector<ELSentence>& sampled) {
    // sample on an interval basis for each formula, enforcing liquid constraints
    for (Domain::formula_const_iterator it = d.formulas_begin(); it != d.formulas_end(); it++) {
        ELSentence curSentence = *it;

        if (curSentence.hasInfWeight()) {
            sampled.push_back(curSentence); // have to take it
            continue;
        }
        SISet satisfied = curSentence.dSatisfied(m, d);

        double prob = 1.0 - exp(-(double)(curSentence.weight()));   // probability to sample an interval
        SISet where(true, d.maxInterval());

        // assume its liquid for now!!
        LiquidSampler sampler;
        for (SISet::const_iterator siIt = satisfied.begin(); siIt != satisfied.end(); siIt++) {
            std::vector<SpanInterval> samples = sampler(*siIt, prob);
            for (std::vector<SpanInterval>::const_iterator sampleIt = samples.begin();
                    sampleIt != samples.end();
                    sampleIt++) {
                where.add(*sampleIt);
            }
        }
        if (!where.empty()) {
            curSentence.setQuantification(where);
            sampled.push_back(curSentence);
        }
    }

}

MCSatSampleStrategy* MCSatSampleLiquidlyStrategy::clone() const {
    return new MCSatSampleLiquidlyStrategy();
}

<|endoftext|>


<commit_before>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "fs/Listener.hxx"
#include "net/StaticSocketAddress.hxx"

struct BpInstance;
struct SslConfig;

/**
 * Listener for incoming HTTP connections.
 */
class BPListener final : FilteredSocketListenerHandler {
	BpInstance &instance;

	const char *const tag;

	const bool auth_alt_host;

	FilteredSocketListener listener;

public:
	BPListener(BpInstance &_instance, const char *_tag,
		   bool _auth_alt_host,
		   const SslConfig *ssl_config);
	~BPListener() noexcept;

	void Listen(UniqueSocketDescriptor &&_fd) noexcept {
		listener.Listen(std::move(_fd));
	}

	void ListenTCP(unsigned port) {
		listener.ListenTCP(port);
	}

	auto GetLocalAddress() const noexcept {
		return listener.GetLocalAddress();
	}

	bool SetTcpDeferAccept(const int &seconds) noexcept {
		return listener.SetTcpDeferAccept(seconds);
	}

	void AddEvent() noexcept {
		listener.AddEvent();
	}

	void RemoveEvent() noexcept {
		listener.RemoveEvent();
	}

private:
	/* virtual methods from class FilteredSocketListenerHandler */
	void OnFilteredSocketConnect(PoolPtr pool,
				     UniquePoolPtr<FilteredSocket> socket,
				     SocketAddress address,
				     const SslFilter *ssl_filter) noexcept override;
	void OnFilteredSocketError(std::exception_ptr e) noexcept override;

};
<commit_msg>bp/Listener: remove unused methods ListenTCP(), SetTcpDeferAccept()<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "fs/Listener.hxx"
#include "net/StaticSocketAddress.hxx"

struct BpInstance;
struct SslConfig;

/**
 * Listener for incoming HTTP connections.
 */
class BPListener final : FilteredSocketListenerHandler {
	BpInstance &instance;

	const char *const tag;

	const bool auth_alt_host;

	FilteredSocketListener listener;

public:
	BPListener(BpInstance &_instance, const char *_tag,
		   bool _auth_alt_host,
		   const SslConfig *ssl_config);
	~BPListener() noexcept;

	void Listen(UniqueSocketDescriptor &&_fd) noexcept {
		listener.Listen(std::move(_fd));
	}

	auto GetLocalAddress() const noexcept {
		return listener.GetLocalAddress();
	}

	void AddEvent() noexcept {
		listener.AddEvent();
	}

	void RemoveEvent() noexcept {
		listener.RemoveEvent();
	}

private:
	/* virtual methods from class FilteredSocketListenerHandler */
	void OnFilteredSocketConnect(PoolPtr pool,
				     UniquePoolPtr<FilteredSocket> socket,
				     SocketAddress address,
				     const SslFilter *ssl_filter) noexcept override;
	void OnFilteredSocketError(std::exception_ptr e) noexcept override;

};
<|endoftext|>


<commit_before>/* Copyright 2017 Istio Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/istio/mixerclient/attribute_compressor.h"
#include "google/protobuf/arena.h"
#include "include/istio/utils/protobuf.h"
#include "src/istio/mixerclient/global_dictionary.h"

using ::istio::mixer::v1::Attributes;
using ::istio::mixer::v1::Attributes_AttributeValue;
using ::istio::mixer::v1::Attributes_StringMap;
using ::istio::mixer::v1::CompressedAttributes;

namespace istio {
namespace mixerclient {
namespace {

// The size of first version of global dictionary.
// If any dictionary error, global dictionary will fall back to this version.
const int kGlobalDictionaryBaseSize = 111;

// Return per message dictionary index.
int MessageDictIndex(int idx) { return -(idx + 1); }

// Per message dictionary.
class MessageDictionary {
 public:
  MessageDictionary(const GlobalDictionary& global_dict)
      : global_dict_(global_dict) {}

  int GetIndex(const std::string& name) {
    int index;
    if (global_dict_.GetIndex(name, &index)) {
      return index;
    }

    const auto& message_it = message_dict_.find(name);
    if (message_it != message_dict_.end()) {
      return MessageDictIndex(message_it->second);
    }

    index = message_words_.size();
    message_words_.push_back(name);
    message_dict_[name] = index;
    return MessageDictIndex(index);
  }

  const std::vector<std::string>& GetWords() const { return message_words_; }

  void Clear() {
    message_words_.clear();
    message_dict_.clear();
  }

 private:
  const GlobalDictionary& global_dict_;

  // Per message dictionary
  std::vector<std::string> message_words_;
  std::unordered_map<std::string, int> message_dict_;
};

::istio::mixer::v1::StringMap CreateStringMap(
    const Attributes_StringMap& raw_map, MessageDictionary& dict) {
  ::istio::mixer::v1::StringMap compressed_map;
  auto* map_pb = compressed_map.mutable_entries();
  for (const auto& it : raw_map.entries()) {
    (*map_pb)[dict.GetIndex(it.first)] = dict.GetIndex(it.second);
  }
  return compressed_map;
}

void CompressByDict(const Attributes& attributes, MessageDictionary& dict,
                    CompressedAttributes* pb) {
  // Fill attributes.
  for (const auto& it : attributes.attributes()) {
    const std::string& name = it.first;
    const Attributes_AttributeValue& value = it.second;

    int index = dict.GetIndex(name);

    // Fill the attribute to proper map.
    switch (value.value_case()) {
      case Attributes_AttributeValue::kStringValue:
        (*pb->mutable_strings())[index] = dict.GetIndex(value.string_value());
        break;
      case Attributes_AttributeValue::kBytesValue:
        (*pb->mutable_bytes())[index] = value.bytes_value();
        break;
      case Attributes_AttributeValue::kInt64Value:
        (*pb->mutable_int64s())[index] = value.int64_value();
        break;
      case Attributes_AttributeValue::kDoubleValue:
        (*pb->mutable_doubles())[index] = value.double_value();
        break;
      case Attributes_AttributeValue::kBoolValue:
        (*pb->mutable_bools())[index] = value.bool_value();
        break;
      case Attributes_AttributeValue::kTimestampValue:
        (*pb->mutable_timestamps())[index] = value.timestamp_value();
        break;
      case Attributes_AttributeValue::kDurationValue:
        (*pb->mutable_durations())[index] = value.duration_value();
        break;
      case Attributes_AttributeValue::kStringMapValue:
        (*pb->mutable_string_maps())[index] =
            CreateStringMap(value.string_map_value(), dict);
        break;
      case Attributes_AttributeValue::VALUE_NOT_SET:
        break;
    }
  }
}

class BatchCompressorImpl : public BatchCompressor {
 public:
  BatchCompressorImpl(const GlobalDictionary& global_dict)
      : global_dict_(global_dict), dict_(global_dict) {
    AllocReportProtobuf();
  }

  void Add(const Attributes& attributes) override {
    CompressByDict(attributes, dict_, report_->add_attributes());
  }

  int size() const override { return report_->attributes_size(); }

  const ::istio::mixer::v1::ReportRequest& Finish() override {
    for (const std::string& word : dict_.GetWords()) {
      report_->add_default_words(word);
    }
    report_->set_global_word_count(global_dict_.size());
    return *report_;
  }

  void Clear() override {
    dict_.Clear();
    AllocReportProtobuf();
  }

 private:
  void AllocReportProtobuf() {
    arena_.reset(new google::protobuf::Arena);
    report_ = google::protobuf::Arena::CreateMessage<
        ::istio::mixer::v1::ReportRequest>(arena_.get());
  }

  const GlobalDictionary& global_dict_;
  MessageDictionary dict_;
  // protobuf arena
  std::unique_ptr<google::protobuf::Arena> arena_;
  ::istio::mixer::v1::ReportRequest* report_;
};

}  // namespace

GlobalDictionary::GlobalDictionary() {
  const std::vector<std::string>& global_words = GetGlobalWords();
  for (unsigned int i = 0; i < global_words.size(); i++) {
    global_dict_[global_words[i]] = i;
  }
  top_index_ = global_words.size();
}

// Lookup the index, return true if found.
bool GlobalDictionary::GetIndex(const std::string name, int* index) const {
  const auto& it = global_dict_.find(name);
  if (it != global_dict_.end() && it->second < top_index_) {
    // Return global dictionary index.
    *index = it->second;
    return true;
  }
  return false;
}

void GlobalDictionary::ShrinkToBase() {
  if (top_index_ > kGlobalDictionaryBaseSize) {
    top_index_ = kGlobalDictionaryBaseSize;
    GOOGLE_LOG(INFO) << "Shrink global dictionary " << top_index_
                     << " to base.";
  }
}

void AttributeCompressor::Compress(
    const Attributes& attributes,
    ::istio::mixer::v1::CompressedAttributes* pb) const {
  MessageDictionary dict(global_dict_);
  CompressByDict(attributes, dict, pb);

  for (const std::string& word : dict.GetWords()) {
    pb->add_words(word);
  }
}

std::unique_ptr<BatchCompressor> AttributeCompressor::CreateBatchCompressor()
    const {
  return std::unique_ptr<BatchCompressor>(
      new BatchCompressorImpl(global_dict_));
}

}  // namespace mixerclient
}  // namespace istio
<commit_msg>reuse report protobuf instead of using arena allocation (#1989)<commit_after>/* Copyright 2017 Istio Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/istio/mixerclient/attribute_compressor.h"
#include "google/protobuf/arena.h"
#include "include/istio/utils/protobuf.h"
#include "src/istio/mixerclient/global_dictionary.h"

using ::istio::mixer::v1::Attributes;
using ::istio::mixer::v1::Attributes_AttributeValue;
using ::istio::mixer::v1::Attributes_StringMap;
using ::istio::mixer::v1::CompressedAttributes;

namespace istio {
namespace mixerclient {
namespace {

// The size of first version of global dictionary.
// If any dictionary error, global dictionary will fall back to this version.
const int kGlobalDictionaryBaseSize = 111;

// Return per message dictionary index.
int MessageDictIndex(int idx) { return -(idx + 1); }

// Per message dictionary.
class MessageDictionary {
 public:
  MessageDictionary(const GlobalDictionary& global_dict)
      : global_dict_(global_dict) {}

  int GetIndex(const std::string& name) {
    int index;
    if (global_dict_.GetIndex(name, &index)) {
      return index;
    }

    const auto& message_it = message_dict_.find(name);
    if (message_it != message_dict_.end()) {
      return MessageDictIndex(message_it->second);
    }

    index = message_words_.size();
    message_words_.push_back(name);
    message_dict_[name] = index;
    return MessageDictIndex(index);
  }

  const std::vector<std::string>& GetWords() const { return message_words_; }

  void Clear() {
    message_words_.clear();
    message_dict_.clear();
  }

 private:
  const GlobalDictionary& global_dict_;

  // Per message dictionary
  std::vector<std::string> message_words_;
  std::unordered_map<std::string, int> message_dict_;
};

::istio::mixer::v1::StringMap CreateStringMap(
    const Attributes_StringMap& raw_map, MessageDictionary& dict) {
  ::istio::mixer::v1::StringMap compressed_map;
  auto* map_pb = compressed_map.mutable_entries();
  for (const auto& it : raw_map.entries()) {
    (*map_pb)[dict.GetIndex(it.first)] = dict.GetIndex(it.second);
  }
  return compressed_map;
}

void CompressByDict(const Attributes& attributes, MessageDictionary& dict,
                    CompressedAttributes* pb) {
  // Fill attributes.
  for (const auto& it : attributes.attributes()) {
    const std::string& name = it.first;
    const Attributes_AttributeValue& value = it.second;

    int index = dict.GetIndex(name);

    // Fill the attribute to proper map.
    switch (value.value_case()) {
      case Attributes_AttributeValue::kStringValue:
        (*pb->mutable_strings())[index] = dict.GetIndex(value.string_value());
        break;
      case Attributes_AttributeValue::kBytesValue:
        (*pb->mutable_bytes())[index] = value.bytes_value();
        break;
      case Attributes_AttributeValue::kInt64Value:
        (*pb->mutable_int64s())[index] = value.int64_value();
        break;
      case Attributes_AttributeValue::kDoubleValue:
        (*pb->mutable_doubles())[index] = value.double_value();
        break;
      case Attributes_AttributeValue::kBoolValue:
        (*pb->mutable_bools())[index] = value.bool_value();
        break;
      case Attributes_AttributeValue::kTimestampValue:
        (*pb->mutable_timestamps())[index] = value.timestamp_value();
        break;
      case Attributes_AttributeValue::kDurationValue:
        (*pb->mutable_durations())[index] = value.duration_value();
        break;
      case Attributes_AttributeValue::kStringMapValue:
        (*pb->mutable_string_maps())[index] =
            CreateStringMap(value.string_map_value(), dict);
        break;
      case Attributes_AttributeValue::VALUE_NOT_SET:
        break;
    }
  }
}

class BatchCompressorImpl : public BatchCompressor {
 public:
  BatchCompressorImpl(const GlobalDictionary& global_dict)
      : global_dict_(global_dict), dict_(global_dict) {}

  void Add(const Attributes& attributes) override {
    CompressByDict(attributes, dict_, report_.add_attributes());
  }

  int size() const override { return report_.attributes_size(); }

  const ::istio::mixer::v1::ReportRequest& Finish() override {
    for (const std::string& word : dict_.GetWords()) {
      report_.add_default_words(word);
    }
    report_.set_global_word_count(global_dict_.size());
    return report_;
  }

  void Clear() override {
    dict_.Clear();
    report_.Clear();
  }

 private:
  const GlobalDictionary& global_dict_;
  MessageDictionary dict_;
  ::istio::mixer::v1::ReportRequest report_;
};

}  // namespace

GlobalDictionary::GlobalDictionary() {
  const std::vector<std::string>& global_words = GetGlobalWords();
  for (unsigned int i = 0; i < global_words.size(); i++) {
    global_dict_[global_words[i]] = i;
  }
  top_index_ = global_words.size();
}

// Lookup the index, return true if found.
bool GlobalDictionary::GetIndex(const std::string name, int* index) const {
  const auto& it = global_dict_.find(name);
  if (it != global_dict_.end() && it->second < top_index_) {
    // Return global dictionary index.
    *index = it->second;
    return true;
  }
  return false;
}

void GlobalDictionary::ShrinkToBase() {
  if (top_index_ > kGlobalDictionaryBaseSize) {
    top_index_ = kGlobalDictionaryBaseSize;
    GOOGLE_LOG(INFO) << "Shrink global dictionary " << top_index_
                     << " to base.";
  }
}

void AttributeCompressor::Compress(
    const Attributes& attributes,
    ::istio::mixer::v1::CompressedAttributes* pb) const {
  MessageDictionary dict(global_dict_);
  CompressByDict(attributes, dict, pb);

  for (const std::string& word : dict.GetWords()) {
    pb->add_words(word);
  }
}

std::unique_ptr<BatchCompressor> AttributeCompressor::CreateBatchCompressor()
    const {
  return std::unique_ptr<BatchCompressor>(
      new BatchCompressorImpl(global_dict_));
}

}  // namespace mixerclient
}  // namespace istio
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "brightray/browser/notification_presenter.h"

#include "brightray/browser/notification.h"

namespace brightray {

NotificationPresenter::NotificationPresenter() {}

NotificationPresenter::~NotificationPresenter() {
  for (Notification* notification : notifications_)
    delete notification;
}

base::WeakPtr<Notification> NotificationPresenter::CreateNotification(
    NotificationDelegate* delegate,
    const std::string& notification_id) {
  Notification* notification = CreateNotificationObject(delegate);
  notification->set_notification_id(notification_id);
  notifications_.insert(notification);
  return notification->GetWeakPtr();
}

void NotificationPresenter::RemoveNotification(Notification* notification) {
  notifications_.erase(notification);
  delete notification;
}

void NotificationPresenter::CloseNotificationWithId(
    const std::string& notification_id) {
  auto it = std::find_if(notifications_.begin(), notifications_.end(),
                         [&notification_id](const Notification* n) {
                           return n->notification_id() == notification_id;
                         });
  if (it != notifications_.end())
    (*it)->Dismiss();
}

}  // namespace brightray
<commit_msg>fix: include algorithm in notification_presenter<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "brightray/browser/notification_presenter.h"

#include <algorithm>

#include "brightray/browser/notification.h"

namespace brightray {

NotificationPresenter::NotificationPresenter() {}

NotificationPresenter::~NotificationPresenter() {
  for (Notification* notification : notifications_)
    delete notification;
}

base::WeakPtr<Notification> NotificationPresenter::CreateNotification(
    NotificationDelegate* delegate,
    const std::string& notification_id) {
  Notification* notification = CreateNotificationObject(delegate);
  notification->set_notification_id(notification_id);
  notifications_.insert(notification);
  return notification->GetWeakPtr();
}

void NotificationPresenter::RemoveNotification(Notification* notification) {
  notifications_.erase(notification);
  delete notification;
}

void NotificationPresenter::CloseNotificationWithId(
    const std::string& notification_id) {
  auto it = std::find_if(notifications_.begin(), notifications_.end(),
                         [&notification_id](const Notification* n) {
                           return n->notification_id() == notification_id;
                         });
  if (it != notifications_.end())
    (*it)->Dismiss();
}

}  // namespace brightray
<|endoftext|>


<commit_before>#include <cassert>
#include <istream>
#include <ostream>
#include <fstream>
#include <iostream>
#include <memory>

#include "builtin_port.hh"
#include "lisp_ptr.hh"
#include "reader.hh"
#include "printer.hh"
#include "zs_error.hh"
#include "builtin_util.hh"

using namespace std;

namespace {

template<typename T>
zs_error port_type_check_failed(const char* func_name, Lisp_ptr p){
  return zs_error_arg1(func_name,
                       printf_string("arg is not %s!", stringify(to_tag<Ptr_tag, T*>())),
                       {p});
}

template<typename IOType, typename F_IOType>
Lisp_ptr port_open_file(const char* name){
  ZsArgs args;
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed(name, Ptr_tag::string, args[0]);
  }

  unique_ptr<IOType> p{new F_IOType(str->c_str())};
  if(!*p){
    throw zs_error_arg1(name, "failed at opening file");
  }

  return {p.release()};
}

template<typename IOType, typename F_IOType>
Lisp_ptr port_close(const char* name){
  ZsArgs args;
  auto p = args[0].get<IOType*>();
  if(!p){
    throw port_type_check_failed<IOType>(name, args[0]);
  }

  auto fio = dynamic_cast<F_IOType*>(p);
  if(!fio){
    cerr << "native func warning: " << name << ": passed port is not associated to file\n";
    return Lisp_ptr{false};
  }

  fio->close();
  return Lisp_ptr{true};
}

template<typename Fun>
Lisp_ptr port_input_call(const char* name, Fun&& fun){
  ZsArgs args;

  InputPort* p;

  switch(args.size()){
  case 0:
    p = vm.frame()->find(intern(vm.symtable(), CURRENT_INPUT_PORT_SYMNAME)).get<InputPort*>();
    if(!p){
      throw zs_error_arg1(name, "internal variable '"CURRENT_INPUT_PORT_SYMNAME"' is broken!");
    }
    break;
  case 1:
    p = args[0].get<InputPort*>();
    if(!p){
      throw port_type_check_failed<InputPort>(name, args[0]);
    }
    break;
  default:
    throw builtin_argcount_failed(name, 0, 1, args.size());
  }

  return Lisp_ptr{fun(p)};
}

template<typename Fun>
Lisp_ptr port_output_call(const char* name, Fun&& fun){
  ZsArgs args;

  OutputPort* p;

  switch(args.size()){
  case 1:
    p = vm.frame()->find(intern(vm.symtable(), CURRENT_OUTPUT_PORT_SYMNAME)).get<OutputPort*>();
    if(!p){
      throw zs_error_arg1(name, "internal variable '"CURRENT_OUTPUT_PORT_SYMNAME"' is broken!");
    }
    break;
  case 2:
    p = args[1].get<OutputPort*>();
    if(!p){
      throw port_type_check_failed<OutputPort>(name, args[1]);
    }
    break;
  default:
    throw builtin_argcount_failed(name, 1, 2, args.size());
  }

  return Lisp_ptr{fun(args[0], p)};
}

} //namespace

Lisp_ptr port_open_file_i(){
  return port_open_file<InputPort, ifstream>("open-input-file");
}

Lisp_ptr port_open_file_o(){
  return port_open_file<OutputPort, ofstream>("open-output-file");
}

Lisp_ptr port_close_i(){
  return port_close<InputPort, std::ifstream>("close-input-port");
}

Lisp_ptr port_close_o(){
  return port_close<OutputPort, std::ofstream>("close-output-port");
}

Lisp_ptr port_read(){
  return port_input_call("read",
                         [](std::istream* is){ return read(*is); });
}

Lisp_ptr port_read_char(){
  return port_input_call("read-char",
                         [](std::istream* is) -> char { return is->get(); });
}

Lisp_ptr port_peek_char(){
  return port_input_call("peek-char",
                         [](std::istream* is) -> char{ return is->peek(); });
}

Lisp_ptr port_eof_p(){
  ZsArgs args;
  if(args[0].tag() != Ptr_tag::character){
    return Lisp_ptr{false};
  }

  return Lisp_ptr{args[0].get<char>() == EOF};
}

Lisp_ptr port_write(){
  return port_output_call("write",
                          [](Lisp_ptr c, std::ostream* os) -> bool{
                            print(*os, c, print_human_readable::f);
                            return true;
                          });
}

Lisp_ptr port_display(){
  return port_output_call("display",
                          [](Lisp_ptr c, std::ostream* os) -> bool{
                            print(*os, c, print_human_readable::t);
                            return true;
                          });
}

Lisp_ptr port_write_char(){
  return port_output_call("write-char",
                          [](Lisp_ptr c, std::ostream* os) -> Lisp_ptr{
                            if(c.tag() != Ptr_tag::character){
                              throw builtin_type_check_failed("write-char", Ptr_tag::character, c);
                            }

                            os->put(c.get<char>());
                            return c;
                          });
}
<commit_msg>added char-ready? skeleton<commit_after>#include <cassert>
#include <istream>
#include <ostream>
#include <fstream>
#include <iostream>
#include <memory>

#include "builtin_port.hh"
#include "lisp_ptr.hh"
#include "reader.hh"
#include "printer.hh"
#include "zs_error.hh"
#include "builtin_util.hh"

using namespace std;

namespace {

template<typename T>
zs_error port_type_check_failed(const char* func_name, Lisp_ptr p){
  return zs_error_arg1(func_name,
                       printf_string("arg is not %s!", stringify(to_tag<Ptr_tag, T*>())),
                       {p});
}

template<typename IOType, typename F_IOType>
Lisp_ptr port_open_file(const char* name){
  ZsArgs args;
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed(name, Ptr_tag::string, args[0]);
  }

  unique_ptr<IOType> p{new F_IOType(str->c_str())};
  if(!*p){
    throw zs_error_arg1(name, "failed at opening file");
  }

  return {p.release()};
}

template<typename IOType, typename F_IOType>
Lisp_ptr port_close(const char* name){
  ZsArgs args;
  auto p = args[0].get<IOType*>();
  if(!p){
    throw port_type_check_failed<IOType>(name, args[0]);
  }

  auto fio = dynamic_cast<F_IOType*>(p);
  if(!fio){
    cerr << "native func warning: " << name << ": passed port is not associated to file\n";
    return Lisp_ptr{false};
  }

  fio->close();
  return Lisp_ptr{true};
}

template<typename Fun>
Lisp_ptr port_input_call(const char* name, Fun&& fun){
  ZsArgs args;

  InputPort* p;

  switch(args.size()){
  case 0:
    p = vm.frame()->find(intern(vm.symtable(), CURRENT_INPUT_PORT_SYMNAME)).get<InputPort*>();
    if(!p){
      throw zs_error_arg1(name, "internal variable '"CURRENT_INPUT_PORT_SYMNAME"' is broken!");
    }
    break;
  case 1:
    p = args[0].get<InputPort*>();
    if(!p){
      throw port_type_check_failed<InputPort>(name, args[0]);
    }
    break;
  default:
    throw builtin_argcount_failed(name, 0, 1, args.size());
  }

  return Lisp_ptr{fun(p)};
}

template<typename Fun>
Lisp_ptr port_output_call(const char* name, Fun&& fun){
  ZsArgs args;

  OutputPort* p;

  switch(args.size()){
  case 1:
    p = vm.frame()->find(intern(vm.symtable(), CURRENT_OUTPUT_PORT_SYMNAME)).get<OutputPort*>();
    if(!p){
      throw zs_error_arg1(name, "internal variable '"CURRENT_OUTPUT_PORT_SYMNAME"' is broken!");
    }
    break;
  case 2:
    p = args[1].get<OutputPort*>();
    if(!p){
      throw port_type_check_failed<OutputPort>(name, args[1]);
    }
    break;
  default:
    throw builtin_argcount_failed(name, 1, 2, args.size());
  }

  return Lisp_ptr{fun(args[0], p)};
}

bool stream_ready(std::istream* is){
  auto avails = is->rdbuf()->in_avail();

  if(avails > 0){
    return true;
  }else if(avails < 0){ // EOF case
    return true;
  }else{
#ifdef __GLIBCXX__
    // under implementation..
    return false;
#else
#warning "char-ready? may be broken"
    return false;
#endif
  }
}

} //namespace

Lisp_ptr port_open_file_i(){
  return port_open_file<InputPort, ifstream>("open-input-file");
}

Lisp_ptr port_open_file_o(){
  return port_open_file<OutputPort, ofstream>("open-output-file");
}

Lisp_ptr port_close_i(){
  return port_close<InputPort, std::ifstream>("close-input-port");
}

Lisp_ptr port_close_o(){
  return port_close<OutputPort, std::ofstream>("close-output-port");
}

Lisp_ptr port_read(){
  return port_input_call("read",
                         [](std::istream* is){ return read(*is); });
}

Lisp_ptr port_read_char(){
  return port_input_call("read-char",
                         [](std::istream* is) -> char { return is->get(); });
}

Lisp_ptr port_peek_char(){
  return port_input_call("peek-char",
                         [](std::istream* is) -> char{ return is->peek(); });
}

Lisp_ptr port_eof_p(){
  ZsArgs args;
  if(args[0].tag() != Ptr_tag::character){
    return Lisp_ptr{false};
  }

  return Lisp_ptr{args[0].get<char>() == EOF};
}

Lisp_ptr port_write(){
  return port_output_call("write",
                          [](Lisp_ptr c, std::ostream* os) -> bool{
                            print(*os, c, print_human_readable::f);
                            return true;
                          });
}

Lisp_ptr port_display(){
  return port_output_call("display",
                          [](Lisp_ptr c, std::ostream* os) -> bool{
                            print(*os, c, print_human_readable::t);
                            return true;
                          });
}

Lisp_ptr port_write_char(){
  return port_output_call("write-char",
                          [](Lisp_ptr c, std::ostream* os) -> Lisp_ptr{
                            if(c.tag() != Ptr_tag::character){
                              throw builtin_type_check_failed("write-char", Ptr_tag::character, c);
                            }

                            os->put(c.get<char>());
                            return c;
                          });
}

Lisp_ptr port_char_ready(){
  return port_input_call("char-ready?", stream_ready);
}

<|endoftext|>