<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

// mapnik
#include <mapnik/mapped_memory_cache.hpp>

// boost
#include <boost/assert.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/filesystem/operations.hpp>

namespace mapnik
{

boost::unordered_map<std::string, mapped_region_ptr> mapped_memory_cache::cache_;

bool mapped_memory_cache::insert (std::string const& uri, mapped_region_ptr mem)
{
#ifdef MAPNIK_THREADSAFE
    mutex::scoped_lock lock(mutex_);
#endif
    return cache_.insert(std::make_pair(uri,mem)).second;
}

boost::optional<mapped_region_ptr> mapped_memory_cache::find(std::string const& uri, bool update_cache)
{
#ifdef MAPNIK_THREADSAFE
    mutex::scoped_lock lock(mutex_);
#endif
    typedef boost::unordered_map<std::string, mapped_region_ptr>::const_iterator iterator_type;
    boost::optional<mapped_region_ptr> result;
    iterator_type itr = cache_.find(uri);
    if (itr != cache_.end())
    {
        result.reset(itr->second);
        return result;
    }

    boost::filesystem::path path(uri);
    if (exists(path))
    {
        try
        {
            file_mapping mapping(uri.c_str(),read_only);
            mapped_region_ptr region(new mapped_region(mapping,read_only));

            result.reset(region);

            if (update_cache)
            {
                cache_.insert(std::make_pair(uri,*result));
            }
            return result;
        }
        catch (...)
        {
            std::cerr << "Exception caught while loading mapping memory file: " << uri << std::endl;
        }
    }
    else
    {
        std::cerr << "### WARNING Memory region does not exist file:" << uri << std::endl;
    }
    return result;
}

#ifdef MAPNIK_THREADSAFE
boost::mutex mapped_memory_cache::mutex_;
#endif

}
<commit_msg>don't warn if mmap's file is missing (shapefile does not have an index)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

// mapnik
#include <mapnik/mapped_memory_cache.hpp>

// boost
#include <boost/assert.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/filesystem/operations.hpp>

namespace mapnik
{

boost::unordered_map<std::string, mapped_region_ptr> mapped_memory_cache::cache_;

bool mapped_memory_cache::insert (std::string const& uri, mapped_region_ptr mem)
{
#ifdef MAPNIK_THREADSAFE
    mutex::scoped_lock lock(mutex_);
#endif
    return cache_.insert(std::make_pair(uri,mem)).second;
}

boost::optional<mapped_region_ptr> mapped_memory_cache::find(std::string const& uri, bool update_cache)
{
#ifdef MAPNIK_THREADSAFE
    mutex::scoped_lock lock(mutex_);
#endif
    typedef boost::unordered_map<std::string, mapped_region_ptr>::const_iterator iterator_type;
    boost::optional<mapped_region_ptr> result;
    iterator_type itr = cache_.find(uri);
    if (itr != cache_.end())
    {
        result.reset(itr->second);
        return result;
    }

    boost::filesystem::path path(uri);
    if (exists(path))
    {
        try
        {
            file_mapping mapping(uri.c_str(),read_only);
            mapped_region_ptr region(new mapped_region(mapping,read_only));

            result.reset(region);

            if (update_cache)
            {
                cache_.insert(std::make_pair(uri,*result));
            }
            return result;
        }
        catch (...)
        {
            std::cerr << "Exception caught while loading mapping memory file: " << uri << std::endl;
        }
    }
    /*else
    {
        std::cerr << "### WARNING Memory region does not exist file: " << uri << std::endl;
    }*/
    return result;
}

#ifdef MAPNIK_THREADSAFE
boost::mutex mapped_memory_cache::mutex_;
#endif

}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow 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 "tensorflow/core/grappler/op_types.h"

namespace tensorflow {
namespace grappler {

bool IsConcat(const NodeDef& node) {
  const auto op = node.op();
  return op == "Concat" || op == "ConcatV2";
}

bool IsDequeueOp(const NodeDef& node) {
  static const std::set<std::string> dequeue_ops = {
      "QueueDequeueManyV2", "QueueDequeueMany", "QueueDequeueV2",
      "QueueDequeue"};
  return dequeue_ops.count(node.op()) > 0;
}

bool IsPlaceholder(const NodeDef& node) {
  const auto op = node.op();
  return op == "Placeholder" || op == "PlaceholderV2";
}

bool IsTranspose(const NodeDef& node) {
  const auto op = node.op();
  return op == "Transpose";
}

bool IsVariable(const NodeDef& node) {
  const auto op = node.op();
  return op == "Variable" || op == "VariableV2" || op == "AutoReloadVariable" ||
         op == "VarHandleOp";
}

bool IsMerge(const NodeDef& node) {
  const auto op = node.op();
  return op == "Merge";
}

}  // end namespace grappler
}  // end namespace tensorflow
<commit_msg>Improved support for variables<commit_after>/* Copyright 2017 The TensorFlow 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 "tensorflow/core/grappler/op_types.h"

namespace tensorflow {
namespace grappler {

bool IsConcat(const NodeDef& node) {
  const auto op = node.op();
  return op == "Concat" || op == "ConcatV2";
}

bool IsDequeueOp(const NodeDef& node) {
  static const std::set<std::string> dequeue_ops = {
      "QueueDequeueManyV2", "QueueDequeueMany", "QueueDequeueV2",
      "QueueDequeue"};
  return dequeue_ops.count(node.op()) > 0;
}

bool IsPlaceholder(const NodeDef& node) {
  const auto op = node.op();
  return op == "Placeholder" || op == "PlaceholderV2";
}

bool IsTranspose(const NodeDef& node) {
  const auto op = node.op();
  return op == "Transpose";
}

bool IsVariable(const NodeDef& node) {
  const auto op = node.op();
  return op == "Variable" || op == "VariableV2" || op == "AutoReloadVariable" ||
         op == "VarHandleOp" || op == "TemporaryVariable";
}

bool IsMerge(const NodeDef& node) {
  const auto op = node.op();
  return op == "Merge";
}

}  // end namespace grappler
}  // end namespace tensorflow
<|endoftext|>


<commit_before>#ifndef MINIMAT_UTIL_STREAM_HPP
#define MINIMAT_UTIL_STREAM_HPP

#include <deque>

namespace miniMAT {
    namespace util {
        template <typename ElementType>
        struct Stream {
            Stream() {
                stream = std::deque<ElementType>();
            }

            template <typename Function, typename ...Args>
            void Take(Function f, Args ...params) {
                // Call user-provided function
                f(params...);

                // Advance item in stream
                stream.pop_front();
            }

            void PutBack(const ElementType& t) {
                stream.push_front(t);
            }

            void Add(const ElementType& t) {
                stream.push_back(t);
            }

            ElementType Current() {
                return stream.front();
            }

        private:
            std::deque<ElementType> stream;
        };
    }
}

#endif<commit_msg>Default constructor should be fine here<commit_after>#ifndef MINIMAT_UTIL_STREAM_HPP
#define MINIMAT_UTIL_STREAM_HPP

#include <deque>

namespace miniMAT {
    namespace util {
        template <typename ElementType>
        struct Stream {
            template <typename Function, typename ...Args>
            void Take(Function f, Args ...params) {
                // Call user-provided function
                f(params...);

                // Advance item in stream
                stream.pop_front();
            }

            void PutBack(const ElementType& t) {
                stream.push_front(t);
            }

            void Add(const ElementType& t) {
                stream.push_back(t);
            }

            ElementType Current() {
                return stream.front();
            }

        private:
            std::deque<ElementType> stream = std::deque<ElementType>();
        };
    }
}

#endif<|endoftext|>


<commit_before>/***************************************************************************
 *                                                                         *
 * Copyright (C) 2007-2013 by Johan De Taeye, frePPLe bvba                 *
 *                                                                         *
 * This library 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 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 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 <http://www.gnu.org/licenses/>.                             *
 *                                                                         *
 ***************************************************************************/

#define FREPPLE_CORE
#include "frepple/model.h"

namespace frepple
{

DECLARE_EXPORT const MetaCategory* ResourceSkill::metadata;

int ResourceSkill::initialize()
{
  // Initialize the metadata
  metadata = new MetaCategory("resourceskill", "resourceskills", MetaCategory::ControllerDefault, writer);
  const_cast<MetaCategory*>(metadata)->registerClass(
    "resourceskill","resourceskill",true,Object::createDefault<ResourceSkill>
  );

  // Initialize the Python class
  PythonType& x = FreppleCategory<ResourceSkill>::getType();
  x.setName("resourceskill");
  x.setDoc("frePPLe resourceskill");
  x.supportgetattro();
  x.supportsetattro();
  x.supportcreate(create);
  x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
  const_cast<MetaCategory*>(ResourceSkill::metadata)->pythonClass = x.type_object();
  return x.typeReady();
}

DECLARE_EXPORT ResourceSkill::ResourceSkill(Skill* s, Resource* r, int u)
{
  setSkill(s);
  setResource(r);
  setPriority(u);
  initType(metadata);
  try { validate(ADD); }
  catch (...)
  {
    if (getSkill()) getSkill()->resources.erase(this);
    if (getResource()) getResource()->skills.erase(this);
    resetReferenceCount();
    throw;
  }
}

DECLARE_EXPORT ResourceSkill::ResourceSkill(Skill* s, Resource* r, int u, DateRange e)
{
  setSkill(s);
  setResource(r);
  setPriority(u);
  setEffective(e);
  initType(metadata);
  try { validate(ADD); }
  catch (...)
  {
    if (getSkill()) getSkill()->resources.erase(this);
    if (getResource()) getResource()->skills.erase(this);
    resetReferenceCount();
    throw;
  }
}

void ResourceSkill::writer(const MetaCategory* c, Serializer* o)
{
  bool first = true;
  for (Resource::iterator i = Resource::begin(); i != Resource::end(); ++i)
    for (Resource::skilllist::const_iterator j = i->getSkills().begin(); j != i->getSkills().end(); ++j)
    {
      if (first)
      {
        o->BeginList(Tags::tag_resourceskills);
        first = false;
      }
      // We use the FULL mode, to force the resource skills being written regardless
      // of the depth in the XML tree.
      o->writeElement(Tags::tag_resourceskill, &*j, FULL);
    }
  if (!first) o->EndList(Tags::tag_resourceskills);
}

DECLARE_EXPORT void ResourceSkill::writeElement(Serializer* o, const Keyword& tag, mode m) const
{
  // If the resourceskill has already been saved, no need to repeat it again
  // A 'reference' to a load is not useful to be saved.
  if (m == REFERENCE) return;
  assert(m != NOHEAD && m != NOHEADTAIL);

  o->BeginObject(tag);

  // If the resourceskill is defined inside of a resource tag, we don't need to save
  // the resource. Otherwise we do save it...
  if (!dynamic_cast<Resource*>(o->getPreviousObject()))
    o->writeElement(Tags::tag_resource, getResource());

  // If the resourceskill is defined inside of a skill tag, we don't need to save
  // the skill. Otherwise we do save it...
  if (!dynamic_cast<Skill*>(o->getPreviousObject()))
    o->writeElement(Tags::tag_skill, getSkill());

  // Write the priority and effective daterange
  if (getPriority()!=1) o->writeElement(Tags::tag_priority, getPriority());
  if (getEffective().getStart() != Date::infinitePast)
    o->writeElement(Tags::tag_effective_start, getEffective().getStart());
  if (getEffective().getEnd() != Date::infiniteFuture)
    o->writeElement(Tags::tag_effective_end, getEffective().getEnd());

  // Write source field
  o->writeElement(Tags::tag_source, getSource());

  // Write the custom fields
  PythonDictionary::write(o, getDict());

  // Write the tail
  if (m != NOHEADTAIL && m != NOTAIL) o->EndObject(tag);
}

DECLARE_EXPORT void ResourceSkill::beginElement(XMLInput& pIn, const Attribute& pAttr)
{
  if (pAttr.isA (Tags::tag_resource))
    pIn.readto( Resource::reader(Resource::metadata,pIn.getAttributes()) );
  else if (pAttr.isA (Tags::tag_skill))
    pIn.readto( Skill::reader(Skill::metadata,pIn.getAttributes()) );
  else
    PythonDictionary::read(pIn, pAttr, getDict());
}

DECLARE_EXPORT void ResourceSkill::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
{
  if (pAttr.isA (Tags::tag_resource))
  {
    Resource *r = dynamic_cast<Resource*>(pIn.getPreviousObject());
    if (r) setResource(r);
    else throw LogicException("Incorrect object type during read operation");
  }
  else if (pAttr.isA (Tags::tag_skill))
  {
    Skill *s = dynamic_cast<Skill*>(pIn.getPreviousObject());
    if (s) setSkill(s);
    else throw LogicException("Incorrect object type during read operation");
  }
  else if (pAttr.isA(Tags::tag_priority))
    setPriority(pElement.getInt());
  else if (pAttr.isA(Tags::tag_effective_end))
    setEffectiveEnd(pElement.getDate());
  else if (pAttr.isA(Tags::tag_effective_start))
    setEffectiveStart(pElement.getDate());
  else if (pAttr.isA(Tags::tag_source))
    setSource(pElement.getString());
  else if (pAttr.isA(Tags::tag_action))
  {
    delete static_cast<Action*>(pIn.getUserArea());
    pIn.setUserArea(
      new Action(MetaClass::decodeAction(pElement.getString().c_str()))
    );
  }
  else if (pIn.isObjectEnd())
  {
    // The resourceskill data is now all read in. See if it makes sense now...
    Action a = pIn.getUserArea() ?
        *static_cast<Action*>(pIn.getUserArea()) :
        ADD_CHANGE;
    delete static_cast<Action*>(pIn.getUserArea());
    try { validate(a); }
    catch (...)
    {
      delete this;
      throw;
    }
  }
}

DECLARE_EXPORT PyObject* ResourceSkill::getattro(const Attribute& attr)
{
  if (attr.isA(Tags::tag_resource))
    return PythonObject(getResource());
  if (attr.isA(Tags::tag_skill))
    return PythonObject(getSkill());
  if (attr.isA(Tags::tag_priority))
    return PythonObject(getPriority());
  if (attr.isA(Tags::tag_effective_end))
    return PythonObject(getEffective().getEnd());
  if (attr.isA(Tags::tag_effective_start))
    return PythonObject(getEffective().getStart());
  if (attr.isA(Tags::tag_source))
    return PythonObject(getSource());
  return NULL;
}

DECLARE_EXPORT int ResourceSkill::setattro(const Attribute& attr, const PythonObject& field)
{
  if (attr.isA(Tags::tag_resource))
  {
    if (!field.check(Resource::metadata))
    {
      PyErr_SetString(PythonDataException, "resourceskill resource must be of type resource");
      return -1;
    }
    Resource* y = static_cast<Resource*>(static_cast<PyObject*>(field));
    setResource(y);
  }
  else if (attr.isA(Tags::tag_skill))
  {
    if (!field.check(Skill::metadata))
    {
      PyErr_SetString(PythonDataException, "resourceskill skill must be of type skill");
      return -1;
    }
    Skill* y = static_cast<Skill*>(static_cast<PyObject*>(field));
    setSkill(y);
  }
  else if (attr.isA(Tags::tag_priority))
    setPriority(field.getInt());
  else if (attr.isA(Tags::tag_effective_end))
    setEffectiveEnd(field.getDate());
  else if (attr.isA(Tags::tag_effective_start))
    setEffectiveStart(field.getDate());
  else if (attr.isA(Tags::tag_source))
    setSource(field.getString());
  else
    return -1;
  return 0;
}

/** @todo this method implementation is not generic enough and not extendible by subclasses. */
PyObject* ResourceSkill::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds)
{
  try
  {
    // Pick up the skill
    PyObject* skill = PyDict_GetItemString(kwds,"skill");
    if (!PyObject_TypeCheck(skill, Skill::metadata->pythonClass))
      throw DataException("resourceskill skill must be of type skill");

    // Pick up the resource
    PyObject* res = PyDict_GetItemString(kwds,"resource");
    if (!PyObject_TypeCheck(res, Resource::metadata->pythonClass))
      throw DataException("resourceskill resource must be of type resource");

    // Pick up the priority
    PyObject* q1 = PyDict_GetItemString(kwds,"priority");
    int q2 = q1 ? PythonObject(q1).getInt() : 1;

    // Pick up the effective dates
    DateRange eff;
    PyObject* eff_start = PyDict_GetItemString(kwds,"effective_start");
    if (eff_start)
    {
      PythonObject d(eff_start);
      eff.setStart(d.getDate());
    }
    PyObject* eff_end = PyDict_GetItemString(kwds,"effective_end");
    if (eff_end)
    {
      PythonObject d(eff_end);
      eff.setEnd(d.getDate());
    }

    // Create the resourceskill
    ResourceSkill *l = new ResourceSkill(
      static_cast<Skill*>(skill),
      static_cast<Resource*>(res),
      q2, eff
    );

    // Iterate over extra keywords, and set attributes.   @todo move this responsibility to the readers...
    if (l)
    {
      PyObject *key, *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(kwds, &pos, &key, &value))
      {
        PythonObject field(value);
        PyObject* key_utf8 = PyUnicode_AsUTF8String(key);
        Attribute attr(PyBytes_AsString(key_utf8));
        Py_DECREF(key_utf8);
        if (!attr.isA(Tags::tag_effective_end) && !attr.isA(Tags::tag_effective_start)
          && !attr.isA(Tags::tag_skill) && !attr.isA(Tags::tag_resource)
          && !attr.isA(Tags::tag_priority) && !attr.isA(Tags::tag_type)
          && !attr.isA(Tags::tag_action))
        {
          int result = l->setattro(attr, field);
          if (result && !PyErr_Occurred())
            PyErr_Format(PyExc_AttributeError,
                "attribute '%S' on '%s' can't be updated",
                key, Py_TYPE(l)->tp_name);
        }
      };
    }

    // Return the object
    Py_INCREF(l);
    return static_cast<PyObject*>(l);
  }
  catch (...)
  {
    PythonType::evalException();
    return NULL;
  }
}

DECLARE_EXPORT void ResourceSkill::validate(Action action)
{
  // Catch null operation and resource pointers
  Skill *skill = getSkill();
  Resource *res = getResource();
  if (!skill || !res)
  {
    // Invalid load model
    if (!skill && !res)
      throw DataException("Missing resource and kill on a resourceskill");
    else if (!skill)
      throw DataException("Missing skill on a resourceskill on resource '"
          + res->getName() + "'");
    else if (!res)
      throw DataException("Missing resource on a resourceskill on skill '"
          + skill->getName() + "'");
  }

  // Check if a resourceskill with 1) identical resource, 2) identical skill and
  // 3) overlapping effectivity dates already exists
  Skill::resourcelist::const_iterator i = skill->getResources().begin();
  for (; i != skill->getResources().end(); ++i)
    if (i->getResource() == res
        && i->getEffective().overlap(getEffective())
        && &*i != this)
      break;

  // Apply the appropriate action
  switch (action)
  {
    case ADD:
      if (i != skill->getResources().end())
      {
        throw DataException("Resourceskill of '" + res->getName() + "' and '"
            + skill->getName() + "' already exists");
      }
      break;
    case CHANGE:
      throw DataException("Can't update a resourceskill");
    case ADD_CHANGE:
      // ADD is handled in the code after the switch statement
      if (i == skill->getResources().end()) break;
      throw DataException("Can't update a resourceskill");
    case REMOVE:
      // This resourceskill was only used temporarily during the reading process
      delete this;
      if (i == skill->getResources().end())
        // Nothing to delete
        throw DataException("Can't remove nonexistent resourceskill of '"
            + res->getName() + "' and '" + skill->getName() + "'");
      delete &*i;
      return;
  }
}

int ResourceSkillIterator::initialize()
{
  // Initialize the type
  PythonType& x = PythonExtension<ResourceSkillIterator>::getType();
  x.setName("resourceSkillIterator");
  x.setDoc("frePPLe iterator for resource skills");
  x.supportiter();
  return x.typeReady();
}

PyObject* ResourceSkillIterator::iternext()
{
  PyObject* result;
  if (res)
  {
    // Iterate over skills on a resource
    if (ir == res->getSkills().end()) return NULL;
    result = const_cast<ResourceSkill*>(&*ir);
    ++ir;
  }
  else
  {
    // Iterate over resources having a skill
    if (is == skill->getResources().end()) return NULL;
    result = const_cast<ResourceSkill*>(&*is);
    ++is;
  }
  Py_INCREF(result);
  return result;
}

}
<commit_msg>adding destructor for resourceskill<commit_after>/***************************************************************************
 *                                                                         *
 * Copyright (C) 2007-2013 by Johan De Taeye, frePPLe bvba                 *
 *                                                                         *
 * This library 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 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 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 <http://www.gnu.org/licenses/>.                             *
 *                                                                         *
 ***************************************************************************/

#define FREPPLE_CORE
#include "frepple/model.h"

namespace frepple
{

DECLARE_EXPORT const MetaCategory* ResourceSkill::metadata;

int ResourceSkill::initialize()
{
  // Initialize the metadata
  metadata = new MetaCategory("resourceskill", "resourceskills", MetaCategory::ControllerDefault, writer);
  const_cast<MetaCategory*>(metadata)->registerClass(
    "resourceskill","resourceskill",true,Object::createDefault<ResourceSkill>
  );

  // Initialize the Python class
  PythonType& x = FreppleCategory<ResourceSkill>::getType();
  x.setName("resourceskill");
  x.setDoc("frePPLe resourceskill");
  x.supportgetattro();
  x.supportsetattro();
  x.supportcreate(create);
  x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
  const_cast<MetaCategory*>(ResourceSkill::metadata)->pythonClass = x.type_object();
  return x.typeReady();
}

DECLARE_EXPORT ResourceSkill::ResourceSkill(Skill* s, Resource* r, int u)
{
  setSkill(s);
  setResource(r);
  setPriority(u);
  initType(metadata);
  try { validate(ADD); }
  catch (...)
  {
    if (getSkill()) getSkill()->resources.erase(this);
    if (getResource()) getResource()->skills.erase(this);
    resetReferenceCount();
    throw;
  }
}

DECLARE_EXPORT ResourceSkill::ResourceSkill(Skill* s, Resource* r, int u, DateRange e)
{
  setSkill(s);
  setResource(r);
  setPriority(u);
  setEffective(e);
  initType(metadata);
  try { validate(ADD); }
  catch (...)
  {
    if (getSkill()) getSkill()->resources.erase(this);
    if (getResource()) getResource()->skills.erase(this);
    resetReferenceCount();
    throw;
  }
}

DECLARE_EXPORT ResourceSkill::~ResourceSkill()
{
  // Delete the associated from the related objects
  if (getResource()) getResource()->skills.erase(this);
  if (getSkill()) getSkill()->resources.erase(this);
}

void ResourceSkill::writer(const MetaCategory* c, Serializer* o)
{
  bool first = true;
  for (Resource::iterator i = Resource::begin(); i != Resource::end(); ++i)
    for (Resource::skilllist::const_iterator j = i->getSkills().begin(); j != i->getSkills().end(); ++j)
    {
      if (first)
      {
        o->BeginList(Tags::tag_resourceskills);
        first = false;
      }
      // We use the FULL mode, to force the resource skills being written regardless
      // of the depth in the XML tree.
      o->writeElement(Tags::tag_resourceskill, &*j, FULL);
    }
  if (!first) o->EndList(Tags::tag_resourceskills);
}

DECLARE_EXPORT void ResourceSkill::writeElement(Serializer* o, const Keyword& tag, mode m) const
{
  // If the resourceskill has already been saved, no need to repeat it again
  // A 'reference' to a load is not useful to be saved.
  if (m == REFERENCE) return;
  assert(m != NOHEAD && m != NOHEADTAIL);

  o->BeginObject(tag);

  // If the resourceskill is defined inside of a resource tag, we don't need to save
  // the resource. Otherwise we do save it...
  if (!dynamic_cast<Resource*>(o->getPreviousObject()))
    o->writeElement(Tags::tag_resource, getResource());

  // If the resourceskill is defined inside of a skill tag, we don't need to save
  // the skill. Otherwise we do save it...
  if (!dynamic_cast<Skill*>(o->getPreviousObject()))
    o->writeElement(Tags::tag_skill, getSkill());

  // Write the priority and effective daterange
  if (getPriority()!=1) o->writeElement(Tags::tag_priority, getPriority());
  if (getEffective().getStart() != Date::infinitePast)
    o->writeElement(Tags::tag_effective_start, getEffective().getStart());
  if (getEffective().getEnd() != Date::infiniteFuture)
    o->writeElement(Tags::tag_effective_end, getEffective().getEnd());

  // Write source field
  o->writeElement(Tags::tag_source, getSource());

  // Write the custom fields
  PythonDictionary::write(o, getDict());

  // Write the tail
  if (m != NOHEADTAIL && m != NOTAIL) o->EndObject(tag);
}

DECLARE_EXPORT void ResourceSkill::beginElement(XMLInput& pIn, const Attribute& pAttr)
{
  if (pAttr.isA (Tags::tag_resource))
    pIn.readto( Resource::reader(Resource::metadata,pIn.getAttributes()) );
  else if (pAttr.isA (Tags::tag_skill))
    pIn.readto( Skill::reader(Skill::metadata,pIn.getAttributes()) );
  else
    PythonDictionary::read(pIn, pAttr, getDict());
}

DECLARE_EXPORT void ResourceSkill::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
{
  if (pAttr.isA (Tags::tag_resource))
  {
    Resource *r = dynamic_cast<Resource*>(pIn.getPreviousObject());
    if (r) setResource(r);
    else throw LogicException("Incorrect object type during read operation");
  }
  else if (pAttr.isA (Tags::tag_skill))
  {
    Skill *s = dynamic_cast<Skill*>(pIn.getPreviousObject());
    if (s) setSkill(s);
    else throw LogicException("Incorrect object type during read operation");
  }
  else if (pAttr.isA(Tags::tag_priority))
    setPriority(pElement.getInt());
  else if (pAttr.isA(Tags::tag_effective_end))
    setEffectiveEnd(pElement.getDate());
  else if (pAttr.isA(Tags::tag_effective_start))
    setEffectiveStart(pElement.getDate());
  else if (pAttr.isA(Tags::tag_source))
    setSource(pElement.getString());
  else if (pAttr.isA(Tags::tag_action))
  {
    delete static_cast<Action*>(pIn.getUserArea());
    pIn.setUserArea(
      new Action(MetaClass::decodeAction(pElement.getString().c_str()))
    );
  }
  else if (pIn.isObjectEnd())
  {
    // The resourceskill data is now all read in. See if it makes sense now...
    Action a = pIn.getUserArea() ?
        *static_cast<Action*>(pIn.getUserArea()) :
        ADD_CHANGE;
    delete static_cast<Action*>(pIn.getUserArea());
    try { validate(a); }
    catch (...)
    {
      delete this;
      throw;
    }
  }
}

DECLARE_EXPORT PyObject* ResourceSkill::getattro(const Attribute& attr)
{
  if (attr.isA(Tags::tag_resource))
    return PythonObject(getResource());
  if (attr.isA(Tags::tag_skill))
    return PythonObject(getSkill());
  if (attr.isA(Tags::tag_priority))
    return PythonObject(getPriority());
  if (attr.isA(Tags::tag_effective_end))
    return PythonObject(getEffective().getEnd());
  if (attr.isA(Tags::tag_effective_start))
    return PythonObject(getEffective().getStart());
  if (attr.isA(Tags::tag_source))
    return PythonObject(getSource());
  return NULL;
}

DECLARE_EXPORT int ResourceSkill::setattro(const Attribute& attr, const PythonObject& field)
{
  if (attr.isA(Tags::tag_resource))
  {
    if (!field.check(Resource::metadata))
    {
      PyErr_SetString(PythonDataException, "resourceskill resource must be of type resource");
      return -1;
    }
    Resource* y = static_cast<Resource*>(static_cast<PyObject*>(field));
    setResource(y);
  }
  else if (attr.isA(Tags::tag_skill))
  {
    if (!field.check(Skill::metadata))
    {
      PyErr_SetString(PythonDataException, "resourceskill skill must be of type skill");
      return -1;
    }
    Skill* y = static_cast<Skill*>(static_cast<PyObject*>(field));
    setSkill(y);
  }
  else if (attr.isA(Tags::tag_priority))
    setPriority(field.getInt());
  else if (attr.isA(Tags::tag_effective_end))
    setEffectiveEnd(field.getDate());
  else if (attr.isA(Tags::tag_effective_start))
    setEffectiveStart(field.getDate());
  else if (attr.isA(Tags::tag_source))
    setSource(field.getString());
  else
    return -1;
  return 0;
}

/** @todo this method implementation is not generic enough and not extendible by subclasses. */
PyObject* ResourceSkill::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds)
{
  try
  {
    // Pick up the skill
    PyObject* skill = PyDict_GetItemString(kwds,"skill");
    if (!PyObject_TypeCheck(skill, Skill::metadata->pythonClass))
      throw DataException("resourceskill skill must be of type skill");

    // Pick up the resource
    PyObject* res = PyDict_GetItemString(kwds,"resource");
    if (!PyObject_TypeCheck(res, Resource::metadata->pythonClass))
      throw DataException("resourceskill resource must be of type resource");

    // Pick up the priority
    PyObject* q1 = PyDict_GetItemString(kwds,"priority");
    int q2 = q1 ? PythonObject(q1).getInt() : 1;

    // Pick up the effective dates
    DateRange eff;
    PyObject* eff_start = PyDict_GetItemString(kwds,"effective_start");
    if (eff_start)
    {
      PythonObject d(eff_start);
      eff.setStart(d.getDate());
    }
    PyObject* eff_end = PyDict_GetItemString(kwds,"effective_end");
    if (eff_end)
    {
      PythonObject d(eff_end);
      eff.setEnd(d.getDate());
    }

    // Create the resourceskill
    ResourceSkill *l = new ResourceSkill(
      static_cast<Skill*>(skill),
      static_cast<Resource*>(res),
      q2, eff
    );

    // Iterate over extra keywords, and set attributes.   @todo move this responsibility to the readers...
    if (l)
    {
      PyObject *key, *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(kwds, &pos, &key, &value))
      {
        PythonObject field(value);
        PyObject* key_utf8 = PyUnicode_AsUTF8String(key);
        Attribute attr(PyBytes_AsString(key_utf8));
        Py_DECREF(key_utf8);
        if (!attr.isA(Tags::tag_effective_end) && !attr.isA(Tags::tag_effective_start)
          && !attr.isA(Tags::tag_skill) && !attr.isA(Tags::tag_resource)
          && !attr.isA(Tags::tag_priority) && !attr.isA(Tags::tag_type)
          && !attr.isA(Tags::tag_action))
        {
          int result = l->setattro(attr, field);
          if (result && !PyErr_Occurred())
            PyErr_Format(PyExc_AttributeError,
                "attribute '%S' on '%s' can't be updated",
                key, Py_TYPE(l)->tp_name);
        }
      };
    }

    // Return the object
    Py_INCREF(l);
    return static_cast<PyObject*>(l);
  }
  catch (...)
  {
    PythonType::evalException();
    return NULL;
  }
}

DECLARE_EXPORT void ResourceSkill::validate(Action action)
{
  // Catch null operation and resource pointers
  Skill *skill = getSkill();
  Resource *res = getResource();
  if (!skill || !res)
  {
    // Invalid load model
    if (!skill && !res)
      throw DataException("Missing resource and kill on a resourceskill");
    else if (!skill)
      throw DataException("Missing skill on a resourceskill on resource '"
          + res->getName() + "'");
    else if (!res)
      throw DataException("Missing resource on a resourceskill on skill '"
          + skill->getName() + "'");
  }

  // Check if a resourceskill with 1) identical resource, 2) identical skill and
  // 3) overlapping effectivity dates already exists
  Skill::resourcelist::const_iterator i = skill->getResources().begin();
  for (; i != skill->getResources().end(); ++i)
    if (i->getResource() == res
        && i->getEffective().overlap(getEffective())
        && &*i != this)
      break;

  // Apply the appropriate action
  switch (action)
  {
    case ADD:
      if (i != skill->getResources().end())
      {
        throw DataException("Resourceskill of '" + res->getName() + "' and '"
            + skill->getName() + "' already exists");
      }
      break;
    case CHANGE:
      throw DataException("Can't update a resourceskill");
    case ADD_CHANGE:
      // ADD is handled in the code after the switch statement
      if (i == skill->getResources().end()) break;
      throw DataException("Can't update a resourceskill");
    case REMOVE:
      // This resourceskill was only used temporarily during the reading process
      delete this;
      if (i == skill->getResources().end())
        // Nothing to delete
        throw DataException("Can't remove nonexistent resourceskill of '"
            + res->getName() + "' and '" + skill->getName() + "'");
      delete &*i;
      return;
  }
}

int ResourceSkillIterator::initialize()
{
  // Initialize the type
  PythonType& x = PythonExtension<ResourceSkillIterator>::getType();
  x.setName("resourceSkillIterator");
  x.setDoc("frePPLe iterator for resource skills");
  x.supportiter();
  return x.typeReady();
}

PyObject* ResourceSkillIterator::iternext()
{
  PyObject* result;
  if (res)
  {
    // Iterate over skills on a resource
    if (ir == res->getSkills().end()) return NULL;
    result = const_cast<ResourceSkill*>(&*ir);
    ++ir;
  }
  else
  {
    // Iterate over resources having a skill
    if (is == skill->getResources().end()) return NULL;
    result = const_cast<ResourceSkill*>(&*is);
    ++is;
  }
  Py_INCREF(result);
  return result;
}

}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ServerMenu.h"

/* common implementation headers */
#include "FontManager.h"
#include "StateDatabase.h"

/* local implementation headers */
#include "FontSizer.h"
#include "MainMenu.h"
#include "HUDDialogStack.h"
#include "clientConfig.h"
#include "ConfigFileManager.h"
#include "bzflag.h"
#include "LocalFontFace.h"
#include "playing.h"

bool ServerMenuDefaultKey::keyPress(const BzfKeyEvent& key)
{
  ServerList &serverList = ServerList::instance();

  HUDuiControl* activeTabControl = menu->tabbedControl->getActiveTab();
  HUDuiServerList* activeServerList = NULL;

  // The currently active tab is the custom tab creation control. We don't handle
  // any key presses for that here, so pass it on, and return the result we get.
  if (activeTabControl == menu->customTabControl) // Is this the right way to check?
    return MenuDefaultKey::keyPress(key);
  // The currently active tab is NOT the custom tab, so let's try casting it as a
  // HUDuiServerList control. For the server browser we only expect controls of type
  // HUDuiServerListCustomTab, or HUDuiServerList. However, since we are using a
  // HUDuiTabbedControl, we could have any subclass of HUDuiControl, so we have to
  // be careful to check what class we are dealing with when executing key presses.
  else
    activeServerList = dynamic_cast<HUDuiServerList*>(activeTabControl);

  // The active tab is not the custom tab control, and is not a HUDuiServerList
  // Right now we're handling input that affects either custom tab creation, or
  // server list browsing. Since this is neither, return false, we don't handle it.
  if ((activeServerList == 0)||(activeServerList == NULL))
    // dynamic_cast returns 0 if it fails
    return false;

  // These key presses should only be processed when the user has a server selected.
  // As such, we should check to see if the server list, or the tabbed control have
  // focus, and if they do, ignore these key presses for now. Also check that the
  // user has a server selected.
  if ((!activeServerList->hasFocus())&&(!menu->tabbedControl->hasFocus())&&
     (activeServerList->getSelectedServer() != NULL)){
    // The favorite key was pressed
    if (key.chr == 'f') {
      // Check to see if we're on the favorites list, if we are, ignore keypress
      if (activeServerList == menu->favoritesList) {
	return false;
      } else {
	// Mark it as a favorite server
	serverList.markAsFavorite(activeServerList->getSelectedServer());
	return true;
      }
    }

    // The remove server key was pressed
    if (key.chr == 'h') {
      // Design decision: Don't let users remove any servers from the normal server
      // list. Let's keep this as a pure representation of all the available servers
      if (activeServerList == menu->normalList)
        return false;

      // If we're on the favorites list, we need to unmark the server
      // as a favorite server in order to remove it from the list
      if (activeServerList == menu->favoritesList)
        serverList.unmarkAsFavorite(activeServerList->getSelectedServer());

      // If we're on the recents list, we need to unmark the server
      // as a recent server in order to remove it from the list
      if (activeServerList == menu->recentList)
        serverList.unmarkAsRecent(activeServerList->getSelectedServer());

      // Remove the selected server from the active server list
      activeServerList->removeItem(activeServerList->getSelectedServer());
      return true;
    }
  }

  // The clear server list key was pressed
  if (key.chr == 'c') {
    // Design decision: Don't let users remove any servers from the normal server
    // list. Let's keep this as a pure representation of all the available servers
    if (activeServerList == menu->normalList)
      return false;

    // If we're on the favorites list, cycle through all favorite servers and unmark
    // them as favorites. This may be a bad idea, it's fairly easy to accidentally
    // clear your favorites list using this functionality.
    if (activeServerList == menu->favoritesList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsFavorite(activeServerList->get(i)->getServer());
      }
    }

    // If we're on the recent server list, cycle through all
    // recent servers and unmark them as a recent server.
    if (activeServerList == menu->recentList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsRecent(activeServerList->get(i)->getServer());
      }
    }

    // Clear the list
    activeServerList->clearList();
    return true;
  }

  // Remove the current tab. This can be pressed at any
  // time, but only works if the user is on a custom tab.
  if (key.chr == 'v') {
    // Do nothing if the user is on any of the standard tabs
    if ((activeServerList == menu->favoritesList) ||
	(activeServerList == menu->normalList) ||
	(activeServerList == menu->recentList))
      return false;

    // Remove the current tab from the tabbed control
    std::string tabName = menu->tabbedControl->getActiveTabName();
    HUDuiServerListCache::instance().removeList(activeServerList, tabName);
    menu->tabbedControl->removeTab(activeServerList, tabName);
    return true;
  }

  // Refresh the server list. This can be done at any time.
  if (key.chr == 'r') {
    ServerList::instance().clear();
    ServerList::instance().startServerPings(getStartupInfo());
    return true;
  }

  return MenuDefaultKey::keyPress(key);
}

bool ServerMenuDefaultKey::keyRelease(const BzfKeyEvent& key)
{
  switch (key.chr) {
  case 27: // escape
  case 13: // return
    return true;
  }

  return false;
}

ServerMenu::PingsMap ServerMenu::activePings;

ServerMenu::ServerMenu()
  : normalList(0)
  , recentList(0)
  , favoritesList(0)
  , tabbedControl(0)
  , serverInfo(new HUDuiServerInfo())
  , customTabControl(new HUDuiServerListCustomTab())
  , listsCache(HUDuiServerListCache::instance())
  , serverList(ServerList::instance())
  , defaultKey(this)
  , title(0)
  , help(0)
{
  // cache font face ID
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  addPlayingCallback(&playingCB, this);

  serverList.updateFromCache();
  serverList.startServerPings(getStartupInfo());
  listsCache.loadCache();

  std::vector<std::pair<HUDuiServerList*, std::string> > cachedLists = listsCache.readCachedLists();

  if (cachedLists.size() > (size_t) 0) {
    normalList = cachedLists[0].first;
    recentList = cachedLists[1].first;
    favoritesList = cachedLists[2].first;
  } else {
    normalList = new HUDuiServerList;
    favoritesList = new HUDuiServerList;
    recentList = new HUDuiServerList;
    listsCache.addNewList(normalList, "");
    listsCache.addNewList(favoritesList, "");
    listsCache.addNewList(recentList, "");
  }

  normalList->setFontFace(fontFace);
  favoritesList->setFontFace(fontFace);
  recentList->setFontFace(fontFace);
  serverInfo->setFontFace(fontFace);
  customTabControl->setFontFace(fontFace);

  title = new HUDuiLabel();
  title->setString("Servers");
  title->setFontFace(fontFace);

  help = new HUDuiLabel();
  help->setString("f - add server to favorites      h - remove server from tab      c - clear tab      v - delete tab      r - refresh server list");
  help->setFontFace(fontFace);

  tabbedControl = new HUDuiTabbedControl;
  tabbedControl->setFontFace(fontFace);
  tabbedControl->addTab(normalList, "All");
  tabbedControl->addTab(recentList, "Recent");
  tabbedControl->addTab(favoritesList, "Favorites");

  for (size_t i=3; i<cachedLists.size(); i++) {
    cachedLists[i].first->setFontFace(fontFace);
    tabbedControl->addTab(cachedLists[i].first, cachedLists[i].second);
  }

  tabbedControl->addTab(customTabControl, "Create New Tab");
  tabbedControl->setActiveTab(0);

  serverList.addServerCallback(newServer, normalList);
  serverList.addFavoriteServerCallback(newServer, favoritesList);
  serverList.addRecentServerCallback(newServer, recentList);

  addControl(title, false);
  addControl(tabbedControl);
  addControl(serverInfo);
  addControl(help, false);

  initNavigation();
}

ServerMenu::~ServerMenu()
{
  serverList.removeServerCallback(newServer, normalList);
  serverList.removeFavoriteServerCallback(newServer, favoritesList);
  serverList.removeRecentServerCallback(newServer, recentList);
}

void ServerMenu::newServer(ServerItem* addedServer, void* data)
{
  HUDuiServerList* serverData( static_cast<HUDuiServerList*>(data) );

  // Server already has a ping
  if (addedServer->ping.pingTime != 0) {
    serverData->addItem(addedServer);
    return;
  }

  // Pinging in process, add on to the list vector
  if (addedServer->ping.pinging) {
    ServerMenu::activePings[addedServer->getServerKey()].second.push_back(serverData);
  }

  ServerPing* newping = new ServerPing(addedServer->ping.serverId.serverHost, ntohs(addedServer->ping.serverId.port));
  newping->start();
  std::vector<HUDuiServerList*> serverListsVector;
  serverListsVector.push_back(serverData);
  ServerMenu::activePings.insert(PingsMap::value_type(addedServer->getServerKey(), std::pair<ServerPing*, std::vector<HUDuiServerList*> >(newping, serverListsVector)));
  addedServer->ping.pinging = true;
}

void ServerMenu::execute()
{
  if ((tabbedControl->getActiveTab() == customTabControl) &&
      (dynamic_cast<HUDuiServerListCustomTab*>(tabbedControl->getActiveTab())->createNew->hasFocus()))
  {
    HUDuiServerList* newServerList = customTabControl->createServerList();
    listsCache.addNewList(newServerList, customTabControl->tabName->getString());
    tabbedControl->addTab(newServerList, customTabControl->tabName->getString(), tabbedControl->getTabCount() - 1);
    for (size_t i=0; i<serverList.size(); i++) {
      newServerList->addItem(serverList.getServerAt(i));
    }
    //newServerList->searchServers(customTabControl->serverName->getString());
    dynamic_cast<HUDuiNestedContainer*>(tabbedControl->getTab(tabbedControl->getTabCount() - 2))->getNav().set(1);
    return;
  }

  if ((tabbedControl->hasFocus())||
      (tabbedControl->getActiveTab()->hasFocus())||
      (tabbedControl->getActiveTabName() == "Create New Tab"))
    return;

  // update startup info
  StartupInfo* info = getStartupInfo();
  ServerItem* selectedServer = dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer();
  strncpy(info->serverName, selectedServer->name.c_str(), ServerNameLen-1);
  info->serverPort = ntohs((unsigned short) selectedServer->ping.serverId.port);

  // all done
  HUDDialogStack::get()->pop();
}

void ServerMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);
  FontSizer fs = FontSizer(_width, _height);

  FontManager &fm = FontManager::instance();
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  // reposition title
  float x, y;

  // use a big font for title, smaller font for the rest
  fs.setMin(0, (int)(1.0 / BZDB.eval("headerFontSize") / 2.0));
  const float titleFontSize = fs.getFontSize(fontFace->getFMFace(), "headerFontSize");

  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStringWidth(fontFace->getFMFace(), titleFontSize, title->getString());
  const float titleHeight = fm.getStringHeight(fontFace->getFMFace(), titleFontSize);
  x = 0.5f * ((float)_width - titleWidth);
  y = (float)_height - titleHeight;
  title->setPosition(x, y);

  fs.setMin(40,10);
  const float fontSize = fs.getFontSize(fontFace->getFMFace(), "alertFontSize");

  float edgeSpacer = fm.getStringWidth(fontFace->getFMFace(), fontSize, "X");
  float bottomSpacer = fm.getStringHeight(fontFace->getFMFace(), fontSize);

  float remainingSpace = y - bottomSpacer*2;
  float listHeight = remainingSpace*0.65f;

  tabbedControl->setSize((_width - (2*edgeSpacer)),listHeight);
  serverInfo->setSize((_width - (2*edgeSpacer)), (remainingSpace - 4*bottomSpacer)*0.35f);

  y = y - (titleHeight/2) - tabbedControl->getHeight();

  float helpLength = fm.getStringWidth(fontFace->getFMFace(), fontSize, help->getString());

  tabbedControl->setPosition(edgeSpacer, y);
  serverInfo->setPosition(edgeSpacer, bottomSpacer/2 + bottomSpacer);
  help->setPosition((_width - helpLength)/2, bottomSpacer/2);
  tabbedControl->setFontSize(fontSize);
  serverInfo->setFontSize(fontSize);
  help->setFontSize(fontSize);
}

void ServerMenu::updateStatus()
{
  if (tabbedControl->hasFocus() ||
      tabbedControl->getActiveTab()->hasFocus() ||
      tabbedControl->getActiveTabName() == "Create New Tab")
    serverInfo->setServerItem(NULL);
  else
    serverInfo->setServerItem(dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer());
}

void ServerMenu::playingCB(void* _self)
{
  ServerList &list = ServerList::instance();
  for (PingsMap::iterator i = ServerMenu::activePings.begin();
       i != ServerMenu::activePings.end();) {
    i->second.first->doPings();
    if (i->second.first->done()) {
      ServerItem* server = list.lookupServer(i->first);
      if (server == NULL)
	break;
      server->ping.pingTime = i->second.first->calcLag();
      server->ping.pinging = false;
      for (size_t j=0; j<(i->second.second.size()); j++) {
	i->second.second[j]->addItem(server);
      }
      delete i->second.first;
      ServerMenu::activePings.erase(i++);
      continue;
    }
    ++i;
  }

  static_cast<ServerMenu*>(_self)->serverList.checkEchos(getStartupInfo());
  static_cast<ServerMenu*>(_self)->updateStatus();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>For clarity, increment the "for" loop index in the "for" statement itself rather than down inside the loop.<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ServerMenu.h"

/* common implementation headers */
#include "FontManager.h"
#include "StateDatabase.h"

/* local implementation headers */
#include "FontSizer.h"
#include "MainMenu.h"
#include "HUDDialogStack.h"
#include "clientConfig.h"
#include "ConfigFileManager.h"
#include "bzflag.h"
#include "LocalFontFace.h"
#include "playing.h"

bool ServerMenuDefaultKey::keyPress(const BzfKeyEvent& key)
{
  ServerList &serverList = ServerList::instance();

  HUDuiControl* activeTabControl = menu->tabbedControl->getActiveTab();
  HUDuiServerList* activeServerList = NULL;

  // The currently active tab is the custom tab creation control. We don't handle
  // any key presses for that here, so pass it on, and return the result we get.
  if (activeTabControl == menu->customTabControl) // Is this the right way to check?
    return MenuDefaultKey::keyPress(key);
  // The currently active tab is NOT the custom tab, so let's try casting it as a
  // HUDuiServerList control. For the server browser we only expect controls of type
  // HUDuiServerListCustomTab, or HUDuiServerList. However, since we are using a
  // HUDuiTabbedControl, we could have any subclass of HUDuiControl, so we have to
  // be careful to check what class we are dealing with when executing key presses.
  else
    activeServerList = dynamic_cast<HUDuiServerList*>(activeTabControl);

  // The active tab is not the custom tab control, and is not a HUDuiServerList
  // Right now we're handling input that affects either custom tab creation, or
  // server list browsing. Since this is neither, return false, we don't handle it.
  if ((activeServerList == 0)||(activeServerList == NULL))
    // dynamic_cast returns 0 if it fails
    return false;

  // These key presses should only be processed when the user has a server selected.
  // As such, we should check to see if the server list, or the tabbed control have
  // focus, and if they do, ignore these key presses for now. Also check that the
  // user has a server selected.
  if ((!activeServerList->hasFocus())&&(!menu->tabbedControl->hasFocus())&&
     (activeServerList->getSelectedServer() != NULL)){
    // The favorite key was pressed
    if (key.chr == 'f') {
      // Check to see if we're on the favorites list, if we are, ignore keypress
      if (activeServerList == menu->favoritesList) {
	return false;
      } else {
	// Mark it as a favorite server
	serverList.markAsFavorite(activeServerList->getSelectedServer());
	return true;
      }
    }

    // The remove server key was pressed
    if (key.chr == 'h') {
      // Design decision: Don't let users remove any servers from the normal server
      // list. Let's keep this as a pure representation of all the available servers
      if (activeServerList == menu->normalList)
        return false;

      // If we're on the favorites list, we need to unmark the server
      // as a favorite server in order to remove it from the list
      if (activeServerList == menu->favoritesList)
        serverList.unmarkAsFavorite(activeServerList->getSelectedServer());

      // If we're on the recents list, we need to unmark the server
      // as a recent server in order to remove it from the list
      if (activeServerList == menu->recentList)
        serverList.unmarkAsRecent(activeServerList->getSelectedServer());

      // Remove the selected server from the active server list
      activeServerList->removeItem(activeServerList->getSelectedServer());
      return true;
    }
  }

  // The clear server list key was pressed
  if (key.chr == 'c') {
    // Design decision: Don't let users remove any servers from the normal server
    // list. Let's keep this as a pure representation of all the available servers
    if (activeServerList == menu->normalList)
      return false;

    // If we're on the favorites list, cycle through all favorite servers and unmark
    // them as favorites. This may be a bad idea, it's fairly easy to accidentally
    // clear your favorites list using this functionality.
    if (activeServerList == menu->favoritesList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsFavorite(activeServerList->get(i)->getServer());
      }
    }

    // If we're on the recent server list, cycle through all
    // recent servers and unmark them as a recent server.
    if (activeServerList == menu->recentList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsRecent(activeServerList->get(i)->getServer());
      }
    }

    // Clear the list
    activeServerList->clearList();
    return true;
  }

  // Remove the current tab. This can be pressed at any
  // time, but only works if the user is on a custom tab.
  if (key.chr == 'v') {
    // Do nothing if the user is on any of the standard tabs
    if ((activeServerList == menu->favoritesList) ||
	(activeServerList == menu->normalList) ||
	(activeServerList == menu->recentList))
      return false;

    // Remove the current tab from the tabbed control
    std::string tabName = menu->tabbedControl->getActiveTabName();
    HUDuiServerListCache::instance().removeList(activeServerList, tabName);
    menu->tabbedControl->removeTab(activeServerList, tabName);
    return true;
  }

  // Refresh the server list. This can be done at any time.
  if (key.chr == 'r') {
    ServerList::instance().clear();
    ServerList::instance().startServerPings(getStartupInfo());
    return true;
  }

  return MenuDefaultKey::keyPress(key);
}

bool ServerMenuDefaultKey::keyRelease(const BzfKeyEvent& key)
{
  switch (key.chr) {
  case 27: // escape
  case 13: // return
    return true;
  }

  return false;
}

ServerMenu::PingsMap ServerMenu::activePings;

ServerMenu::ServerMenu()
  : normalList(0)
  , recentList(0)
  , favoritesList(0)
  , tabbedControl(0)
  , serverInfo(new HUDuiServerInfo())
  , customTabControl(new HUDuiServerListCustomTab())
  , listsCache(HUDuiServerListCache::instance())
  , serverList(ServerList::instance())
  , defaultKey(this)
  , title(0)
  , help(0)
{
  // cache font face ID
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  addPlayingCallback(&playingCB, this);

  serverList.updateFromCache();
  serverList.startServerPings(getStartupInfo());
  listsCache.loadCache();

  std::vector<std::pair<HUDuiServerList*, std::string> > cachedLists = listsCache.readCachedLists();

  if (cachedLists.size() > (size_t) 0) {
    normalList = cachedLists[0].first;
    recentList = cachedLists[1].first;
    favoritesList = cachedLists[2].first;
  } else {
    normalList = new HUDuiServerList;
    favoritesList = new HUDuiServerList;
    recentList = new HUDuiServerList;
    listsCache.addNewList(normalList, "");
    listsCache.addNewList(favoritesList, "");
    listsCache.addNewList(recentList, "");
  }

  normalList->setFontFace(fontFace);
  favoritesList->setFontFace(fontFace);
  recentList->setFontFace(fontFace);
  serverInfo->setFontFace(fontFace);
  customTabControl->setFontFace(fontFace);

  title = new HUDuiLabel();
  title->setString("Servers");
  title->setFontFace(fontFace);

  help = new HUDuiLabel();
  help->setString("f - add server to favorites      h - remove server from tab      c - clear tab      v - delete tab      r - refresh server list");
  help->setFontFace(fontFace);

  tabbedControl = new HUDuiTabbedControl;
  tabbedControl->setFontFace(fontFace);
  tabbedControl->addTab(normalList, "All");
  tabbedControl->addTab(recentList, "Recent");
  tabbedControl->addTab(favoritesList, "Favorites");

  for (size_t i=3; i<cachedLists.size(); i++) {
    cachedLists[i].first->setFontFace(fontFace);
    tabbedControl->addTab(cachedLists[i].first, cachedLists[i].second);
  }

  tabbedControl->addTab(customTabControl, "Create New Tab");
  tabbedControl->setActiveTab(0);

  serverList.addServerCallback(newServer, normalList);
  serverList.addFavoriteServerCallback(newServer, favoritesList);
  serverList.addRecentServerCallback(newServer, recentList);

  addControl(title, false);
  addControl(tabbedControl);
  addControl(serverInfo);
  addControl(help, false);

  initNavigation();
}

ServerMenu::~ServerMenu()
{
  serverList.removeServerCallback(newServer, normalList);
  serverList.removeFavoriteServerCallback(newServer, favoritesList);
  serverList.removeRecentServerCallback(newServer, recentList);
}

void ServerMenu::newServer(ServerItem* addedServer, void* data)
{
  HUDuiServerList* serverData( static_cast<HUDuiServerList*>(data) );

  // Server already has a ping
  if (addedServer->ping.pingTime != 0) {
    serverData->addItem(addedServer);
    return;
  }

  // Pinging in process, add on to the list vector
  if (addedServer->ping.pinging) {
    ServerMenu::activePings[addedServer->getServerKey()].second.push_back(serverData);
  }

  ServerPing* newping = new ServerPing(addedServer->ping.serverId.serverHost, ntohs(addedServer->ping.serverId.port));
  newping->start();
  std::vector<HUDuiServerList*> serverListsVector;
  serverListsVector.push_back(serverData);
  ServerMenu::activePings.insert(PingsMap::value_type(addedServer->getServerKey(), std::pair<ServerPing*, std::vector<HUDuiServerList*> >(newping, serverListsVector)));
  addedServer->ping.pinging = true;
}

void ServerMenu::execute()
{
  if ((tabbedControl->getActiveTab() == customTabControl) &&
      (dynamic_cast<HUDuiServerListCustomTab*>(tabbedControl->getActiveTab())->createNew->hasFocus()))
  {
    HUDuiServerList* newServerList = customTabControl->createServerList();
    listsCache.addNewList(newServerList, customTabControl->tabName->getString());
    tabbedControl->addTab(newServerList, customTabControl->tabName->getString(), tabbedControl->getTabCount() - 1);
    for (size_t i=0; i<serverList.size(); i++) {
      newServerList->addItem(serverList.getServerAt(i));
    }
    //newServerList->searchServers(customTabControl->serverName->getString());
    dynamic_cast<HUDuiNestedContainer*>(tabbedControl->getTab(tabbedControl->getTabCount() - 2))->getNav().set(1);
    return;
  }

  if ((tabbedControl->hasFocus())||
      (tabbedControl->getActiveTab()->hasFocus())||
      (tabbedControl->getActiveTabName() == "Create New Tab"))
    return;

  // update startup info
  StartupInfo* info = getStartupInfo();
  ServerItem* selectedServer = dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer();
  strncpy(info->serverName, selectedServer->name.c_str(), ServerNameLen-1);
  info->serverPort = ntohs((unsigned short) selectedServer->ping.serverId.port);

  // all done
  HUDDialogStack::get()->pop();
}

void ServerMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);
  FontSizer fs = FontSizer(_width, _height);

  FontManager &fm = FontManager::instance();
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  // reposition title
  float x, y;

  // use a big font for title, smaller font for the rest
  fs.setMin(0, (int)(1.0 / BZDB.eval("headerFontSize") / 2.0));
  const float titleFontSize = fs.getFontSize(fontFace->getFMFace(), "headerFontSize");

  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStringWidth(fontFace->getFMFace(), titleFontSize, title->getString());
  const float titleHeight = fm.getStringHeight(fontFace->getFMFace(), titleFontSize);
  x = 0.5f * ((float)_width - titleWidth);
  y = (float)_height - titleHeight;
  title->setPosition(x, y);

  fs.setMin(40,10);
  const float fontSize = fs.getFontSize(fontFace->getFMFace(), "alertFontSize");

  float edgeSpacer = fm.getStringWidth(fontFace->getFMFace(), fontSize, "X");
  float bottomSpacer = fm.getStringHeight(fontFace->getFMFace(), fontSize);

  float remainingSpace = y - bottomSpacer*2;
  float listHeight = remainingSpace*0.65f;

  tabbedControl->setSize((_width - (2*edgeSpacer)),listHeight);
  serverInfo->setSize((_width - (2*edgeSpacer)), (remainingSpace - 4*bottomSpacer)*0.35f);

  y = y - (titleHeight/2) - tabbedControl->getHeight();

  float helpLength = fm.getStringWidth(fontFace->getFMFace(), fontSize, help->getString());

  tabbedControl->setPosition(edgeSpacer, y);
  serverInfo->setPosition(edgeSpacer, bottomSpacer/2 + bottomSpacer);
  help->setPosition((_width - helpLength)/2, bottomSpacer/2);
  tabbedControl->setFontSize(fontSize);
  serverInfo->setFontSize(fontSize);
  help->setFontSize(fontSize);
}

void ServerMenu::updateStatus()
{
  if (tabbedControl->hasFocus() ||
      tabbedControl->getActiveTab()->hasFocus() ||
      tabbedControl->getActiveTabName() == "Create New Tab")
    serverInfo->setServerItem(NULL);
  else
    serverInfo->setServerItem(dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer());
}

void ServerMenu::playingCB(void* _self)
{
  ServerList &list = ServerList::instance();
  for (PingsMap::iterator i = ServerMenu::activePings.begin();
       i != ServerMenu::activePings.end(); i++) {
    i->second.first->doPings();
    if (i->second.first->done()) {
      ServerItem* server = list.lookupServer(i->first);
      if (server == NULL)
	break;
      server->ping.pingTime = i->second.first->calcLag();
      server->ping.pinging = false;
      for (size_t j=0; j<(i->second.second.size()); j++) {
	i->second.second[j]->addItem(server);
      }
      delete i->second.first;
      ServerMenu::activePings.erase(i);
    }
  }

  static_cast<ServerMenu*>(_self)->serverList.checkEchos(getStartupInfo());
  static_cast<ServerMenu*>(_self)->updateStatus();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include <iostream>
#include "cjk-tokenizer.h"

using namespace std;
using namespace cjk;

class handler : public tokenizer_handler {
public:
    void handle_token(const std::string &tok, bool is_cjk) {
        cout << "Handling [" << tok << "] by handler class. "
             << "(CJK: " << is_cjk << ")" << endl;
    };
};

int main() {
    tokenizer tknzr;
    vector<string> token_list;
    vector<string>::iterator token_iter;
    char text[] =
        "美女遊戲等你挑戰周蕙最新鈴搶先下載茄子醬耍可愛一流"
        "华沙是波兰的首都，也是其最大的城市。"
        "납치 여중생 공포에 떠는데'…경찰 200m 거리 25분만에 출동"
        "寛永通宝の一。京都方広寺の大仏をこわして1668年（寛文8）から鋳造した銅銭。"
        "ㄅㄆㄇㄈㄉㄊㄋㄌㄧㄨㄩ"
        "Giant Microwave Turns Plastic Back to Oil";
    string text_str = string(text);

    cout << "[Default]" << endl;
    token_list.clear();
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Trigram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 3;
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Pentagram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 5;
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Max token count]" << endl;
    token_list.clear();
    tknzr.max_token_count = 10;
    cout << "Max token count: " << tknzr.max_token_count << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Unigram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 1;
    tknzr.max_token_count = 0;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Split]" << endl;
    token_list.clear();
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    vector<unicode_char_t> uchar_list;
    vector<unicode_char_t>::iterator uchar_iter;

    cout << "[Split (unicode_char_t)]" << endl;
    tknzr.split(text_str, uchar_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (uchar_iter = uchar_list.begin();
         uchar_iter != uchar_list.end(); uchar_iter++) {
        cout << "[" << *uchar_iter << "] ";
    }
    cout << endl << endl;

    cout << "-- CJK Segmentation" << endl;
    cout << "Original string: " << text << endl;
    token_list.clear();
    tknzr.segment(text_str, token_list);
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Split] (zh_tw -> zh_cn)" << endl;
    token_list.clear();
    tknzr.han_conv_method = HAN_CONV_TRAD2SIMP;
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Split] (zh_cn -> zh_tw)" << endl;
    token_list.clear();
    tknzr.han_conv_method = HAN_CONV_SIMP2TRAD;
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    handler h;
    cout << "-- CJK Tokenizer Handler" << endl;
    tknzr.han_conv_method = HAN_CONV_NONE;
    tknzr.tokenize(text_str, h);
    cout << endl << endl;

    string cjk_str = "這是CJK字串";
    string pure_cjk_str =
        "這個字串只含中日韓。"
        "コンピューターの機能を、音響・映像・作品制御などに利用する芸術の総称。"
        "납치 여중생 공포에 떠는데'…경찰 200m 거리 25분만에 출동"
        "ㄅㄆㄇㄈㄉㄊㄋㄌㄧㄨㄩ";
    cout << "[" << cjk_str << "]" << " has CJK characters? "
         << tknzr.has_cjk(cjk_str) << endl;
    cout << "[" << cjk_str << "]" << " has CJK characters only? "
         << tknzr.has_cjk_only(cjk_str) << endl;
    cout << "[" << pure_cjk_str << "]" << " has CJK characters? "
         << tknzr.has_cjk(pure_cjk_str) << endl;
    cout << "[" << pure_cjk_str << "]" << " has CJK characters only? "
         << tknzr.has_cjk_only(pure_cjk_str) << endl;
    cout << endl;
    return 0;
}
<commit_msg>Tidy up test by splitting it into a couple of separate functions.<commit_after>#include <iostream>
#include "cjk-tokenizer.h"

using namespace std;
using namespace cjk;

class handler : public tokenizer_handler {
public:
    void handle_token(const std::string &tok, bool is_cjk) {
        cout << "Handling [" << tok << "] by handler class. "
             << "(CJK: " << is_cjk << ")" << endl;
    };
};

void test1(string text_str) {
    tokenizer tknzr;
    vector<pair<string, unsigned> > token_list;
    vector<pair<string, unsigned> >::iterator token_iter;
    cout << "[Default]" << endl;
    token_list.clear();
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << token_iter->first << "," << token_iter->second << "] ";
    }
    cout << endl << endl;

    cout << "[Trigram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 3;
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << token_iter->first << "] ";
    }
    cout << endl << endl;

    cout << "[Pentagram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 5;
    cout << "Ngram size: "  << tknzr.ngram_size << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << token_iter->first << "] ";
    }
    cout << endl << endl;

    cout << "[Max token count]" << endl;
    token_list.clear();
    tknzr.max_token_count = 10;
    cout << "Max token count: " << tknzr.max_token_count << endl;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << token_iter->first << "] ";
    }
    cout << endl << endl;

    cout << "[Unigram]" << endl;
    token_list.clear();
    tknzr.ngram_size = 1;
    tknzr.max_token_count = 0;
    tknzr.tokenize(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << token_iter->first << "] ";
    }
    cout << endl << endl;
}

void test2(string text_str) {
    tokenizer tknzr;
    vector<string> token_list;
    vector<string>::iterator token_iter;
    cout << "[Split]" << endl;
    token_list.clear();
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    vector<unicode_char_t> uchar_list;
    vector<unicode_char_t>::iterator uchar_iter;

    cout << "[Split (unicode_char_t)]" << endl;
    tknzr.split(text_str, uchar_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (uchar_iter = uchar_list.begin();
         uchar_iter != uchar_list.end(); uchar_iter++) {
        cout << "[" << *uchar_iter << "] ";
    }
    cout << endl << endl;

    cout << "-- CJK Segmentation" << endl;
    cout << "Original string: " << text_str << endl;
    token_list.clear();
    tknzr.segment(text_str, token_list);
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Split] (zh_tw -> zh_cn)" << endl;
    token_list.clear();
    tknzr.han_conv_method = HAN_CONV_TRAD2SIMP;
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    cout << "[Split] (zh_cn -> zh_tw)" << endl;
    token_list.clear();
    tknzr.han_conv_method = HAN_CONV_SIMP2TRAD;
    tknzr.split(text_str, token_list);
    cout << "Original string: " << text_str << endl;
    cout << "Tokenized result: ";
    for (token_iter = token_list.begin();
         token_iter != token_list.end(); ++token_iter) {
        cout << "[" << *token_iter << "] ";
    }
    cout << endl << endl;

    handler h;
    cout << "-- CJK Tokenizer Handler" << endl;
    tknzr.han_conv_method = HAN_CONV_NONE;
    tknzr.tokenize(text_str, h);
    cout << endl << endl;

    string cjk_str = "這是CJK字串";
    string pure_cjk_str =
        "這個字串只含中日韓。"
        "コンピューターの機能を、音響・映像・作品制御などに利用する芸術の総称。"
        "납치 여중생 공포에 떠는데'…경찰 200m 거리 25분만에 출동"
        "ㄅㄆㄇㄈㄉㄊㄋㄌㄧㄨㄩ";
    cout << "[" << cjk_str << "]" << " has CJK characters? "
         << tknzr.has_cjk(cjk_str) << endl;
    cout << "[" << cjk_str << "]" << " has CJK characters only? "
         << tknzr.has_cjk_only(cjk_str) << endl;
    cout << "[" << pure_cjk_str << "]" << " has CJK characters? "
         << tknzr.has_cjk(pure_cjk_str) << endl;
    cout << "[" << pure_cjk_str << "]" << " has CJK characters only? "
         << tknzr.has_cjk_only(pure_cjk_str) << endl;
    cout << endl;
}

int main() {
    char text[] =
        "美女遊戲等你挑戰周蕙最新鈴搶先下載茄子醬耍可愛一流"
        "华沙是波兰的首都，也是其最大的城市。"
        "납치 여중생 공포에 떠는데'…경찰 200m 거리 25분만에 출동"
        "寛永通宝の一。京都方広寺の大仏をこわして1668年（寛文8）から鋳造した銅銭。"
        "ㄅㄆㄇㄈㄉㄊㄋㄌㄧㄨㄩ"
        "Giant Microwave Turns Plastic Back to Oil";
    string text_str = string(text);

    test1(text_str);
    test2(text_str);
    return 0;
}
<|endoftext|>


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

#include "atom/renderer/renderer_client_base.h"

#include <memory>
#include <string>
#include <vector>

#include "atom/common/color_util.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_autofill_agent.h"
#include "atom/renderer/atom_render_frame_observer.h"
#include "atom/renderer/atom_render_view_observer.h"
#include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/preferences_manager.h"
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "electron/buildflags/buildflags.h"
#include "native_mate/dictionary.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_custom_element.h"  // NOLINT(build/include_alpha)
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"

#if defined(OS_MACOSX)
#include "base/strings/sys_string_conversions.h"
#endif

#if defined(OS_WIN)
#include <shlobj.h>
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "atom/common/atom_constants.h"
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)

#if BUILDFLAG(ENABLE_PEPPER_FLASH)
#include "chrome/renderer/pepper/pepper_helper.h"
#endif  // BUILDFLAG(ENABLE_PEPPER_FLASH)

#if BUILDFLAG(ENABLE_TTS)
#include "chrome/renderer/tts_dispatcher.h"
#endif  // BUILDFLAG(ENABLE_TTS)

#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h"
#include "components/printing/renderer/print_render_frame_helper.h"
#endif  // BUILDFLAG(ENABLE_PRINTING)

namespace atom {

namespace {

v8::Local<v8::Value> GetRenderProcessPreferences(
    const PreferencesManager* preferences_manager,
    v8::Isolate* isolate) {
  if (preferences_manager->preferences())
    return mate::ConvertToV8(isolate, *preferences_manager->preferences());
  else
    return v8::Null(isolate);
}

std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
                                               const char* switch_name) {
  std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name);
  return base::SplitString(custom_schemes, ",", base::TRIM_WHITESPACE,
                           base::SPLIT_WANT_NONEMPTY);
}

void SetHiddenValue(v8::Handle<v8::Context> context,
                    const base::StringPiece& key,
                    v8::Local<v8::Value> value) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::Local<v8::Private> privateKey =
      v8::Private::ForApi(isolate, mate::StringToV8(isolate, key));
  context->Global()->SetPrivate(context, privateKey, value);
}

}  // namespace

RendererClientBase::RendererClientBase() {
  auto* command_line = base::CommandLine::ForCurrentProcess();
  // Parse --standard-schemes=scheme1,scheme2
  std::vector<std::string> standard_schemes_list =
      ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);
  for (const std::string& scheme : standard_schemes_list)
    url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
  isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kContextIsolation);
  // We rely on the unique process host id which is notified to the
  // renderer process via command line switch from the content layer,
  // if this switch is removed from the content layer for some reason,
  // we should define our own.
  DCHECK(command_line->HasSwitch(::switches::kRendererClientId));
  renderer_client_id_ =
      command_line->GetSwitchValueASCII(::switches::kRendererClientId);
}

RendererClientBase::~RendererClientBase() {}

void RendererClientBase::DidCreateScriptContext(
    v8::Handle<v8::Context> context,
    content::RenderFrame* render_frame) {
  // global.setHidden("contextId", `${processHostId}-${++next_context_id_}`)
  auto context_id = base::StringPrintf(
      "%s-%" PRId64, renderer_client_id_.c_str(), ++next_context_id_);
  v8::Isolate* isolate = context->GetIsolate();
  SetHiddenValue(context, "contextId", mate::ConvertToV8(isolate, context_id));

  auto* command_line = base::CommandLine::ForCurrentProcess();
  bool enableRemoteModule =
      !command_line->HasSwitch(switches::kDisableRemoteModule);
  SetHiddenValue(context, "enableRemoteModule",
                 mate::ConvertToV8(isolate, enableRemoteModule));
}

void RendererClientBase::AddRenderBindings(
    v8::Isolate* isolate,
    v8::Local<v8::Object> binding_object) {
  mate::Dictionary dict(isolate, binding_object);
  dict.SetMethod(
      "getRenderProcessPreferences",
      base::Bind(GetRenderProcessPreferences, preferences_manager_.get()));
}

void RendererClientBase::RenderThreadStarted() {
  auto* command_line = base::CommandLine::ForCurrentProcess();

  blink::WebCustomElement::AddEmbedderCustomElementName("webview");
  blink::WebCustomElement::AddEmbedderCustomElementName("browserplugin");

  WTF::String extension_scheme("chrome-extension");
  // Extension resources are HTTP-like and safe to expose to the fetch API. The
  // rules for the fetch API are consistent with XHR.
  blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(
      extension_scheme);
  // Extension resources, when loaded as the top-level document, should bypass
  // Blink's strict first-party origin checks.
  blink::SchemeRegistry::RegisterURLSchemeAsFirstPartyWhenTopLevel(
      extension_scheme);
  // In Chrome we should set extension's origins to match the pages they can
  // work on, but in Electron currently we just let extensions do anything.
  blink::SchemeRegistry::RegisterURLSchemeAsSecure(extension_scheme);
  blink::SchemeRegistry::RegisterURLSchemeAsCORSEnabled(extension_scheme);
  blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
      extension_scheme);

  // Parse --secure-schemes=scheme1,scheme2
  std::vector<std::string> secure_schemes_list =
      ParseSchemesCLISwitch(command_line, switches::kSecureSchemes);
  for (const std::string& scheme : secure_schemes_list)
    blink::SchemeRegistry::RegisterURLSchemeAsSecure(
        WTF::String::FromUTF8(scheme.data(), scheme.length()));

  // Allow file scheme to handle service worker by default.
  // FIXME(zcbenz): Can this be moved elsewhere?
  blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
  blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file");

  preferences_manager_.reset(new PreferencesManager);

#if defined(OS_WIN)
  // Set ApplicationUserModelID in renderer process.
  base::string16 app_id =
      command_line->GetSwitchValueNative(switches::kAppUserModelId);
  if (!app_id.empty()) {
    SetCurrentProcessExplicitAppUserModelID(app_id.c_str());
  }
#endif
}

void RendererClientBase::RenderFrameCreated(
    content::RenderFrame* render_frame) {
#if defined(TOOLKIT_VIEWS)
  new AutofillAgent(render_frame);
#endif
#if BUILDFLAG(ENABLE_PEPPER_FLASH)
  new PepperHelper(render_frame);
#endif
  new ContentSettingsObserver(render_frame);
#if BUILDFLAG(ENABLE_PRINTING)
  new printing::PrintRenderFrameHelper(
      render_frame, std::make_unique<ChromePrintRenderFrameHelperDelegate>());
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
  // Allow access to file scheme from pdf viewer.
  blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(
      GURL(kPdfViewerUIOrigin), "file", "", true);
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)
}

void RendererClientBase::RenderViewCreated(content::RenderView* render_view) {
  new AtomRenderViewObserver(render_view);
  blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
  if (!web_frame_widget)
    return;

  base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
  if (cmd->HasSwitch(switches::kGuestInstanceID)) {  // webview.
    web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
  } else {  // normal window.
    std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
    SkColor color = name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
    web_frame_widget->SetBaseBackgroundColor(color);
  }
}

void RendererClientBase::DidClearWindowObject(
    content::RenderFrame* render_frame) {
  // Make sure every page will get a script context created.
  render_frame->GetWebFrame()->ExecuteScript(blink::WebScriptSource("void 0"));
}

std::unique_ptr<blink::WebSpeechSynthesizer>
RendererClientBase::OverrideSpeechSynthesizer(
    blink::WebSpeechSynthesizerClient* client) {
#if BUILDFLAG(ENABLE_TTS)
  return std::make_unique<TtsDispatcher>(client);
#else
  return nullptr;
#endif
}

bool RendererClientBase::OverrideCreatePlugin(
    content::RenderFrame* render_frame,
    const blink::WebPluginParams& params,
    blink::WebPlugin** plugin) {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (params.mime_type.Utf8() == content::kBrowserPluginMimeType ||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
      params.mime_type.Utf8() == kPdfPluginMimeType ||
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)
      command_line->HasSwitch(switches::kEnablePlugins))
    return false;

  *plugin = nullptr;
  return true;
}

void RendererClientBase::AddSupportedKeySystems(
    std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) {
#if defined(WIDEVINE_CDM_AVAILABLE)
  key_systems_provider_.AddSupportedKeySystems(key_systems);
#endif
}

bool RendererClientBase::IsKeySystemsUpdateNeeded() {
#if defined(WIDEVINE_CDM_AVAILABLE)
  return key_systems_provider_.IsKeySystemsUpdateNeeded();
#else
  return false;
#endif
}

v8::Local<v8::Context> RendererClientBase::GetContext(
    blink::WebLocalFrame* frame,
    v8::Isolate* isolate) const {
  if (isolated_world())
    return frame->WorldScriptContext(isolate, World::ISOLATED_WORLD);
  else
    return frame->MainWorldScriptContext();
}

}  // namespace atom
<commit_msg>fix: preserve background color through reload (#15105)<commit_after>// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/renderer/renderer_client_base.h"

#include <memory>
#include <string>
#include <vector>

#include "atom/common/color_util.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_autofill_agent.h"
#include "atom/renderer/atom_render_frame_observer.h"
#include "atom/renderer/atom_render_view_observer.h"
#include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/preferences_manager.h"
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "electron/buildflags/buildflags.h"
#include "native_mate/dictionary.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_custom_element.h"  // NOLINT(build/include_alpha)
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"

#if defined(OS_MACOSX)
#include "base/strings/sys_string_conversions.h"
#endif

#if defined(OS_WIN)
#include <shlobj.h>
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "atom/common/atom_constants.h"
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)

#if BUILDFLAG(ENABLE_PEPPER_FLASH)
#include "chrome/renderer/pepper/pepper_helper.h"
#endif  // BUILDFLAG(ENABLE_PEPPER_FLASH)

#if BUILDFLAG(ENABLE_TTS)
#include "chrome/renderer/tts_dispatcher.h"
#endif  // BUILDFLAG(ENABLE_TTS)

#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h"
#include "components/printing/renderer/print_render_frame_helper.h"
#endif  // BUILDFLAG(ENABLE_PRINTING)

namespace atom {

namespace {

v8::Local<v8::Value> GetRenderProcessPreferences(
    const PreferencesManager* preferences_manager,
    v8::Isolate* isolate) {
  if (preferences_manager->preferences())
    return mate::ConvertToV8(isolate, *preferences_manager->preferences());
  else
    return v8::Null(isolate);
}

std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
                                               const char* switch_name) {
  std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name);
  return base::SplitString(custom_schemes, ",", base::TRIM_WHITESPACE,
                           base::SPLIT_WANT_NONEMPTY);
}

void SetHiddenValue(v8::Handle<v8::Context> context,
                    const base::StringPiece& key,
                    v8::Local<v8::Value> value) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::Local<v8::Private> privateKey =
      v8::Private::ForApi(isolate, mate::StringToV8(isolate, key));
  context->Global()->SetPrivate(context, privateKey, value);
}

}  // namespace

RendererClientBase::RendererClientBase() {
  auto* command_line = base::CommandLine::ForCurrentProcess();
  // Parse --standard-schemes=scheme1,scheme2
  std::vector<std::string> standard_schemes_list =
      ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);
  for (const std::string& scheme : standard_schemes_list)
    url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
  isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kContextIsolation);
  // We rely on the unique process host id which is notified to the
  // renderer process via command line switch from the content layer,
  // if this switch is removed from the content layer for some reason,
  // we should define our own.
  DCHECK(command_line->HasSwitch(::switches::kRendererClientId));
  renderer_client_id_ =
      command_line->GetSwitchValueASCII(::switches::kRendererClientId);
}

RendererClientBase::~RendererClientBase() {}

void RendererClientBase::DidCreateScriptContext(
    v8::Handle<v8::Context> context,
    content::RenderFrame* render_frame) {
  // global.setHidden("contextId", `${processHostId}-${++next_context_id_}`)
  auto context_id = base::StringPrintf(
      "%s-%" PRId64, renderer_client_id_.c_str(), ++next_context_id_);
  v8::Isolate* isolate = context->GetIsolate();
  SetHiddenValue(context, "contextId", mate::ConvertToV8(isolate, context_id));

  auto* command_line = base::CommandLine::ForCurrentProcess();
  bool enableRemoteModule =
      !command_line->HasSwitch(switches::kDisableRemoteModule);
  SetHiddenValue(context, "enableRemoteModule",
                 mate::ConvertToV8(isolate, enableRemoteModule));
}

void RendererClientBase::AddRenderBindings(
    v8::Isolate* isolate,
    v8::Local<v8::Object> binding_object) {
  mate::Dictionary dict(isolate, binding_object);
  dict.SetMethod(
      "getRenderProcessPreferences",
      base::Bind(GetRenderProcessPreferences, preferences_manager_.get()));
}

void RendererClientBase::RenderThreadStarted() {
  auto* command_line = base::CommandLine::ForCurrentProcess();

  blink::WebCustomElement::AddEmbedderCustomElementName("webview");
  blink::WebCustomElement::AddEmbedderCustomElementName("browserplugin");

  WTF::String extension_scheme("chrome-extension");
  // Extension resources are HTTP-like and safe to expose to the fetch API. The
  // rules for the fetch API are consistent with XHR.
  blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(
      extension_scheme);
  // Extension resources, when loaded as the top-level document, should bypass
  // Blink's strict first-party origin checks.
  blink::SchemeRegistry::RegisterURLSchemeAsFirstPartyWhenTopLevel(
      extension_scheme);
  // In Chrome we should set extension's origins to match the pages they can
  // work on, but in Electron currently we just let extensions do anything.
  blink::SchemeRegistry::RegisterURLSchemeAsSecure(extension_scheme);
  blink::SchemeRegistry::RegisterURLSchemeAsCORSEnabled(extension_scheme);
  blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
      extension_scheme);

  // Parse --secure-schemes=scheme1,scheme2
  std::vector<std::string> secure_schemes_list =
      ParseSchemesCLISwitch(command_line, switches::kSecureSchemes);
  for (const std::string& scheme : secure_schemes_list)
    blink::SchemeRegistry::RegisterURLSchemeAsSecure(
        WTF::String::FromUTF8(scheme.data(), scheme.length()));

  // Allow file scheme to handle service worker by default.
  // FIXME(zcbenz): Can this be moved elsewhere?
  blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
  blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file");

  preferences_manager_.reset(new PreferencesManager);

#if defined(OS_WIN)
  // Set ApplicationUserModelID in renderer process.
  base::string16 app_id =
      command_line->GetSwitchValueNative(switches::kAppUserModelId);
  if (!app_id.empty()) {
    SetCurrentProcessExplicitAppUserModelID(app_id.c_str());
  }
#endif
}

void RendererClientBase::RenderFrameCreated(
    content::RenderFrame* render_frame) {
#if defined(TOOLKIT_VIEWS)
  new AutofillAgent(render_frame);
#endif
#if BUILDFLAG(ENABLE_PEPPER_FLASH)
  new PepperHelper(render_frame);
#endif
  new ContentSettingsObserver(render_frame);
#if BUILDFLAG(ENABLE_PRINTING)
  new printing::PrintRenderFrameHelper(
      render_frame, std::make_unique<ChromePrintRenderFrameHelperDelegate>());
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
  // Allow access to file scheme from pdf viewer.
  blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(
      GURL(kPdfViewerUIOrigin), "file", "", true);
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)

  content::RenderView* render_view = render_frame->GetRenderView();
  if (render_frame->IsMainFrame() && render_view) {
    blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
    if (web_frame_widget) {
      base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
      if (cmd->HasSwitch(switches::kGuestInstanceID)) {  // webview.
        web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
      } else {  // normal window.
        std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
        SkColor color =
            name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
        web_frame_widget->SetBaseBackgroundColor(color);
      }
    }
  }
}

void RendererClientBase::RenderViewCreated(content::RenderView* render_view) {
  new AtomRenderViewObserver(render_view);
}

void RendererClientBase::DidClearWindowObject(
    content::RenderFrame* render_frame) {
  // Make sure every page will get a script context created.
  render_frame->GetWebFrame()->ExecuteScript(blink::WebScriptSource("void 0"));
}

std::unique_ptr<blink::WebSpeechSynthesizer>
RendererClientBase::OverrideSpeechSynthesizer(
    blink::WebSpeechSynthesizerClient* client) {
#if BUILDFLAG(ENABLE_TTS)
  return std::make_unique<TtsDispatcher>(client);
#else
  return nullptr;
#endif
}

bool RendererClientBase::OverrideCreatePlugin(
    content::RenderFrame* render_frame,
    const blink::WebPluginParams& params,
    blink::WebPlugin** plugin) {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (params.mime_type.Utf8() == content::kBrowserPluginMimeType ||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
      params.mime_type.Utf8() == kPdfPluginMimeType ||
#endif  // BUILDFLAG(ENABLE_PDF_VIEWER)
      command_line->HasSwitch(switches::kEnablePlugins))
    return false;

  *plugin = nullptr;
  return true;
}

void RendererClientBase::AddSupportedKeySystems(
    std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) {
#if defined(WIDEVINE_CDM_AVAILABLE)
  key_systems_provider_.AddSupportedKeySystems(key_systems);
#endif
}

bool RendererClientBase::IsKeySystemsUpdateNeeded() {
#if defined(WIDEVINE_CDM_AVAILABLE)
  return key_systems_provider_.IsKeySystemsUpdateNeeded();
#else
  return false;
#endif
}

v8::Local<v8::Context> RendererClientBase::GetContext(
    blink::WebLocalFrame* frame,
    v8::Isolate* isolate) const {
  if (isolated_world())
    return frame->WorldScriptContext(isolate, World::ISOLATED_WORLD);
  else
    return frame->MainWorldScriptContext();
}

}  // namespace atom
<|endoftext|>