<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnordmetric/metricdb/httpapi.h>
#include <fnordmetric/query/queryservice.h>
#include <fnordmetric/metricdb/metricrepository.h>
#include <fnordmetric/metricdb/metrictablerepository.h>
#include <fnordmetric/util/stringutil.h>

namespace fnordmetric {
namespace metricdb {

static const char kMetricsUrl[] = "/metrics";
static const char kMetricsUrlPrefix[] = "/metrics/";
static const char kQueryUrl[] = "/query";
static const char kLabelParamPrefix[] = "label[";

HTTPAPI::HTTPAPI(IMetricRepository* metric_repo) : metric_repo_(metric_repo) {}

bool HTTPAPI::handleHTTPRequest(
    http::HTTPRequest* request,
    http::HTTPResponse* response) {
  util::URI uri(request->getUrl());
  auto path = uri.path();
  fnord::util::StringUtil::stripTrailingSlashes(&path);

  response->addHeader("Access-Control-Allow-Origin", "*");

  // PATH: ^/metrics/?$
  if (path == kMetricsUrl) {
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
        renderMetricList(request, response, &uri);
        return true;
      case http::HTTPRequest::M_POST:
        insertSample(request, response, &uri);
        return true;
      default:
        return false;
    }
  }

  // PATH: ^/metrics/.*
  if (path.compare(0, sizeof(kMetricsUrlPrefix) - 1, kMetricsUrlPrefix) == 0) {
    // PATH: ^/metrics/(.*)$
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
        renderMetricSampleScan(request, response, &uri);
        return true;
      default:
        return false;
    }
  }

  // PATH: ^/query/?*
  if (path == kQueryUrl) {
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
      case http::HTTPRequest::M_POST:
        executeQuery(request, response, &uri);
        return true;
      default:
        return false;
    }
    return true;
  }

  return false;
}

void HTTPAPI::renderMetricList(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");
  util::JSONOutputStream json(response->getBodyOutputStream());

  json.beginObject();
  json.addObjectEntry("metrics");
  json.beginArray();

  int i = 0;
  for (const auto& metric : metric_repo_->listMetrics()) {
    if (i++ > 0) { json.addComma(); }
    renderMetricJSON(metric, &json);
  }

  json.endArray();
  json.endObject();
}

void HTTPAPI::insertSample(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  auto params = uri->queryParams();

  std::string metric_key;
  if (!util::URI::getParam(params, "metric", &metric_key)) {
    response->addBody("error: invalid metric key: " + metric_key);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  std::string value_str;
  if (!util::URI::getParam(params, "value", &value_str)) {
    response->addBody("error: missing ?value=... parameter");
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  std::vector<std::pair<std::string, std::string>> labels;
  for (const auto& param : params) {
    const auto& key = param.first;
    const auto& value = param.second;

    if (key.compare(0, sizeof(kLabelParamPrefix) - 1, kLabelParamPrefix) == 0 &&
        key.back() == ']') {
      auto label_key = key.substr(
          sizeof(kLabelParamPrefix) - 1,
          key.size() - sizeof(kLabelParamPrefix));

      labels.emplace_back(label_key, value);
    }
  }

  double sample_value;
  try {
    sample_value = std::stod(value_str);
  } catch (std::exception& e) {
    response->addBody("error: invalid value: " + value_str);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  auto metric = metric_repo_->findOrCreateMetric(metric_key);
  metric->insertSample(sample_value, labels);
  response->setStatus(http::kStatusCreated);
}

void HTTPAPI::renderMetricSampleScan(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  auto metric_key = uri->path().substr(sizeof(kMetricsUrlPrefix) - 1);
  if (metric_key.size() < 3) {
    response->addBody("error: invalid metric key: " + metric_key);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  auto metric = metric_repo_->findMetric(metric_key);
  if (metric == nullptr) {
    response->addBody("metric not found: " + metric_key);
    response->setStatus(http::kStatusNotFound);
    return;
  }

  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");
  util::JSONOutputStream json(response->getBodyOutputStream());

  json.beginObject();

  json.addObjectEntry("metric");
  renderMetricJSON(metric, &json);
  json.addComma();

  json.addObjectEntry("samples");
  json.beginArray();

  int i = 0;
  metric->scanSamples(
      fnord::util::DateTime::epoch(),
      fnord::util::DateTime::now(),
      [&json, &i] (Sample* sample) -> bool {
        if (i++ > 0) { json.addComma(); }
        json.beginObject();

        json.addObjectEntry("time");
        json.addLiteral<uint64_t>(static_cast<uint64_t>(sample->time()));
        json.addComma();

        json.addObjectEntry("value");
        json.addLiteral<double>(sample->value());
        json.addComma();

        json.addObjectEntry("labels");
        json.beginObject();
        auto labels = sample->labels();
        for (int n = 0; n < labels.size(); n++) {
          if (n > 0) {
            json.addComma();
          }

          json.addObjectEntry(labels[n].first);
          json.addString(labels[n].second);
        }
        json.endObject();

        json.endObject();
        return true;
      });

  json.endArray();
  json.endObject();
}

void HTTPAPI::executeQuery(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");

  std::shared_ptr<util::InputStream> input_stream =
      request->getBodyInputStream();

  std::shared_ptr<util::OutputStream> output_stream =
      response->getBodyOutputStream();

  query::QueryService query_service;
  std::unique_ptr<query::TableRepository> table_repo(
      new MetricTableRepository(metric_repo_));

  try {
    query_service.executeQuery(
        input_stream,
        query::QueryService::FORMAT_JSON,
        output_stream,
        std::move(table_repo));

  } catch (util::RuntimeException e) {
    response->clearBody();

    util::JSONOutputStream json(std::move(output_stream));
    json.beginObject();
    json.addObjectEntry("status");
    json.addString("error");
    json.addComma();
    json.addObjectEntry("error");
    json.addString(e.getMessage());
    json.endObject();
  }
}

void HTTPAPI::renderMetricJSON(
    IMetric* metric,
    util::JSONOutputStream* json) const {
  json->beginObject();

  json->addObjectEntry("key");
  json->addString(metric->key());
  json->addComma();

  json->addObjectEntry("total_bytes");
  json->addLiteral<size_t>(metric->totalBytes());
  json->addComma();

  json->addObjectEntry("last_insert");
  json->addLiteral<uint64_t>(static_cast<uint64_t>(metric->lastInsertTime()));
  json->addComma();

  json->addObjectEntry("labels");
  json->beginArray();
  auto labels = metric->labels();
  for (auto cur = labels.begin(); cur != labels.end(); ++cur) {
    if (cur != labels.begin()) {
      json->addComma();
    }
    json->addString(*cur);
  }
  json->endArray();

  json->endObject();
}

}
}
<commit_msg>implement final POST /metrics API<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnordmetric/metricdb/httpapi.h>
#include <fnordmetric/query/queryservice.h>
#include <fnordmetric/metricdb/metricrepository.h>
#include <fnordmetric/metricdb/metrictablerepository.h>
#include <fnordmetric/util/stringutil.h>

namespace fnordmetric {
namespace metricdb {

static const char kMetricsUrl[] = "/metrics";
static const char kMetricsUrlPrefix[] = "/metrics/";
static const char kQueryUrl[] = "/query";
static const char kLabelParamPrefix[] = "label[";

HTTPAPI::HTTPAPI(IMetricRepository* metric_repo) : metric_repo_(metric_repo) {}

bool HTTPAPI::handleHTTPRequest(
    http::HTTPRequest* request,
    http::HTTPResponse* response) {
  util::URI uri(request->getUrl());
  auto path = uri.path();
  fnord::util::StringUtil::stripTrailingSlashes(&path);

  response->addHeader("Access-Control-Allow-Origin", "*");

  // PATH: ^/metrics/?$
  if (path == kMetricsUrl) {
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
        renderMetricList(request, response, &uri);
        return true;
      case http::HTTPRequest::M_POST:
        insertSample(request, response, &uri);
        return true;
      default:
        return false;
    }
  }

  // PATH: ^/metrics/.*
  if (path.compare(0, sizeof(kMetricsUrlPrefix) - 1, kMetricsUrlPrefix) == 0) {
    // PATH: ^/metrics/(.*)$
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
        renderMetricSampleScan(request, response, &uri);
        return true;
      default:
        return false;
    }
  }

  // PATH: ^/query/?*
  if (path == kQueryUrl) {
    switch (request->method()) {
      case http::HTTPRequest::M_GET:
      case http::HTTPRequest::M_POST:
        executeQuery(request, response, &uri);
        return true;
      default:
        return false;
    }
    return true;
  }

  return false;
}

void HTTPAPI::renderMetricList(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");
  util::JSONOutputStream json(response->getBodyOutputStream());

  json.beginObject();
  json.addObjectEntry("metrics");
  json.beginArray();

  int i = 0;
  for (const auto& metric : metric_repo_->listMetrics()) {
    if (i++ > 0) { json.addComma(); }
    renderMetricJSON(metric, &json);
  }

  json.endArray();
  json.endObject();
}

void HTTPAPI::insertSample(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  const auto& postbody = request->getBody();
  util::URI::ParamList params;

  if (postbody.size() > 0) {
    util::URI::parseQueryString(postbody, &params);
  } else {
    params = uri->queryParams();
  }

  std::string metric_key;
  if (!util::URI::getParam(params, "metric", &metric_key)) {
    response->addBody("error: invalid metric key: " + metric_key);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  std::string value_str;
  if (!util::URI::getParam(params, "value", &value_str)) {
    response->addBody("error: missing ?value=... parameter");
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  std::vector<std::pair<std::string, std::string>> labels;
  for (const auto& param : params) {
    const auto& key = param.first;
    const auto& value = param.second;

    if (key.compare(0, sizeof(kLabelParamPrefix) - 1, kLabelParamPrefix) == 0 &&
        key.back() == ']') {
      auto label_key = key.substr(
          sizeof(kLabelParamPrefix) - 1,
          key.size() - sizeof(kLabelParamPrefix));

      labels.emplace_back(label_key, value);
    }
  }

  double sample_value;
  try {
    sample_value = std::stod(value_str);
  } catch (std::exception& e) {
    response->addBody("error: invalid value: " + value_str);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  auto metric = metric_repo_->findOrCreateMetric(metric_key);
  metric->insertSample(sample_value, labels);
  response->setStatus(http::kStatusCreated);
}

void HTTPAPI::renderMetricSampleScan(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  auto metric_key = uri->path().substr(sizeof(kMetricsUrlPrefix) - 1);
  if (metric_key.size() < 3) {
    response->addBody("error: invalid metric key: " + metric_key);
    response->setStatus(http::kStatusBadRequest);
    return;
  }

  auto metric = metric_repo_->findMetric(metric_key);
  if (metric == nullptr) {
    response->addBody("metric not found: " + metric_key);
    response->setStatus(http::kStatusNotFound);
    return;
  }

  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");
  util::JSONOutputStream json(response->getBodyOutputStream());

  json.beginObject();

  json.addObjectEntry("metric");
  renderMetricJSON(metric, &json);
  json.addComma();

  json.addObjectEntry("samples");
  json.beginArray();

  int i = 0;
  metric->scanSamples(
      fnord::util::DateTime::epoch(),
      fnord::util::DateTime::now(),
      [&json, &i] (Sample* sample) -> bool {
        if (i++ > 0) { json.addComma(); }
        json.beginObject();

        json.addObjectEntry("time");
        json.addLiteral<uint64_t>(static_cast<uint64_t>(sample->time()));
        json.addComma();

        json.addObjectEntry("value");
        json.addLiteral<double>(sample->value());
        json.addComma();

        json.addObjectEntry("labels");
        json.beginObject();
        auto labels = sample->labels();
        for (int n = 0; n < labels.size(); n++) {
          if (n > 0) {
            json.addComma();
          }

          json.addObjectEntry(labels[n].first);
          json.addString(labels[n].second);
        }
        json.endObject();

        json.endObject();
        return true;
      });

  json.endArray();
  json.endObject();
}

void HTTPAPI::executeQuery(
    http::HTTPRequest* request,
    http::HTTPResponse* response,
    util::URI* uri) {
  response->setStatus(http::kStatusOK);
  response->addHeader("Content-Type", "application/json; charset=utf-8");

  std::shared_ptr<util::InputStream> input_stream =
      request->getBodyInputStream();

  std::shared_ptr<util::OutputStream> output_stream =
      response->getBodyOutputStream();

  query::QueryService query_service;
  std::unique_ptr<query::TableRepository> table_repo(
      new MetricTableRepository(metric_repo_));

  try {
    query_service.executeQuery(
        input_stream,
        query::QueryService::FORMAT_JSON,
        output_stream,
        std::move(table_repo));

  } catch (util::RuntimeException e) {
    response->clearBody();

    util::JSONOutputStream json(std::move(output_stream));
    json.beginObject();
    json.addObjectEntry("status");
    json.addString("error");
    json.addComma();
    json.addObjectEntry("error");
    json.addString(e.getMessage());
    json.endObject();
  }
}

void HTTPAPI::renderMetricJSON(
    IMetric* metric,
    util::JSONOutputStream* json) const {
  json->beginObject();

  json->addObjectEntry("key");
  json->addString(metric->key());
  json->addComma();

  json->addObjectEntry("total_bytes");
  json->addLiteral<size_t>(metric->totalBytes());
  json->addComma();

  json->addObjectEntry("last_insert");
  json->addLiteral<uint64_t>(static_cast<uint64_t>(metric->lastInsertTime()));
  json->addComma();

  json->addObjectEntry("labels");
  json->beginArray();
  auto labels = metric->labels();
  for (auto cur = labels.begin(); cur != labels.end(); ++cur) {
    if (cur != labels.begin()) {
      json->addComma();
    }
    json->addString(*cur);
  }
  json->endArray();

  json->endObject();
}

}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: richtextengine.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 23:07:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX
#define FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX

#ifndef _MyEDITENG_HXX
#include <svx/editeng.hxx>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif

#include <vector>

class SfxItemPool;
class EditStatus;
//........................................................................
namespace frm
{
//........................................................................

    //====================================================================
    //= IEngineStatusListener
    //====================================================================
    class IEngineStatusListener
    {
    public:
        virtual void EditEngineStatusChanged( const EditStatus& _rStatus ) = 0;
    };

    //====================================================================
    //= RichTextEngine
    //====================================================================
    class RichTextEngine : public EditEngine
    {
    private:
        SfxItemPool*                            m_pEnginePool;
        ::std::vector< IEngineStatusListener* > m_aStatusListeners;

    public:
        static  RichTextEngine* Create();
                RichTextEngine* Clone();

                ~RichTextEngine( );

        // for multiplexing the StatusChanged events of the edit engine
        void registerEngineStatusListener( IEngineStatusListener* _pListener );
        void revokeEngineStatusListener( IEngineStatusListener* _pListener );

    protected:
        /** constructs a new RichTextEngine. The instances takes the ownership of the given SfxItemPool
        */
        RichTextEngine( SfxItemPool* _pPool );

    private:
        RichTextEngine( );                                  // never implemented
        RichTextEngine( const RichTextEngine& );            // never implemented
        RichTextEngine& operator=( const RichTextEngine& ); // never implemented

    private:
        DECL_LINK( EditEngineStatusChanged, EditStatus* );
    };

//........................................................................
} // namespace frm
//........................................................................

#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX

<commit_msg>INTEGRATION: CWS oj14 (1.3.160); FILE MERGED 2007/01/25 07:55:11 oj 1.3.160.1: memory leak fixed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: richtextengine.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-06 09:56:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX
#define FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX

#ifndef _MyEDITENG_HXX
#include <svx/editeng.hxx>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif

#include <vector>

class SfxItemPool;
class EditStatus;
//........................................................................
namespace frm
{
//........................................................................

    //====================================================================
    //= IEngineStatusListener
    //====================================================================
    class IEngineStatusListener
    {
    public:
        virtual void EditEngineStatusChanged( const EditStatus& _rStatus ) = 0;
    };

    //====================================================================
    //= RichTextEngine
    //====================================================================
    class RichTextEngine : public EditEngine
    {
    private:
        SfxItemPool*                            m_pEnginePool;
        ::std::vector< IEngineStatusListener* > m_aStatusListeners;

    public:
        static  RichTextEngine* Create();
                RichTextEngine* Clone();

                ~RichTextEngine( );

        // for multiplexing the StatusChanged events of the edit engine
        void registerEngineStatusListener( IEngineStatusListener* _pListener );
        void revokeEngineStatusListener( IEngineStatusListener* _pListener );

        inline SfxItemPool* getPool() { return m_pEnginePool; }

    protected:
        /** constructs a new RichTextEngine. The instances takes the ownership of the given SfxItemPool
        */
        RichTextEngine( SfxItemPool* _pPool );

    private:
        RichTextEngine( );                                  // never implemented
        RichTextEngine( const RichTextEngine& );            // never implemented
        RichTextEngine& operator=( const RichTextEngine& ); // never implemented

    private:
        DECL_LINK( EditEngineStatusChanged, EditStatus* );
    };

//........................................................................
} // namespace frm
//........................................................................

#endif // FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX

<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE
 */
#pragma once
#include <chainbase/chainbase.hpp>
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/config.hpp>

#include <type_traits>

namespace eosio { namespace chain {

struct permission_level_weight {
   permission_level  permission;
   weight_type       weight;

   friend bool operator == ( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
      return tie( lhs.permission, lhs.weight ) == tie( rhs.permission, rhs.weight );
   }
};

struct key_weight {
   public_key_type key;
   weight_type     weight;

   friend bool operator == ( const key_weight& lhs, const key_weight& rhs ) {
      return tie( lhs.key, lhs.weight ) == tie( rhs.key, rhs.weight );
   }
};

struct wait_weight {
   uint32_t     wait_sec;
   weight_type  weight;

   friend bool operator == ( const wait_weight& lhs, const wait_weight& rhs ) {
      return tie( lhs.wait_sec, lhs.weight ) == tie( rhs.wait_sec, rhs.weight );
   }
};

namespace config {
   template<>
   struct billable_size<permission_level_weight> {
      static const uint64_t value = 24; ///< over value of weight for safety
   };

   template<>
   struct billable_size<key_weight> {
      static const uint64_t value = 8; ///< over value of weight for safety, dynamically sizing key
   };

   template<>
   struct billable_size<wait_weight> {
      static const uint64_t value = 16; ///< over value of weight and wait_sec for safety
   };
}

struct authority {
   authority( public_key_type k, uint32_t delay_sec = 0 )
   :threshold(1),keys({{k,1}})
   {
      if( delay_sec > 0 ) {
         threshold = 2;
         waits.push_back(wait_weight{delay_sec, 1});
      }
   }

   authority( uint32_t t, vector<key_weight> k, vector<permission_level_weight> p = {}, vector<wait_weight> w = {} )
   :threshold(t),keys(move(k)),accounts(move(p)),waits(move(w)){}
   authority(){}

   uint32_t                          threshold = 0;
   vector<key_weight>                keys;
   vector<permission_level_weight>   accounts;
   vector<wait_weight>               waits;

   friend bool operator == ( const authority& lhs, const authority& rhs ) {
      return tie( lhs.threshold, lhs.keys, lhs.accounts, lhs.waits ) == tie( rhs.threshold, rhs.keys, rhs.accounts, rhs.waits );
   }

   friend bool operator != ( const authority& lhs, const authority& rhs ) {
      return tie( lhs.threshold, lhs.keys, lhs.accounts, lhs.waits ) != tie( rhs.threshold, rhs.keys, rhs.accounts, rhs.waits );
   }
};

struct shared_authority {
   shared_authority( chainbase::allocator<char> alloc )
   :keys(alloc),accounts(alloc),waits(alloc){}

   shared_authority& operator=(const authority& a) {
      threshold = a.threshold;
      keys = decltype(keys)(a.keys.begin(), a.keys.end(), keys.get_allocator());
      accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator());
      waits = decltype(waits)(a.waits.begin(), a.waits.end(), waits.get_allocator());
      return *this;
   }

   uint32_t                                   threshold = 0;
   shared_vector<key_weight>                  keys;
   shared_vector<permission_level_weight>     accounts;
   shared_vector<wait_weight>                 waits;

   operator authority()const { return to_authority(); }
   authority to_authority()const {
      authority auth;
      auth.threshold = threshold;
      auth.keys.reserve(keys.size());
      auth.accounts.reserve(accounts.size());
      auth.waits.reserve(waits.size());
      for( const auto& k : keys ) { auth.keys.emplace_back( k ); }
      for( const auto& a : accounts ) { auth.accounts.emplace_back( a ); }
      for( const auto& w : waits ) { auth.waits.emplace_back( w ); }
      return auth;
   }

   size_t get_billable_size() const {
      size_t accounts_size = accounts.size() * config::billable_size_v<permission_level_weight>;
      size_t waits_size = waits.size() * config::billable_size_v<wait_weight>;
      size_t keys_size = 0;
      for (const auto& k: keys) {
         keys_size += config::billable_size_v<key_weight>;
         keys_size += fc::raw::pack_size(k.key);  ///< serialized size of the key
      }

      return accounts_size + waits_size + keys_size;
   }
};

namespace config {
   template<>
   struct billable_size<shared_authority> {
      static const uint64_t value = (3 * config::fixed_overhead_shared_vector_ram_bytes) + 4;
   };
}

/**
 * Makes sure all keys are unique and sorted and all account permissions are unique and sorted and that authority can
 * be satisfied
 */
template<typename Authority>
inline bool validate( const Authority& auth ) {
   decltype(auth.threshold) total_weight = 0;

   static_assert( std::is_same<decltype(auth.threshold), uint32_t>::value &&
                  std::is_same<weight_type, uint16_t>::value &&
                  std::is_same<typename decltype(auth.keys)::value_type, key_weight>::value &&
                  std::is_same<typename decltype(auth.accounts)::value_type, permission_level_weight>::value &&
                  std::is_same<typename decltype(auth.waits)::value_type, wait_weight>::value,
                  "unexpected type for threshold and/or weight in authority" );

   if( ( auth.keys.size() + auth.accounts.size() + auth.waits.size() ) > (1 << 16) )
      return false; // overflow protection (assumes weight_type is uint16_t and threshold is of type uint32_t)

   if( auth.threshold == 0 )
      return false;

   {
      const key_weight* prev = nullptr;
      for( const auto& k : auth.keys ) {
         if( prev && !(prev->key < k.key) ) return false; // TODO: require keys to be sorted in ascending order rather than descending (requires modifying many tests)
         total_weight += k.weight;
         prev = &k;
      }
   }
   {
      const permission_level_weight* prev = nullptr;
      for( const auto& a : auth.accounts ) {
         if( prev && ( prev->permission >= a.permission ) ) return false; // TODO: require permission_levels to be sorted in ascending order rather than descending (requires modifying many tests)
         total_weight += a.weight;
         prev = &a;
      }
   }
   {
      const wait_weight* prev = nullptr;
      if( auth.waits.size() > 0 && auth.waits.front().wait_sec == 0 )
         return false;
      for( const auto& w : auth.waits ) {
         if( prev && ( prev->wait_sec >= w.wait_sec ) ) return false;
         total_weight += w.weight;
         prev = &w;
      }
   }

   return total_weight >= auth.threshold;
}

} } // namespace eosio::chain

FC_REFLECT(eosio::chain::permission_level_weight, (permission)(weight) )
FC_REFLECT(eosio::chain::key_weight, (key)(weight) )
FC_REFLECT(eosio::chain::wait_weight, (wait_sec)(weight) )
FC_REFLECT(eosio::chain::authority, (threshold)(keys)(accounts)(waits) )
FC_REFLECT(eosio::chain::shared_authority, (threshold)(keys)(accounts)(waits) )
<commit_msg>Add chain::authority constructor with permission_level<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE
 */
#pragma once
#include <chainbase/chainbase.hpp>
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/config.hpp>

#include <type_traits>

namespace eosio { namespace chain {

struct permission_level_weight {
   permission_level  permission;
   weight_type       weight;

   friend bool operator == ( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
      return tie( lhs.permission, lhs.weight ) == tie( rhs.permission, rhs.weight );
   }
};

struct key_weight {
   public_key_type key;
   weight_type     weight;

   friend bool operator == ( const key_weight& lhs, const key_weight& rhs ) {
      return tie( lhs.key, lhs.weight ) == tie( rhs.key, rhs.weight );
   }
};

struct wait_weight {
   uint32_t     wait_sec;
   weight_type  weight;

   friend bool operator == ( const wait_weight& lhs, const wait_weight& rhs ) {
      return tie( lhs.wait_sec, lhs.weight ) == tie( rhs.wait_sec, rhs.weight );
   }
};

namespace config {
   template<>
   struct billable_size<permission_level_weight> {
      static const uint64_t value = 24; ///< over value of weight for safety
   };

   template<>
   struct billable_size<key_weight> {
      static const uint64_t value = 8; ///< over value of weight for safety, dynamically sizing key
   };

   template<>
   struct billable_size<wait_weight> {
      static const uint64_t value = 16; ///< over value of weight and wait_sec for safety
   };
}

struct authority {
   authority( public_key_type k, uint32_t delay_sec = 0 )
   :threshold(1),keys({{k,1}})
   {
      if( delay_sec > 0 ) {
         threshold = 2;
         waits.push_back(wait_weight{delay_sec, 1});
      }
   }

   authority( permission_level p, uint32_t delay_sec = 0 )
   :threshold(1),accounts({{p,1}})
   {
      if( delay_sec > 0 ) {
         threshold = 2;
         waits.push_back(wait_weight{delay_sec, 1});
      }
   }

   authority( uint32_t t, vector<key_weight> k, vector<permission_level_weight> p = {}, vector<wait_weight> w = {} )
   :threshold(t),keys(move(k)),accounts(move(p)),waits(move(w)){}
   authority(){}

   uint32_t                          threshold = 0;
   vector<key_weight>                keys;
   vector<permission_level_weight>   accounts;
   vector<wait_weight>               waits;

   friend bool operator == ( const authority& lhs, const authority& rhs ) {
      return tie( lhs.threshold, lhs.keys, lhs.accounts, lhs.waits ) == tie( rhs.threshold, rhs.keys, rhs.accounts, rhs.waits );
   }

   friend bool operator != ( const authority& lhs, const authority& rhs ) {
      return tie( lhs.threshold, lhs.keys, lhs.accounts, lhs.waits ) != tie( rhs.threshold, rhs.keys, rhs.accounts, rhs.waits );
   }
};

struct shared_authority {
   shared_authority( chainbase::allocator<char> alloc )
   :keys(alloc),accounts(alloc),waits(alloc){}

   shared_authority& operator=(const authority& a) {
      threshold = a.threshold;
      keys = decltype(keys)(a.keys.begin(), a.keys.end(), keys.get_allocator());
      accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator());
      waits = decltype(waits)(a.waits.begin(), a.waits.end(), waits.get_allocator());
      return *this;
   }

   uint32_t                                   threshold = 0;
   shared_vector<key_weight>                  keys;
   shared_vector<permission_level_weight>     accounts;
   shared_vector<wait_weight>                 waits;

   operator authority()const { return to_authority(); }
   authority to_authority()const {
      authority auth;
      auth.threshold = threshold;
      auth.keys.reserve(keys.size());
      auth.accounts.reserve(accounts.size());
      auth.waits.reserve(waits.size());
      for( const auto& k : keys ) { auth.keys.emplace_back( k ); }
      for( const auto& a : accounts ) { auth.accounts.emplace_back( a ); }
      for( const auto& w : waits ) { auth.waits.emplace_back( w ); }
      return auth;
   }

   size_t get_billable_size() const {
      size_t accounts_size = accounts.size() * config::billable_size_v<permission_level_weight>;
      size_t waits_size = waits.size() * config::billable_size_v<wait_weight>;
      size_t keys_size = 0;
      for (const auto& k: keys) {
         keys_size += config::billable_size_v<key_weight>;
         keys_size += fc::raw::pack_size(k.key);  ///< serialized size of the key
      }

      return accounts_size + waits_size + keys_size;
   }
};

namespace config {
   template<>
   struct billable_size<shared_authority> {
      static const uint64_t value = (3 * config::fixed_overhead_shared_vector_ram_bytes) + 4;
   };
}

/**
 * Makes sure all keys are unique and sorted and all account permissions are unique and sorted and that authority can
 * be satisfied
 */
template<typename Authority>
inline bool validate( const Authority& auth ) {
   decltype(auth.threshold) total_weight = 0;

   static_assert( std::is_same<decltype(auth.threshold), uint32_t>::value &&
                  std::is_same<weight_type, uint16_t>::value &&
                  std::is_same<typename decltype(auth.keys)::value_type, key_weight>::value &&
                  std::is_same<typename decltype(auth.accounts)::value_type, permission_level_weight>::value &&
                  std::is_same<typename decltype(auth.waits)::value_type, wait_weight>::value,
                  "unexpected type for threshold and/or weight in authority" );

   if( ( auth.keys.size() + auth.accounts.size() + auth.waits.size() ) > (1 << 16) )
      return false; // overflow protection (assumes weight_type is uint16_t and threshold is of type uint32_t)

   if( auth.threshold == 0 )
      return false;

   {
      const key_weight* prev = nullptr;
      for( const auto& k : auth.keys ) {
         if( prev && !(prev->key < k.key) ) return false; // TODO: require keys to be sorted in ascending order rather than descending (requires modifying many tests)
         total_weight += k.weight;
         prev = &k;
      }
   }
   {
      const permission_level_weight* prev = nullptr;
      for( const auto& a : auth.accounts ) {
         if( prev && ( prev->permission >= a.permission ) ) return false; // TODO: require permission_levels to be sorted in ascending order rather than descending (requires modifying many tests)
         total_weight += a.weight;
         prev = &a;
      }
   }
   {
      const wait_weight* prev = nullptr;
      if( auth.waits.size() > 0 && auth.waits.front().wait_sec == 0 )
         return false;
      for( const auto& w : auth.waits ) {
         if( prev && ( prev->wait_sec >= w.wait_sec ) ) return false;
         total_weight += w.weight;
         prev = &w;
      }
   }

   return total_weight >= auth.threshold;
}

} } // namespace eosio::chain

FC_REFLECT(eosio::chain::permission_level_weight, (permission)(weight) )
FC_REFLECT(eosio::chain::key_weight, (key)(weight) )
FC_REFLECT(eosio::chain::wait_weight, (wait_sec)(weight) )
FC_REFLECT(eosio::chain::authority, (threshold)(keys)(accounts)(waits) )
FC_REFLECT(eosio::chain::shared_authority, (threshold)(keys)(accounts)(waits) )
<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <eos/http_plugin/http_plugin.hpp>

#include <fc/network/ip.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/io/json.hpp>

#include <boost/asio.hpp>
#include <boost/optional.hpp>

#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/config/asio.hpp>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include <websocketpp/logger/stub.hpp>

#include <thread>
#include <memory>

namespace eos {
   namespace asio = boost::asio;

   using std::map;
   using std::string;
   using boost::optional;
   using boost::asio::ip::tcp;
   using std::shared_ptr;
   using websocketpp::connection_hdl;

   namespace detail {

      struct asio_with_stub_log : public websocketpp::config::asio {
          typedef asio_with_stub_log type;
          typedef asio base;

          typedef base::concurrency_type concurrency_type;

          typedef base::request_type request_type;
          typedef base::response_type response_type;

          typedef base::message_type message_type;
          typedef base::con_msg_manager_type con_msg_manager_type;
          typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;

          /// Custom Logging policies
          /*typedef websocketpp::log::syslog<concurrency_type,
              websocketpp::log::elevel> elog_type;
          typedef websocketpp::log::syslog<concurrency_type,
              websocketpp::log::alevel> alog_type;
          */
          //typedef base::alog_type alog_type;
          //typedef base::elog_type elog_type;
          typedef websocketpp::log::stub elog_type;
          typedef websocketpp::log::stub alog_type;

          typedef base::rng_type rng_type;

          struct transport_config : public base::transport_config {
              typedef type::concurrency_type concurrency_type;
              typedef type::alog_type alog_type;
              typedef type::elog_type elog_type;
              typedef type::request_type request_type;
              typedef type::response_type response_type;
              typedef websocketpp::transport::asio::basic_socket::endpoint
                  socket_type;
          };

          typedef websocketpp::transport::asio::endpoint<transport_config>
              transport_type;

          static const long timeout_open_handshake = 0;
      };
   }

   using websocket_server_type = websocketpp::server<detail::asio_with_stub_log>;

   class http_plugin_impl {
      public:
         //shared_ptr<std::thread>  http_thread;
         //asio::io_service         http_ios;
         map<string,url_handler>  url_handlers;
         optional<tcp::endpoint>  listen_endpoint;
         string                   access_control_allow_origin;
         string                   access_control_allow_headers;
         bool                     access_control_allow_credentials = false;

         websocket_server_type    server;
   };

   http_plugin::http_plugin():my(new http_plugin_impl()){}
   http_plugin::~http_plugin(){}

   void http_plugin::set_program_options(options_description&, options_description& cfg) {
      cfg.add_options()
            ("http-server-endpoint", bpo::value<string>()->default_value("127.0.0.1:8888"),
             "The local IP and port to listen for incoming http connections.")

            ("access-control-allow-origin", bpo::value<string>()->notifier([this](const string& v) {
                my->access_control_allow_origin = v;
                ilog("configured http with Access-Control-Allow-Origin: ${o}", ("o", my->access_control_allow_origin));
             }),
             "Specify the Access-Control-Allow-Origin to be returned on each request.")

            ("access-control-allow-headers", bpo::value<string>()->notifier([this](const string& v) {
                my->access_control_allow_headers = v;
                ilog("configured http with Access-Control-Allow-Headers : ${o}", ("o", my->access_control_allow_headers));
             }),
             "Specify the Access-Control-Allow-Headers to be returned on each request.")

            ("access-control-allow-credentials",
             bpo::bool_switch()->notifier([this](bool v) {
                my->access_control_allow_credentials = v;
                if (v) ilog("configured http with Access-Control-Allow-Credentials: true");
             })->default_value(false),
             "Specify if Access-Control-Allow-Credentials: true should be returned on each request.")
            ;
   }

   void http_plugin::plugin_initialize(const variables_map& options) {
      if(options.count("http-server-endpoint")) {
        #if 0
         auto lipstr = options.at("http-server-endpoint").as< string >();
         auto fcep = fc::ip::endpoint::from_string(lipstr);
         my->listen_endpoint = tcp::endpoint(boost::asio::ip::address_v4::from_string((string)fcep.get_address()), fcep.port());
        #endif
         auto resolver = std::make_shared<tcp::resolver>( std::ref( app().get_io_service() ) );
         if( options.count( "http-server-endpoint" ) ) {
           auto lipstr =  options.at("http-server-endpoint").as< string >();
           auto host = lipstr.substr( 0, lipstr.find(':') );
           auto port = lipstr.substr( host.size()+1, lipstr.size() );
           idump((host)(port));
           tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
           my->listen_endpoint = *resolver->resolve( query);
           ilog("configured http to listen on ${h}:${p}", ("h",host)("p",port));
         }

         // uint32_t addr = my->listen_endpoint->address().to_v4().to_ulong();
         // auto fcep = fc::ip::endpoint (addr,my->listen_endpoint->port());
      }
   }

   void http_plugin::plugin_startup() {
      if(my->listen_endpoint) {

         //my->http_thread = std::make_shared<std::thread>([&](){
            ilog("start processing http thread");
            try {
               my->server.clear_access_channels(websocketpp::log::alevel::all);
               my->server.init_asio(&app().get_io_service()); //&my->http_ios);
               my->server.set_reuse_addr(true);

               my->server.set_http_handler([&](connection_hdl hdl) {
                  auto con = my->server.get_con_from_hdl(hdl);
                  try {
                     //ilog("handle http request: ${url}", ("url",con->get_uri()->str()));
                     //ilog("${body}", ("body", con->get_request_body()));

                     if (!my->access_control_allow_origin.empty()) {
                        con->append_header("Access-Control-Allow-Origin", my->access_control_allow_origin);
                     }
                     if (!my->access_control_allow_headers.empty()) {
                        con->append_header("Access-Control-Allow-Headers", my->access_control_allow_headers);
                     }
                     if (my->access_control_allow_credentials) {
                        con->append_header("Access-Control-Allow-Credentials", "true");
                     }
                     auto body = con->get_request_body();
                     auto resource = con->get_uri()->get_resource();
                     auto handler_itr = my->url_handlers.find(resource);
                     if(handler_itr != my->url_handlers.end()) {
                        handler_itr->second(resource, body, [con,this](int code, string body) {
                           con->set_body(body);
                           con->set_status(websocketpp::http::status_code::value(code));
                        });
                     } else {
                        wlog("404 - not found: ${ep}", ("ep",resource));
                        error_results results{websocketpp::http::status_code::not_found,
                                              "Not Found", "Unknown Endpoint"};
                        con->set_body(fc::json::to_string(results));
                        con->set_status(websocketpp::http::status_code::not_found);
                     }
                  } catch( const fc::exception& e ) {
                     elog( "http: ${e}", ("e",e.to_detail_string()));
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", e.to_detail_string()};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  } catch( const std::exception& e ) {
                     elog( "http: ${e}", ("e",e.what()));
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", e.what()};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  } catch( ... ) {
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", "unknown exception"};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  }
               });

               ilog("start listening for http requests");
               my->server.listen(*my->listen_endpoint);
               my->server.start_accept();

           //    my->http_ios.run();
               ilog("http io service exit");
            } catch ( const fc::exception& e ){
               elog( "http: ${e}", ("e",e.to_detail_string()));
            } catch ( const std::exception& e ){
               elog( "http: ${e}", ("e",e.what()));
            } catch (...) {
                elog("error thrown from http io service");
            }
         //});

      }
   }

   void http_plugin::plugin_shutdown() {
     // if(my->http_thread) {
         if(my->server.is_listening())
             my->server.stop_listening();
     //    my->http_ios.stop();
     //    my->http_thread->join();
     //    my->http_thread.reset();
     // }
   }

   void http_plugin::add_handler(const string& url, const url_handler& handler) {
      ilog( "add api url: ${c}", ("c",url) );
      app().get_io_service().post([=](){
        my->url_handlers.insert(std::make_pair(url,handler));
      });
   }
}
<commit_msg>Add required header.<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <eos/http_plugin/http_plugin.hpp>

#include <fc/network/ip.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/io/json.hpp>

#include <boost/asio.hpp>
#include <boost/optional.hpp>

#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/config/asio.hpp>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include <websocketpp/logger/stub.hpp>

#include <thread>
#include <memory>

namespace eos {
   namespace asio = boost::asio;

   using std::map;
   using std::string;
   using boost::optional;
   using boost::asio::ip::tcp;
   using std::shared_ptr;
   using websocketpp::connection_hdl;

   namespace detail {

      struct asio_with_stub_log : public websocketpp::config::asio {
          typedef asio_with_stub_log type;
          typedef asio base;

          typedef base::concurrency_type concurrency_type;

          typedef base::request_type request_type;
          typedef base::response_type response_type;

          typedef base::message_type message_type;
          typedef base::con_msg_manager_type con_msg_manager_type;
          typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;

          /// Custom Logging policies
          /*typedef websocketpp::log::syslog<concurrency_type,
              websocketpp::log::elevel> elog_type;
          typedef websocketpp::log::syslog<concurrency_type,
              websocketpp::log::alevel> alog_type;
          */
          //typedef base::alog_type alog_type;
          //typedef base::elog_type elog_type;
          typedef websocketpp::log::stub elog_type;
          typedef websocketpp::log::stub alog_type;

          typedef base::rng_type rng_type;

          struct transport_config : public base::transport_config {
              typedef type::concurrency_type concurrency_type;
              typedef type::alog_type alog_type;
              typedef type::elog_type elog_type;
              typedef type::request_type request_type;
              typedef type::response_type response_type;
              typedef websocketpp::transport::asio::basic_socket::endpoint
                  socket_type;
          };

          typedef websocketpp::transport::asio::endpoint<transport_config>
              transport_type;

          static const long timeout_open_handshake = 0;
      };
   }

   using websocket_server_type = websocketpp::server<detail::asio_with_stub_log>;

   class http_plugin_impl {
      public:
         //shared_ptr<std::thread>  http_thread;
         //asio::io_service         http_ios;
         map<string,url_handler>  url_handlers;
         optional<tcp::endpoint>  listen_endpoint;
         string                   access_control_allow_origin;
         string                   access_control_allow_headers;
         bool                     access_control_allow_credentials = false;

         websocket_server_type    server;
   };

   http_plugin::http_plugin():my(new http_plugin_impl()){}
   http_plugin::~http_plugin(){}

   void http_plugin::set_program_options(options_description&, options_description& cfg) {
      cfg.add_options()
            ("http-server-endpoint", bpo::value<string>()->default_value("127.0.0.1:8888"),
             "The local IP and port to listen for incoming http connections.")

            ("access-control-allow-origin", bpo::value<string>()->notifier([this](const string& v) {
                my->access_control_allow_origin = v;
                ilog("configured http with Access-Control-Allow-Origin: ${o}", ("o", my->access_control_allow_origin));
             }),
             "Specify the Access-Control-Allow-Origin to be returned on each request.")

            ("access-control-allow-headers", bpo::value<string>()->notifier([this](const string& v) {
                my->access_control_allow_headers = v;
                ilog("configured http with Access-Control-Allow-Headers : ${o}", ("o", my->access_control_allow_headers));
             }),
             "Specify the Access-Control-Allow-Headers to be returned on each request.")

            ("access-control-allow-credentials",
             bpo::bool_switch()->notifier([this](bool v) {
                my->access_control_allow_credentials = v;
                if (v) ilog("configured http with Access-Control-Allow-Credentials: true");
             })->default_value(false),
             "Specify if Access-Control-Allow-Credentials: true should be returned on each request.")
            ;
   }

   void http_plugin::plugin_initialize(const variables_map& options) {
      if(options.count("http-server-endpoint")) {
        #if 0
         auto lipstr = options.at("http-server-endpoint").as< string >();
         auto fcep = fc::ip::endpoint::from_string(lipstr);
         my->listen_endpoint = tcp::endpoint(boost::asio::ip::address_v4::from_string((string)fcep.get_address()), fcep.port());
        #endif
         auto resolver = std::make_shared<tcp::resolver>( std::ref( app().get_io_service() ) );
         if( options.count( "http-server-endpoint" ) ) {
           auto lipstr =  options.at("http-server-endpoint").as< string >();
           auto host = lipstr.substr( 0, lipstr.find(':') );
           auto port = lipstr.substr( host.size()+1, lipstr.size() );
           idump((host)(port));
           tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
           my->listen_endpoint = *resolver->resolve( query);
           ilog("configured http to listen on ${h}:${p}", ("h",host)("p",port));
         }

         // uint32_t addr = my->listen_endpoint->address().to_v4().to_ulong();
         // auto fcep = fc::ip::endpoint (addr,my->listen_endpoint->port());
      }
   }

   void http_plugin::plugin_startup() {
      if(my->listen_endpoint) {

         //my->http_thread = std::make_shared<std::thread>([&](){
            ilog("start processing http thread");
            try {
               my->server.clear_access_channels(websocketpp::log::alevel::all);
               my->server.init_asio(&app().get_io_service()); //&my->http_ios);
               my->server.set_reuse_addr(true);

               my->server.set_http_handler([&](connection_hdl hdl) {
                  auto con = my->server.get_con_from_hdl(hdl);
                  try {
                     //ilog("handle http request: ${url}", ("url",con->get_uri()->str()));
                     //ilog("${body}", ("body", con->get_request_body()));

                     if (!my->access_control_allow_origin.empty()) {
                        con->append_header("Access-Control-Allow-Origin", my->access_control_allow_origin);
                     }
                     if (!my->access_control_allow_headers.empty()) {
                        con->append_header("Access-Control-Allow-Headers", my->access_control_allow_headers);
                     }
                     if (my->access_control_allow_credentials) {
                        con->append_header("Access-Control-Allow-Credentials", "true");
                     }
                     auto body = con->get_request_body();
                     auto resource = con->get_uri()->get_resource();
                     auto handler_itr = my->url_handlers.find(resource);
                     if(handler_itr != my->url_handlers.end()) {
                        handler_itr->second(resource, body, [con,this](int code, string body) {
                           con->set_body(body);
                           con->set_status(websocketpp::http::status_code::value(code));
                        });
                     } else {
                        wlog("404 - not found: ${ep}", ("ep",resource));
                        error_results results{websocketpp::http::status_code::not_found,
                                              "Not Found", "Unknown Endpoint"};
                        con->set_body(fc::json::to_string(results));
                        con->set_status(websocketpp::http::status_code::not_found);
                     }
                  } catch( const fc::exception& e ) {
                     elog( "http: ${e}", ("e",e.to_detail_string()));
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", e.to_detail_string()};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  } catch( const std::exception& e ) {
                     elog( "http: ${e}", ("e",e.what()));
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", e.what()};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  } catch( ... ) {
                     error_results results{websocketpp::http::status_code::internal_server_error,
                                           "Internal Service Error", "unknown exception"};
                     con->set_body(fc::json::to_string(results));
                     con->set_status(websocketpp::http::status_code::internal_server_error);
                  }
               });

               ilog("start listening for http requests");
               my->server.listen(*my->listen_endpoint);
               my->server.start_accept();

           //    my->http_ios.run();
               ilog("http io service exit");
            } catch ( const fc::exception& e ){
               elog( "http: ${e}", ("e",e.to_detail_string()));
            } catch ( const std::exception& e ){
               elog( "http: ${e}", ("e",e.what()));
            } catch (...) {
                elog("error thrown from http io service");
            }
         //});

      }
   }

   void http_plugin::plugin_shutdown() {
     // if(my->http_thread) {
         if(my->server.is_listening())
             my->server.stop_listening();
     //    my->http_ios.stop();
     //    my->http_thread->join();
     //    my->http_thread.reset();
     // }
   }

   void http_plugin::add_handler(const string& url, const url_handler& handler) {
      ilog( "add api url: ${c}", ("c",url) );
      app().get_io_service().post([=](){
        my->url_handlers.insert(std::make_pair(url,handler));
      });
   }
}
<|endoftext|>


<commit_before>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>
#include <unordered_map>

#include <QString>
#include <QTextBoundaryFinder>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "plugins/display_messages.h"
#include "plugins/notify_messages.h"
#include "plugins/edict_messages.h"
#include "plugins/channel_messages.h"
#include "core/core_messages.h"

namespace std
{
	template <>
	struct hash<QString>
	{
		size_t operator()(const QString& v) const
		{
			return std::hash<std::string>()(v.toStdString());
		}
	};
}

inline char CTRL(char c)
{
	//Leave only the lower 5 bits, so the return value is the numeric value
	//of CTRL+key (e.g. CTRL('c') gives you 3, which is the value you get
	//when hitting ctrl-c)
	return c&0x1f;
}

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	for (unsigned char c : s)
		waddch(w, c|(c>0x7f ? A_ALTCHARSET : 0));
}

//This wraps WINDOW pointers so they're be destroyed on exit
class WindowWrapper
{
public:
	WindowWrapper(WINDOW *ww) : w(ww, delwin) {}
	WindowWrapper() {int maxx, maxy; getmaxyx(stdscr, maxy, maxx); w=shared_ptr<WINDOW>(newpad(maxy-1, maxx), delwin); scrollok(get(), TRUE);}
	WINDOW *get() const {return w.get();}
	operator WINDOW*() const {return get();}
	WINDOW& operator*() const {return *w;}
	WINDOW* operator->() const {return get();}
private:
	shared_ptr<WINDOW> w;
};

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	QString channel="default";
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	//WindowWrapper channel_output=newpad(10000, maxx);
	unordered_map<QString, WindowWrapper> channel_windows;
	if (channel_windows["default"]==nullptr)
		return;
	WindowWrapper input_display=newwin(1, maxx-1, maxy-1, 0);
	if (input_display==nullptr)
		return;
	//Be lazy and let the input scroll
	scrollok(input_display, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
			else if (key==WEOF)
			{
				//Quit since we have no more input
				break;
			}
			else
			{
				//This conversion is always valid, since key's
				//only valid values are valid wchar_t values
				//and WEOF, and we know it's not WEOF.
				wchar_t tmp=key;
				input.push_back(QString::fromWCharArray(&tmp, 1));
			}
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==KEY_ENTER)
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
		}
		while (p.has_message())
		{
			message m=p.read();
			if (m.type=="shutdown")
			{
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				if (!s->status)
				{
					if (s->priority>-32000)
						p.write(registration_message::create(s->priority-1, name, s->type));
				}
			}
			else if (m.type=="display")
			{
				auto s=dynamic_cast<display_message *>(m.getdata());
				if (!s)
					continue;
				p.write(m.decrement_priority());

				QString message_channel=s->channel;
				string nick=s->nick.toLocal8Bit().constData();
				string contents=s->contents.toLocal8Bit().constData();

				if (s->channel=="")
					s->channel=channel;

				if (channel_windows.count(message_channel)!=0)
				{
					if(s->subtype==display_message_subtype::NORMAL)
						wprintu(channel_windows[message_channel], "<%s> %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::ME)
						wprintu(channel_windows[message_channel], "* %s %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY)
						wprintu(channel_windows[message_channel], "‼‽ %s\n", contents.c_str());
				}
			}
			else if (m.type=="set_channel")
			{
				auto i=dynamic_cast<set_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					p.write(notify_message::create(channel, "On channel "+channel));
				else
					channel=i->channel;
			}
			else if (m.type=="leave_channel")
			{
				auto i=dynamic_cast<leave_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				channel_windows.erase(i->channel);
			}
			else
				p.write(m.decrement_priority());
		}
		int x,y;
		getyx(channel_windows[channel], y, x);
		pnoutrefresh(channel_windows[channel], max(y-(maxy-1),0), 0, 0,0,maxy-2,maxx-1);
		wmove(input_display, 0, 0);
		wprintu(input_display, "\n%s", input.toLocal8Bit().constData());
		wnoutrefresh(input_display);
		//This doesn't need to run all the time, but we should be able
		//to cope with the screen refreshing at 10Hz
		doupdate();
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(-30000, name, "display"));
	p.write(registration_message::create(-30000, name, "set_channel"));
	p.write(registration_message::create(-30000, name, "leave_channel"));
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<commit_msg>Added workaround for broken terminals<commit_after>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>
#include <unordered_map>
#include <cwctype>

#include <QString>
#include <QTextBoundaryFinder>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "plugins/display_messages.h"
#include "plugins/notify_messages.h"
#include "plugins/edict_messages.h"
#include "plugins/channel_messages.h"
#include "core/core_messages.h"

namespace std
{
	template <>
	struct hash<QString>
	{
		size_t operator()(const QString& v) const
		{
			return std::hash<std::string>()(v.toStdString());
		}
	};
}

inline char CTRL(char c)
{
	//Leave only the lower 5 bits, so the return value is the numeric value
	//of CTRL+key (e.g. CTRL('c') gives you 3, which is the value you get
	//when hitting ctrl-c)
	return c&0x1f;
}

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	wstring wstr=QString::fromLocal8Bit(s.c_str()).toStdWString();
	waddwstr(w, wstr.c_str());
}

//This wraps WINDOW pointers so they're be destroyed on exit
class WindowWrapper
{
public:
	WindowWrapper(WINDOW *ww) : w(ww, delwin) {}
	WindowWrapper() {int maxx, maxy; getmaxyx(stdscr, maxy, maxx); w=shared_ptr<WINDOW>(newpad(maxy-1, maxx), delwin); scrollok(get(), TRUE);}
	WINDOW *get() const {return w.get();}
	operator WINDOW*() const {return get();}
	WINDOW& operator*() const {return *w;}
	WINDOW* operator->() const {return get();}
private:
	shared_ptr<WINDOW> w;
};

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	QString channel="default";
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	//WindowWrapper channel_output=newpad(10000, maxx);
	unordered_map<QString, WindowWrapper> channel_windows;
	if (channel_windows["default"]==nullptr)
		return;
	WindowWrapper input_display=newwin(1, maxx-1, maxy-1, 0);
	if (input_display==nullptr)
		return;
	//Be lazy and let the input scroll
	scrollok(input_display, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
			else if (key==(unsigned char)CTRL('U'))
			{
				input="";
			}
			else if (key==(unsigned char)CTRL('H'))
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==WEOF)
			{
				//Quit since we have no more input
				break;
			}
			else
			{
				//This conversion is always valid, since key's
				//only valid values are valid wchar_t values
				//and WEOF, and we know it's not WEOF.
				wchar_t tmp=key;
				input.push_back(QString::fromWCharArray(&tmp, 1));
			}
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==KEY_ENTER)
			{
				p.write(raw_edict_message::create(input,channel));
				input="";
			}
		}
		while (p.has_message())
		{
			message m=p.read();
			if (m.type=="shutdown")
			{
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				if (!s->status)
				{
					if (s->priority>-32000)
						p.write(registration_message::create(s->priority-1, name, s->type));
				}
			}
			else if (m.type=="display")
			{
				auto s=dynamic_cast<display_message *>(m.getdata());
				if (!s)
					continue;
				p.write(m.decrement_priority());

				QString message_channel=s->channel;
				string nick=s->nick.toLocal8Bit().constData();
				string contents=s->contents.toLocal8Bit().constData();

				if (s->channel=="")
					s->channel=channel;

				if (channel_windows.count(message_channel)!=0)
				{
					if(s->subtype==display_message_subtype::NORMAL)
						wprintu(channel_windows[message_channel], "<%s> %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::ME)
						wprintu(channel_windows[message_channel], "* %s %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY)
						wprintu(channel_windows[message_channel], "‼‽ %s\n", contents.c_str());
				}
			}
			else if (m.type=="set_channel")
			{
				auto i=dynamic_cast<set_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					p.write(notify_message::create(channel, "On channel "+channel));
				else
					channel=i->channel;
			}
			else if (m.type=="leave_channel")
			{
				auto i=dynamic_cast<leave_channel *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				channel_windows.erase(i->channel);
			}
			else
				p.write(m.decrement_priority());
		}
		int x,y;
		getyx(channel_windows[channel], y, x);
		pnoutrefresh(channel_windows[channel], max(y-(maxy-1),0), 0, 0,0,maxy-2,maxx-1);
		wmove(input_display, 0, 0);
		wprintu(input_display, "\n%s", input.toLocal8Bit().constData());
		wnoutrefresh(input_display);
		//This doesn't need to run all the time, but we should be able
		//to cope with the screen refreshing at 10Hz
		doupdate();
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(-30000, name, "display"));
	p.write(registration_message::create(-30000, name, "set_channel"));
	p.write(registration_message::create(-30000, name, "leave_channel"));
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "ui/gfx/gl/gl_bindings.h"
#include "ui/gfx/gl/gl_implementation.h"

namespace gfx {
namespace {

// TODO(piman): it should be Desktop GL marshalling from double to float. Today
// on native GLES, we do float->double->float.
void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
  glClearDepthf(static_cast<GLclampf>(depth));
}

void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
                                                    GLclampd z_far) {
  glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
}

// Load a library, printing an error message on failure.
base::NativeLibrary LoadLibrary(const FilePath& filename) {
  std::string error;
  base::NativeLibrary library = base::LoadNativeLibrary(filename,
                                                        &error);
  if (!library) {
    VLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
    return NULL;
  }
  return library;
}

base::NativeLibrary LoadLibrary(const char* filename) {
  return LoadLibrary(FilePath(filename));
}

// TODO(backer): Find a more principled (less heavy handed) way to prevent a
// race in the bindings initialization.
#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
base::Lock g_lock;
#endif

}  // namespace anonymous

bool InitializeGLBindings(GLImplementation implementation) {
#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
  base::AutoLock locked(g_lock);
#endif
  // Prevent reinitialization with a different implementation. Once the gpu
  // unit tests have initialized with kGLImplementationMock, we don't want to
  // later switch to another GL implementation.
  if (GetGLImplementation() != kGLImplementationNone)
    return true;

  switch (implementation) {
#if !defined(USE_WAYLAND)
    case kGLImplementationOSMesaGL: {
      FilePath module_path;
      if (!PathService::Get(base::DIR_MODULE, &module_path)) {
        LOG(ERROR) << "PathService::Get failed.";
        return false;
      }

      base::NativeLibrary library = LoadLibrary(
          module_path.Append("libosmesa.so"));
      if (!library)
        return false;

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "OSMesaGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "OSMesaGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationOSMesaGL);

      InitializeGLBindingsGL();
      InitializeGLBindingsOSMESA();
      break;
    }
    case kGLImplementationDesktopGL: {
      base::NativeLibrary library = LoadLibrary("libGL.so.1");
      if (!library)
        return false;

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "glXGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "glxGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationDesktopGL);

      InitializeGLBindingsGL();
      InitializeGLBindingsGLX();
      break;
    }
#endif  // !defined(USE_WAYLAND)
    case kGLImplementationEGLGLES2: {
      base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so");
      if (!gles_library)
        return false;
      base::NativeLibrary egl_library = LoadLibrary("libEGL.so");
      if (!egl_library) {
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  egl_library, "eglGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "eglGetProcAddress not found.";
        base::UnloadNativeLibrary(egl_library);
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(egl_library);
      AddGLNativeLibrary(gles_library);
      SetGLImplementation(kGLImplementationEGLGLES2);

      InitializeGLBindingsGL();
      InitializeGLBindingsEGL();

      // These two functions take single precision float rather than double
      // precision float parameters in GLES.
      ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
      ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
      break;
    }
    case kGLImplementationMockGL: {
      SetGLGetProcAddressProc(GetMockGLProcAddress);
      SetGLImplementation(kGLImplementationMockGL);
      InitializeGLBindingsGL();
      break;
    }
    default:
      return false;
  }

  return true;
}

void InitializeDebugGLBindings() {
  InitializeDebugGLBindingsEGL();
  InitializeDebugGLBindingsGL();
#if !defined(USE_WAYLAND)
  InitializeDebugGLBindingsGLX();
  InitializeDebugGLBindingsOSMESA();
#endif
}

}  // namespace gfx
<commit_msg>Wrap Lock in a LazyInstance.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "ui/gfx/gl/gl_bindings.h"
#include "ui/gfx/gl/gl_implementation.h"

namespace gfx {
namespace {

// TODO(piman): it should be Desktop GL marshalling from double to float. Today
// on native GLES, we do float->double->float.
void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
  glClearDepthf(static_cast<GLclampf>(depth));
}

void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
                                                    GLclampd z_far) {
  glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
}

// Load a library, printing an error message on failure.
base::NativeLibrary LoadLibrary(const FilePath& filename) {
  std::string error;
  base::NativeLibrary library = base::LoadNativeLibrary(filename,
                                                        &error);
  if (!library) {
    VLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
    return NULL;
  }
  return library;
}

base::NativeLibrary LoadLibrary(const char* filename) {
  return LoadLibrary(FilePath(filename));
}

// TODO(backer): Find a more principled (less heavy handed) way to prevent a
// race in the bindings initialization.
#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
base::LazyInstance<base::Lock> g_lock(base::LINKER_INITIALIZED);
#endif

}  // namespace anonymous

bool InitializeGLBindings(GLImplementation implementation) {
#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
  base::AutoLock locked(g_lock.Get());
#endif
  // Prevent reinitialization with a different implementation. Once the gpu
  // unit tests have initialized with kGLImplementationMock, we don't want to
  // later switch to another GL implementation.
  if (GetGLImplementation() != kGLImplementationNone)
    return true;

  switch (implementation) {
#if !defined(USE_WAYLAND)
    case kGLImplementationOSMesaGL: {
      FilePath module_path;
      if (!PathService::Get(base::DIR_MODULE, &module_path)) {
        LOG(ERROR) << "PathService::Get failed.";
        return false;
      }

      base::NativeLibrary library = LoadLibrary(
          module_path.Append("libosmesa.so"));
      if (!library)
        return false;

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "OSMesaGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "OSMesaGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationOSMesaGL);

      InitializeGLBindingsGL();
      InitializeGLBindingsOSMESA();
      break;
    }
    case kGLImplementationDesktopGL: {
      base::NativeLibrary library = LoadLibrary("libGL.so.1");
      if (!library)
        return false;

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  library, "glXGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "glxGetProcAddress not found.";
        base::UnloadNativeLibrary(library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(library);
      SetGLImplementation(kGLImplementationDesktopGL);

      InitializeGLBindingsGL();
      InitializeGLBindingsGLX();
      break;
    }
#endif  // !defined(USE_WAYLAND)
    case kGLImplementationEGLGLES2: {
      base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so");
      if (!gles_library)
        return false;
      base::NativeLibrary egl_library = LoadLibrary("libEGL.so");
      if (!egl_library) {
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

      GLGetProcAddressProc get_proc_address =
          reinterpret_cast<GLGetProcAddressProc>(
              base::GetFunctionPointerFromNativeLibrary(
                  egl_library, "eglGetProcAddress"));
      if (!get_proc_address) {
        LOG(ERROR) << "eglGetProcAddress not found.";
        base::UnloadNativeLibrary(egl_library);
        base::UnloadNativeLibrary(gles_library);
        return false;
      }

      SetGLGetProcAddressProc(get_proc_address);
      AddGLNativeLibrary(egl_library);
      AddGLNativeLibrary(gles_library);
      SetGLImplementation(kGLImplementationEGLGLES2);

      InitializeGLBindingsGL();
      InitializeGLBindingsEGL();

      // These two functions take single precision float rather than double
      // precision float parameters in GLES.
      ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
      ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
      break;
    }
    case kGLImplementationMockGL: {
      SetGLGetProcAddressProc(GetMockGLProcAddress);
      SetGLImplementation(kGLImplementationMockGL);
      InitializeGLBindingsGL();
      break;
    }
    default:
      return false;
  }

  return true;
}

void InitializeDebugGLBindings() {
  InitializeDebugGLBindingsEGL();
  InitializeDebugGLBindingsGL();
#if !defined(USE_WAYLAND)
  InitializeDebugGLBindingsGLX();
  InitializeDebugGLBindingsOSMESA();
#endif
}

}  // namespace gfx
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

using namespace std;

void Load(const string& file, string s[2])
{
    fstream stream(file, ios_base::in);
    if (stream.good())
    {
        cout << "Loading " << file << "..." << endl;
        string line; unsigned int x = 0;
        while (getline(stream ,line))
        {
            if (line.compare("")) { s[x] = line; x++; }
        }
    }
    else
    {
        cout << "Not loading " << file << "..." << endl;
    }
}

int main()
{
    string s[2];
    Load("talent1.txt", s);
    cout << s[0] << endl;
    cout << s[1] << endl;
    return 0;
}<commit_msg>finished<commit_after>#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

void Load(const string& file, string s[2])
{
    fstream stream(file.c_str(), ios_base::in);
    if (stream.good())
    {
        cout << "Loading " << file << "..." << endl;
        string line; unsigned int x = 0;
        while (getline(stream ,line))
        { if (line.compare("")) { s[x] = line; x++; } }
    }
    else cout << "Unable to load " << file << "..." << endl << endl;
}

void Talent(unsigned int x)
{
    stringstream oss;
    string data[2];
    oss << "talent" << x << ".txt";
    Load(oss.str(), data);
    if (!data[0].compare("")) return;
    cout << oss.str() << ":" << endl;
    cout << "\t~ " << data[0] << endl;
    cout << "\t~ " << data[1] << endl;
    oss.clear();
    cout << "Results : ";
    for (unsigned int i = (unsigned int) data[0].length(); i > 0; i--)
    {
        string temp = data[0].substr(0, i);
        if (data[1].rfind(temp) != string::npos && temp[temp.length()-1] == data[1][data[1].length()-1])
        {
            cout << temp << " " << temp.length() << endl << endl;
            return;
        }
    }
    cout << "0" << endl << endl;
}

int main(int argc, char* argv[])
{
    for (unsigned int x = 1; x < 12; x++)
    { Talent(x); }
    return 0;
}<|endoftext|>