<commit_before>///
/// @file   cmdoptions.cpp
/// @brief  Parse command-line options for the primesieve console
///         (terminal) application.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.hpp>
#include "cmdoptions.hpp"
#include "calculator.hpp"

#include <string>
#include <map>
#include <cstddef>
#include <stdint.h>

void help();
void version();

using namespace std;
using namespace primesieve;

namespace {

/// Command-line option
/// e.g. str = "--threads", value = "4"
struct Option
{
  string str;
  string value;
  template <typename T>
  T getValue() const
  {
    return calculator::eval<T>(value);
  }
};

enum OptionID
{
  OPTION_COUNT,
  OPTION_HELP,
  OPTION_NTHPRIME,
  OPTION_NO_STATUS,
  OPTION_NUMBER,
  OPTION_DISTANCE,
  OPTION_PRINT,
  OPTION_QUIET,
  OPTION_SIZE,
  OPTION_THREADS,
  OPTION_TIME,
  OPTION_VERSION
};

/// Command-line options
map<string, OptionID> optionMap =
{
  { "-c",          OPTION_COUNT },
  { "--count",     OPTION_COUNT },
  { "-h",          OPTION_HELP },
  { "--help",      OPTION_HELP },
  { "-n",          OPTION_NTHPRIME },
  { "--nthprime",  OPTION_NTHPRIME },
  { "--no-status", OPTION_NO_STATUS },
  { "--number",    OPTION_NUMBER },
  { "-d",          OPTION_DISTANCE },
  { "--dist",      OPTION_DISTANCE },
  { "-p",          OPTION_PRINT },
  { "--print",     OPTION_PRINT },
  { "-q",          OPTION_QUIET },
  { "--quiet",     OPTION_QUIET },
  { "-s",          OPTION_SIZE },
  { "--size",      OPTION_SIZE },
  { "-t",          OPTION_THREADS },
  { "--threads",   OPTION_THREADS },
  { "--time",      OPTION_TIME },
  { "-v",          OPTION_VERSION },
  { "--version",   OPTION_VERSION }
};

int check(int primeType)
{
  primeType--;

  if (primeType < 0 ||
      primeType > 5)
    help();

  return primeType;
}

void optionPrint(Option& opt,
                 CmdOptions& opts)
{
  opts.quiet = true;

  if (opt.value.empty())
   opt.value = "1";

  int i = opt.getValue<int>();
  i = check(i);
  opts.flags |= PrimeSieve::PRINT_PRIMES << i;
}

void optionCount(Option& opt,
                 CmdOptions& opts)
{
  if (opt.value.empty())
    opt.value = "1";

  int n = opt.getValue<int>();

  for (; n > 0; n /= 10)
  {
    int i = check(n % 10);
    opts.flags |= PrimeSieve::COUNT_PRIMES << i;
  }
}

/// e.g. "--threads=8"
/// -> opt.str = "--threads"
/// -> opt.value = "8"
///
Option makeOption(const string& str)
{
  Option opt;
  size_t delimiter = str.find_first_of("=0123456789");

  if (delimiter == string::npos)
    opt.str = str;
  else
  {
    opt.str = str.substr(0, delimiter);
    opt.value = str.substr(delimiter + (str.at(delimiter) == '=' ? 1 : 0));
  }

  if (opt.str.empty() && !opt.value.empty())
    opt.str = "--number";
  if (!optionMap.count(opt.str))
    opt.str = "--help";

  return opt;
}

} // namespace

CmdOptions parseOptions(int argc, char* argv[])
{
  CmdOptions opts;

  for (int i = 1; i < argc; i++)
  {
    Option opt = makeOption(argv[i]);

    switch (optionMap[opt.str])
    {
      case OPTION_COUNT:     optionCount(opt, opts); break;
      case OPTION_PRINT:     optionPrint(opt, opts); break;
      case OPTION_SIZE:      opts.sieveSize = opt.getValue<int>(); break;
      case OPTION_THREADS:   opts.threads = opt.getValue<int>(); break;
      case OPTION_QUIET:     opts.quiet = true; break;
      case OPTION_NTHPRIME:  opts.nthPrime = true; break;
      case OPTION_NO_STATUS: opts.status = false; break;
      case OPTION_TIME:      opts.time = true; break;
      case OPTION_NUMBER:    opts.numbers.push_back(opt.getValue<uint64_t>()); break;
      case OPTION_DISTANCE:  opts.numbers.push_back(opt.getValue<uint64_t>() + opts.numbers[0]); break;
      case OPTION_VERSION:   version(); break;
      case OPTION_HELP:      help(); break;
    }
  }

  if (opts.numbers.size() < 1 ||
      opts.numbers.size() > 2)
    help();

  if (opts.quiet)
    opts.status = false;
  else
    opts.time = true;

  return opts;
}
<commit_msg>Fix code alignment<commit_after>///
/// @file   cmdoptions.cpp
/// @brief  Parse command-line options for the primesieve console
///         (terminal) application.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.hpp>
#include "cmdoptions.hpp"
#include "calculator.hpp"

#include <string>
#include <map>
#include <cstddef>
#include <stdint.h>

void help();
void version();

using namespace std;
using namespace primesieve;

namespace {

/// Command-line option
/// e.g. str = "--threads", value = "4"
struct Option
{
  string str;
  string value;
  template <typename T>
  T getValue() const
  {
    return calculator::eval<T>(value);
  }
};

enum OptionID
{
  OPTION_COUNT,
  OPTION_HELP,
  OPTION_NTHPRIME,
  OPTION_NO_STATUS,
  OPTION_NUMBER,
  OPTION_DISTANCE,
  OPTION_PRINT,
  OPTION_QUIET,
  OPTION_SIZE,
  OPTION_THREADS,
  OPTION_TIME,
  OPTION_VERSION
};

/// Command-line options
map<string, OptionID> optionMap =
{
  { "-c",          OPTION_COUNT },
  { "--count",     OPTION_COUNT },
  { "-h",          OPTION_HELP },
  { "--help",      OPTION_HELP },
  { "-n",          OPTION_NTHPRIME },
  { "--nthprime",  OPTION_NTHPRIME },
  { "--no-status", OPTION_NO_STATUS },
  { "--number",    OPTION_NUMBER },
  { "-d",          OPTION_DISTANCE },
  { "--dist",      OPTION_DISTANCE },
  { "-p",          OPTION_PRINT },
  { "--print",     OPTION_PRINT },
  { "-q",          OPTION_QUIET },
  { "--quiet",     OPTION_QUIET },
  { "-s",          OPTION_SIZE },
  { "--size",      OPTION_SIZE },
  { "-t",          OPTION_THREADS },
  { "--threads",   OPTION_THREADS },
  { "--time",      OPTION_TIME },
  { "-v",          OPTION_VERSION },
  { "--version",   OPTION_VERSION }
};

int check(int primeType)
{
  primeType--;

  if (primeType < 0 ||
      primeType > 5)
    help();

  return primeType;
}

void optionPrint(Option& opt,
                 CmdOptions& opts)
{
  opts.quiet = true;

  if (opt.value.empty())
    opt.value = "1";

  int i = opt.getValue<int>();
  i = check(i);
  opts.flags |= PrimeSieve::PRINT_PRIMES << i;
}

void optionCount(Option& opt,
                 CmdOptions& opts)
{
  if (opt.value.empty())
    opt.value = "1";

  int n = opt.getValue<int>();

  for (; n > 0; n /= 10)
  {
    int i = check(n % 10);
    opts.flags |= PrimeSieve::COUNT_PRIMES << i;
  }
}

/// e.g. "--threads=8"
/// -> opt.str = "--threads"
/// -> opt.value = "8"
///
Option makeOption(const string& str)
{
  Option opt;
  size_t delimiter = str.find_first_of("=0123456789");

  if (delimiter == string::npos)
    opt.str = str;
  else
  {
    opt.str = str.substr(0, delimiter);
    opt.value = str.substr(delimiter + (str.at(delimiter) == '=' ? 1 : 0));
  }

  if (opt.str.empty() && !opt.value.empty())
    opt.str = "--number";
  if (!optionMap.count(opt.str))
    opt.str = "--help";

  return opt;
}

} // namespace

CmdOptions parseOptions(int argc, char* argv[])
{
  CmdOptions opts;

  for (int i = 1; i < argc; i++)
  {
    Option opt = makeOption(argv[i]);

    switch (optionMap[opt.str])
    {
      case OPTION_COUNT:     optionCount(opt, opts); break;
      case OPTION_PRINT:     optionPrint(opt, opts); break;
      case OPTION_SIZE:      opts.sieveSize = opt.getValue<int>(); break;
      case OPTION_THREADS:   opts.threads = opt.getValue<int>(); break;
      case OPTION_QUIET:     opts.quiet = true; break;
      case OPTION_NTHPRIME:  opts.nthPrime = true; break;
      case OPTION_NO_STATUS: opts.status = false; break;
      case OPTION_TIME:      opts.time = true; break;
      case OPTION_NUMBER:    opts.numbers.push_back(opt.getValue<uint64_t>()); break;
      case OPTION_DISTANCE:  opts.numbers.push_back(opt.getValue<uint64_t>() + opts.numbers[0]); break;
      case OPTION_VERSION:   version(); break;
      case OPTION_HELP:      help(); break;
    }
  }

  if (opts.numbers.size() < 1 ||
      opts.numbers.size() > 2)
    help();

  if (opts.quiet)
    opts.status = false;
  else
    opts.time = true;

  return opts;
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_META_PARTIALS_RETURN_TYPE_HPP
#define STAN_MATH_PRIM_SCAL_META_PARTIALS_RETURN_TYPE_HPP

#include <stan/math/prim/scal/meta/partials_type.hpp>
#include <stan/math/prim/scal/meta/scalar_type.hpp>
#include <boost/math/tools/promotion.hpp>

namespace stan {

/**
 * Template metaprogram to calculate the base scalar return type for partial
 * derivatives. The metaprogram can take an arbitrary number of template
 * parameters.
 *
 * All C++ primitive types (except long double) are automatically
 * promoted to double.
 *
 * partials_return_type<...> is a class defining a single public
 * typedef type that is double for containers
 * of base C++ types (except for long double) as well as
 * containers of vars.
 *
 * partials_type<fvar<var> >::type is not var.
 *
 * Example usage:
 *  - return_type<int,double,float>::type is double
 *  - return_type<double,var>::type is double
 *
 * @tparam T (required) A type
 * @tparam T_pack (optional) A parameter pack containing further types.
 */

template <typename T, typename... T_pack>
struct partials_return_type {
  typedef typename boost::math::tools::promote_args<
      double, typename partials_type<typename scalar_type<T>::type>::type,
      typename partials_return_type<T_pack...>::type>::type type;
};

template <typename T>
struct partials_return_type<T> {
  typedef typename boost::math::tools::promote_args<
      double, typename partials_type<typename scalar_type<T>::type>::type>::type
      type;
};

}  // namespace stan
#endif
<commit_msg>Found error in fvar includes in partials_return_type. Fixed Doxygen errors.<commit_after>#ifndef STAN_MATH_PRIM_SCAL_META_PARTIALS_RETURN_TYPE_HPP
#define STAN_MATH_PRIM_SCAL_META_PARTIALS_RETURN_TYPE_HPP

#include <stan/math/prim/scal/meta/partials_type.hpp>
#include <stan/math/rev/core/var.hpp>
#include <stan/math/rev/scal/meta/partials_type.hpp>
#include <stan/math/fwd/core/fvar.hpp>
#include <stan/math/fwd/scal/meta/partials_type.hpp>
#include <stan/math/prim/scal/meta/scalar_type.hpp>
#include <boost/math/tools/promotion.hpp>

namespace stan {

  /**
   * Template metaprogram to calculate the base scalar return type resulting
   * from promoting all the scalar types of the template parameters. The
   * metaprogram can take an arbitrary number of template parameters.
   *
   * All C++ primitive types (except long double) are automatically
   * promoted to double.
   *
   * partials_return_type<...> is a class defining a single public
   * typedef type that is var if there is a forward
   * mode variable type and is double otherwise (this is the most
   * common case).
   * Example usage:
   *
   *  - return_type<int,double,var>::type is double
   *  - The same thing with var replaced with a forward mode type
   *  like fvar<T> will return T.
   *
   * @tparam T (required) A type
   * @tparam T_pack (optional) A parameter pack containing further types.
   */

template <typename T, typename... T_pack>
struct partials_return_type {
  typedef typename boost::math::tools::promote_args<
      double, typename partials_type<typename scalar_type<T>::type>::type,
      typename partials_return_type<T_pack...>::type>::type type;
};

template <typename T>
struct partials_return_type<T> {
  typedef typename boost::math::tools::promote_args<
      double, typename partials_type<typename scalar_type<T>::type>::type>::type
      type;
};

}  // namespace stan
#endif
<|endoftext|>


<commit_before>#include <mist/procs.h>
#include <mist/config.h>
#include <mist/timing.h>
#include "controller_streams.h"
#include "controller_storage.h"
#include <sys/stat.h>

namespace Controller {

  std::map<std::string, int> lastBuffer; ///< Last moment of contact with all buffers.

  bool streamsEqual(JSON::Value & one, JSON::Value & two){
    if (!one.isMember("source") || !two.isMember("source") || one["source"] != two["source"]){
      return false;
    }
    return true;
  }

  void startStream(std::string name, JSON::Value & data){
    data["online"] = (std::string)"Checking...";
    data.removeMember("error");
    std::string URL;
    if (data.isMember("channel") && data["channel"].isMember("URL")){
      URL = data["channel"]["URL"].asString();
    }
    if (data.isMember("source")){
      URL = data["source"].asString();
    }
    std::string cmd1, cmd2, cmd3;
    if (URL == ""){
      Log("STRM", "Error for stream " + name + "! Source parameter missing.");
      data["error"] = "Missing source parameter!";
      return;
    }
    if (URL.substr(0, 4) == "push"){
      std::string pusher = URL.substr(7);
      cmd2 = "MistBuffer -s " + name + " " + pusher;
      Util::Procs::Start(name, Util::getMyPath() + cmd2);
      Log("BUFF", "(re)starting stream buffer " + name + " for push data from " + pusher);
    }else{
      if (URL.substr(0, 1) == "/"){
        struct stat fileinfo;
        if (stat(URL.c_str(), &fileinfo) != 0 || S_ISDIR(fileinfo.st_mode)){
          Log("BUFF", "Warning for VoD stream " + name + "! File not found: " + URL);
          data["error"] = "Not found: " + URL;
          data["online"] = 0;
          return;
        }
        cmd1 = "cat " + URL;
        data["error"] = "Available";
        data["online"] = 2;
        return; //MistPlayer handles VoD
      }else{
        cmd1 = "ffmpeg -re -async 2 -i " + URL + " -f flv -";
        cmd2 = "MistFLV2DTSC";
      }
      if (data.isMember("DVR") && data["DVR"].asInt() > 0){
        data["DVR"] = data["DVR"].asInt();
        cmd3 = "MistBuffer -t " + data["DVR"].asString() + " -s " + name;
      }else{
        cmd3 = "MistBuffer -s " + name;
      }
      if (cmd2 != ""){
        Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd2, Util::getMyPath() + cmd3);
        Log("BUFF", "(re)starting stream buffer " + name + " for ffmpeg data: " + cmd1);
      }else{
        Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd3);
        Log("BUFF", "(re)starting stream buffer " + name + " using input file " + URL);
      }
    }
  }

  void CheckAllStreams(JSON::Value & data){
    long long int currTime = Util::epoch();
    for (JSON::ObjIter jit = data.ObjBegin(); jit != data.ObjEnd(); jit++){
      if ( !Util::Procs::isActive(jit->first)){
        startStream(jit->first, jit->second);
      }
      if (currTime - lastBuffer[jit->first] > 5){
        if (jit->second.isMember("source") && jit->second["source"].asString().substr(0, 1) == "/" && jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
          jit->second["online"] = 2;
        }else{
          if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
            jit->second.removeMember("error");
          }
          jit->second["online"] = 0;
        }
      }else{
        if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
          jit->second.removeMember("error");
        }
        jit->second["online"] = 1;
      }
    }
    static JSON::Value strlist;
    bool changed = false;
    if (strlist["config"] != Storage["config"]){
      strlist["config"] = Storage["config"];
      changed = true;
    }
    if (strlist["streams"] != Storage["streams"]){
      strlist["streams"] = Storage["streams"];
      changed = true;
    }
    if (changed){
      WriteFile("/tmp/mist/streamlist", strlist.toString());
    }
  }

  void CheckStreams(JSON::Value & in, JSON::Value & out){
    bool changed = false;

    //check for new streams and updates
    for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
      if (out.isMember(jit->first)){
        if ( !streamsEqual(jit->second, out[jit->first])){
          Log("STRM", std::string("Updated stream ") + jit->first);
          Util::Procs::Stop(jit->first);
          startStream(jit->first, jit->second);
        }
      }else{
        Log("STRM", std::string("New stream ") + jit->first);
        startStream(jit->first, jit->second);
      }
    }

    //check for deleted streams
    for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){
      if ( !in.isMember(jit->first)){
        Log("STRM", std::string("Deleted stream ") + jit->first);
        Util::Procs::Stop(jit->first);
      }
    }

    //update old-style configurations to new-style
    for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
      if (jit->second.isMember("channel")){
        if ( !jit->second.isMember("source")){
          jit->second["source"] = jit->second["channel"]["URL"];
        }
        jit->second.removeMember("channel");
      }
      if (jit->second.isMember("preset")){
        jit->second.removeMember("preset");
      }
    }

    out = in;
  }

} //Controller namespace
<commit_msg>Fixed DVR setting parsing for push:// streams.<commit_after>#include <mist/procs.h>
#include <mist/config.h>
#include <mist/timing.h>
#include "controller_streams.h"
#include "controller_storage.h"
#include <sys/stat.h>

namespace Controller {

  std::map<std::string, int> lastBuffer; ///< Last moment of contact with all buffers.

  bool streamsEqual(JSON::Value & one, JSON::Value & two){
    if (!one.isMember("source") || !two.isMember("source") || one["source"] != two["source"]){
      return false;
    }
    return true;
  }

  void startStream(std::string name, JSON::Value & data){
    data["online"] = (std::string)"Checking...";
    data.removeMember("error");
    std::string URL;
    if (data.isMember("channel") && data["channel"].isMember("URL")){
      URL = data["channel"]["URL"].asString();
    }
    if (data.isMember("source")){
      URL = data["source"].asString();
    }
    std::string cmd1, cmd2, cmd3;
    if (URL == ""){
      Log("STRM", "Error for stream " + name + "! Source parameter missing.");
      data["error"] = "Missing source parameter!";
      return;
    }
    if (URL.substr(0, 4) == "push"){
      std::string pusher = URL.substr(7);
      if (data.isMember("DVR") && data["DVR"].asInt() > 0){
        data["DVR"] = data["DVR"].asInt();
        cmd2 = "MistBuffer -t " + data["DVR"].asString() + " -s " + name + " " + pusher;
      }else{
        cmd2 = "MistBuffer -s " + name + " " + pusher;
      }
      Util::Procs::Start(name, Util::getMyPath() + cmd2);
      Log("BUFF", "(re)starting stream buffer " + name + " for push data from " + pusher);
    }else{
      if (URL.substr(0, 1) == "/"){
        struct stat fileinfo;
        if (stat(URL.c_str(), &fileinfo) != 0 || S_ISDIR(fileinfo.st_mode)){
          Log("BUFF", "Warning for VoD stream " + name + "! File not found: " + URL);
          data["error"] = "Not found: " + URL;
          data["online"] = 0;
          return;
        }
        cmd1 = "cat " + URL;
        data["error"] = "Available";
        data["online"] = 2;
        return; //MistPlayer handles VoD
      }else{
        cmd1 = "ffmpeg -re -async 2 -i " + URL + " -f flv -";
        cmd2 = "MistFLV2DTSC";
      }
      if (data.isMember("DVR") && data["DVR"].asInt() > 0){
        data["DVR"] = data["DVR"].asInt();
        cmd3 = "MistBuffer -t " + data["DVR"].asString() + " -s " + name;
      }else{
        cmd3 = "MistBuffer -s " + name;
      }
      if (cmd2 != ""){
        Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd2, Util::getMyPath() + cmd3);
        Log("BUFF", "(re)starting stream buffer " + name + " for ffmpeg data: " + cmd1);
      }else{
        Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd3);
        Log("BUFF", "(re)starting stream buffer " + name + " using input file " + URL);
      }
    }
  }

  void CheckAllStreams(JSON::Value & data){
    long long int currTime = Util::epoch();
    for (JSON::ObjIter jit = data.ObjBegin(); jit != data.ObjEnd(); jit++){
      if ( !Util::Procs::isActive(jit->first)){
        startStream(jit->first, jit->second);
      }
      if (currTime - lastBuffer[jit->first] > 5){
        if (jit->second.isMember("source") && jit->second["source"].asString().substr(0, 1) == "/" && jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
          jit->second["online"] = 2;
        }else{
          if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
            jit->second.removeMember("error");
          }
          jit->second["online"] = 0;
        }
      }else{
        if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
          jit->second.removeMember("error");
        }
        jit->second["online"] = 1;
      }
    }
    static JSON::Value strlist;
    bool changed = false;
    if (strlist["config"] != Storage["config"]){
      strlist["config"] = Storage["config"];
      changed = true;
    }
    if (strlist["streams"] != Storage["streams"]){
      strlist["streams"] = Storage["streams"];
      changed = true;
    }
    if (changed){
      WriteFile("/tmp/mist/streamlist", strlist.toString());
    }
  }

  void CheckStreams(JSON::Value & in, JSON::Value & out){
    bool changed = false;

    //check for new streams and updates
    for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
      if (out.isMember(jit->first)){
        if ( !streamsEqual(jit->second, out[jit->first])){
          Log("STRM", std::string("Updated stream ") + jit->first);
          Util::Procs::Stop(jit->first);
          startStream(jit->first, jit->second);
        }
      }else{
        Log("STRM", std::string("New stream ") + jit->first);
        startStream(jit->first, jit->second);
      }
    }

    //check for deleted streams
    for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){
      if ( !in.isMember(jit->first)){
        Log("STRM", std::string("Deleted stream ") + jit->first);
        Util::Procs::Stop(jit->first);
      }
    }

    //update old-style configurations to new-style
    for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
      if (jit->second.isMember("channel")){
        if ( !jit->second.isMember("source")){
          jit->second["source"] = jit->second["channel"]["URL"];
        }
        jit->second.removeMember("channel");
      }
      if (jit->second.isMember("preset")){
        jit->second.removeMember("preset");
      }
    }

    out = in;
  }

} //Controller namespace
<|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.
*/

#include "common.h"

// implementation header
#include "EventHandler.h"

// system headers
#include <assert.h>
#include <algorithm>

// common headers
#include "bzfio.h"
#include "GfxBlock.h"
#include "OpenGLPassState.h"

using std::string;
using std::vector;
using std::set;
using std::map;

EventHandler eventHandler;

/******************************************************************************/
/******************************************************************************/

// it's easier to read with named booleans
static const int REQ_FULL_READ  = (1 << 0);
static const int REQ_INPUT_CTRL = (1 << 1);

void EventHandler::SetupEvent(const string& eName, EventClientList* list,
                              int bits, bool reversed)
{
  list->set_reversed(reversed);
  assert(eventMap.find(eName) == eventMap.end());
  const bool reqFullRead  = ((bits & REQ_FULL_READ) ? true : false);
  const bool reqInputCtrl = ((bits & REQ_INPUT_CTRL) ? true : false);
  eventMap[eName] = EventInfo(eName, list, reqFullRead, reqInputCtrl, reversed);
}

#define SETUP_EVENT(name, ...) \
  SetupEvent(#name, &list ## name, ## __VA_ARGS__)

/******************************************************************************/
/******************************************************************************/

EventHandler::EventHandler()
{
  mouseOwner = NULL;

  SETUP_EVENT(Update);

  SETUP_EVENT(BZDBChange);

  SETUP_EVENT(RecvChatMsg);
  SETUP_EVENT(RecvLuaData);

  SETUP_EVENT(ServerJoined);
  SETUP_EVENT(ServerParted);

  SETUP_EVENT(PlayerAdded);
  SETUP_EVENT(PlayerRemoved);
  SETUP_EVENT(PlayerSpawned);
  SETUP_EVENT(PlayerKilled);
  SETUP_EVENT(PlayerJumped);
  SETUP_EVENT(PlayerLanded);
  SETUP_EVENT(PlayerTeleported);
  SETUP_EVENT(PlayerTeamChange);
  SETUP_EVENT(PlayerScoreChange);

  SETUP_EVENT(ShotAdded);
  SETUP_EVENT(ShotRemoved);

  SETUP_EVENT(FlagAdded);
  SETUP_EVENT(FlagRemoved);
  SETUP_EVENT(FlagGrabbed);
  SETUP_EVENT(FlagDropped);
  SETUP_EVENT(FlagCaptured);
  SETUP_EVENT(FlagTransferred);

  SETUP_EVENT(ViewResize);
  SETUP_EVENT(GLContextInit);
  SETUP_EVENT(GLContextFree);

  SETUP_EVENT(DrawGenesis,     0, true);
  SETUP_EVENT(DrawWorldStart,  0, true);
  SETUP_EVENT(DrawWorld,       0, true);
  SETUP_EVENT(DrawWorldAlpha,  0, true);
  SETUP_EVENT(DrawWorldShadow, 0, true);
  SETUP_EVENT(DrawScreenStart, 0, true);
  SETUP_EVENT(DrawScreen,      0, true);
  SETUP_EVENT(DrawRadar,       0, true);

  SETUP_EVENT(KeyPress,     REQ_INPUT_CTRL);
  SETUP_EVENT(KeyRelease,   REQ_INPUT_CTRL);
  SETUP_EVENT(MousePress,   REQ_INPUT_CTRL);
  SETUP_EVENT(MouseMove,    REQ_INPUT_CTRL);
  SETUP_EVENT(MouseRelease, REQ_INPUT_CTRL);
  SETUP_EVENT(MouseWheel,   REQ_INPUT_CTRL);
  SETUP_EVENT(IsAbove,      REQ_INPUT_CTRL);
  SETUP_EVENT(GetTooltip,   REQ_INPUT_CTRL);

  SETUP_EVENT(WordComplete, REQ_INPUT_CTRL);
}

EventHandler::~EventHandler()
{
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::AddClient(EventClient* ec)
{
  if (ec->GetName().empty()) {
    logDebugMessage(0, "EventClients must have valid names");
    return;
  }

  if (!clients.insert(ec)) {
    logDebugMessage(0, "Duplicate EventClient name: %s\n");
    return;
  }

  // add events that the clients wants (and is allowed to use)
  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    const EventInfo& ei = it->second;
    if (ei.IsManaged() && CanUseEvent(ec, ei) && ec->WantsEvent(ei.name)) {
      ei.GetList()->insert(ec);
    }
  }
}

void EventHandler::RemoveClient(EventClient* ec)
{
  if (mouseOwner == ec) {
    mouseOwner = NULL;
  }

  clients.remove(ec);

  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    const EventInfo& ei = it->second;
    if (ei.IsManaged() && (ei.GetList() != NULL)) {
      ei.GetList()->remove(ec);
    }
  }

  GfxBlockMgr::removeClient(ec);

//???  RemoveClientActions(ec, syncedActions);
//???  RemoveClientActions(ec, unsyncedActions);
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::GetEventList(vector<string>& list) const
{
  list.clear();
  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    list.push_back(it->first);
  }
}

const EventHandler::EventInfo*
  EventHandler::GetEventInfo(const std::string& eName) const
{
  EventMap::const_iterator it = eventMap.find(eName);
  return (it != eventMap.end()) ? &(it->second) : NULL;
}

bool EventHandler::IsKnown(const string& eName) const
{
  return GetEventInfo(eName) != NULL;
}

bool EventHandler::IsManaged(const string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && (ei->GetList() != NULL);
}

bool EventHandler::IsReversed(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->IsReversed();
}

bool EventHandler::ReqFullRead(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->ReqFullRead();
}

bool EventHandler::ReqInputCtrl(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->ReqInputCtrl();
}

/******************************************************************************/
/******************************************************************************/

bool EventHandler::CanUseEvent(EventClient* ec, const EventInfo& ei) const
{
  if ((ei.ReqFullRead()  && !ec->HasFullRead()) ||
      (ei.ReqInputCtrl() && !ec->HasInputCtrl())) {
    return false;
  }
  return true;
}

bool EventHandler::InsertEvent(EventClient* ec, const string& ciName)
{
  EventMap::iterator it = eventMap.find(ciName);
  if (it == eventMap.end()) {
    return false;
  }
  const EventInfo& ei = it->second;
  EventClientList* ecList = ei.GetList();
  if (ecList == NULL) {
    return false;
  }
  if (!CanUseEvent(ec, ei)) {
    return false;
  }
  return ecList->insert(ec);
}

bool EventHandler::RemoveEvent(EventClient* ec, const string& ciName)
{
  EventMap::iterator it = eventMap.find(ciName);
  if ((it == eventMap.end()) || (it->second.GetList() == NULL)) {
    return false;
  }
  return it->second.GetList()->remove(ec);
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::RecvLuaData(int srcPlayerID, int srcScriptID,
                               int dstPlayerID, int dstScriptID,
                               int status, const std::string& data)
{
  EventClientList& list = listRecvLuaData;
  if (list.empty()) { return; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if ((dstScriptID == 0) || (dstScriptID == ec->GetOrder())) {
      ec->RecvLuaData(srcPlayerID, srcScriptID,
                      dstPlayerID, dstScriptID,
                      status, data);
    }
  }
  list.finish();
}

/******************************************************************************/
/******************************************************************************/

#define DRAW_CALLIN(name)                 \
  void EventHandler:: name ()             \
  {                                       \
    EventClientList& list = list ## name; \
    if (list.empty()) { return; }         \
                                          \
    OpenGLPassState::Enable ## name ();   \
                                          \
    EventClient* ec = NULL;               \
    size_t i = 0;                         \
    list.start(i);                        \
    list.next(i, ec);                     \
    ec-> name ();                         \
                                          \
    while (list.next(i, ec)) {            \
      OpenGLPassState::Reset ## name ();  \
      ec-> name ();                       \
    }                                     \
    list.finish();                        \
                                          \
    OpenGLPassState::Disable ## name ();  \
  }

DRAW_CALLIN(DrawGenesis)
DRAW_CALLIN(DrawWorldStart)
DRAW_CALLIN(DrawWorld)
DRAW_CALLIN(DrawWorldAlpha)
DRAW_CALLIN(DrawWorldShadow)
DRAW_CALLIN(DrawScreenStart)
DRAW_CALLIN(DrawScreen)
DRAW_CALLIN(DrawRadar)

/******************************************************************************/
/******************************************************************************/

bool EventHandler::KeyPress(int key, bool isRepeat)
{
  EventClientList& list = listKeyPress;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->KeyPress(key, isRepeat)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::KeyRelease(int key)
{
  EventClientList& list = listKeyRelease;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->KeyRelease(key)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MousePress(int x, int y, int button)
{
  EventClientList& list = listMousePress;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MousePress(x, y, button)) {
      mouseOwner = ec;
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MouseRelease(int x, int y, int button)
{
  if (mouseOwner == NULL) {
    return false;
  }
  const bool retval = mouseOwner->MouseRelease(x, y, button);
  mouseOwner = NULL;
  return retval;
}

bool EventHandler::MouseMove(int x, int y)
{
  EventClientList& list = listMouseMove;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MouseMove(x, y) && (ec == mouseOwner)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MouseWheel(float value)
{
  EventClientList& list = listMouseWheel;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MouseWheel(value)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::IsAbove(int x, int y)
{
  EventClientList& list = listIsAbove;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->IsAbove(x, y)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

string EventHandler::GetTooltip(int x, int y)
{
  EventClientList& list = listGetTooltip;
  if (list.empty()) { return ""; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    const string tt = ec->GetTooltip(x, y);
    if (!tt.empty()) {
      list.finish();
      return tt;
    }
  }
  list.finish();
  return "";
}

void EventHandler::WordComplete(const string& line, set<string>& partials)
{
  EventClientList& list = listWordComplete;
  if (list.empty()) { return; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    set<string> safePartials;
    ec->WordComplete(line, safePartials);
    set<string>::const_iterator it;
    for (it = safePartials.begin(); it != safePartials.end(); ++it) {
      const string& partial = *it;
      if (!partial.empty()) {
        partials.insert(partial);
      }
    }
  }
  list.finish();
}

/******************************************************************************/
/******************************************************************************/
<commit_msg>* replaced the anonymous variadic macros<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.
*/

#include "common.h"

// implementation header
#include "EventHandler.h"

// system headers
#include <assert.h>
#include <algorithm>

// common headers
#include "bzfio.h"
#include "GfxBlock.h"
#include "OpenGLPassState.h"

using std::string;
using std::vector;
using std::set;
using std::map;

EventHandler eventHandler;

/******************************************************************************/
/******************************************************************************/

// it's easier to read with named booleans
static const int REQ_FULL_READ  = (1 << 0);
static const int REQ_INPUT_CTRL = (1 << 1);

void EventHandler::SetupEvent(const string& eName, EventClientList* list,
                              int bits, bool reversed)
{
  list->set_reversed(reversed);
  assert(eventMap.find(eName) == eventMap.end());
  const bool reqFullRead  = ((bits & REQ_FULL_READ) ? true : false);
  const bool reqInputCtrl = ((bits & REQ_INPUT_CTRL) ? true : false);
  eventMap[eName] = EventInfo(eName, list, reqFullRead, reqInputCtrl, reversed);
}

#define SETUP_EVENT(name, bits, reversed) \
  SetupEvent(#name, &list ## name, bits, reversed)

/******************************************************************************/
/******************************************************************************/

EventHandler::EventHandler()
{
  mouseOwner = NULL;

  SETUP_EVENT(Update, 0, false);

  SETUP_EVENT(BZDBChange, 0, false);

  SETUP_EVENT(RecvChatMsg, 0, false);
  SETUP_EVENT(RecvLuaData, 0, false);

  SETUP_EVENT(ServerJoined, 0, false);
  SETUP_EVENT(ServerParted, 0, false);

  SETUP_EVENT(PlayerAdded,       0, false);
  SETUP_EVENT(PlayerRemoved,     0, false);
  SETUP_EVENT(PlayerSpawned,     0, false);
  SETUP_EVENT(PlayerKilled,      0, false);
  SETUP_EVENT(PlayerJumped,      0, false);
  SETUP_EVENT(PlayerLanded,      0, false);
  SETUP_EVENT(PlayerTeleported,  0, false);
  SETUP_EVENT(PlayerTeamChange,  0, false);
  SETUP_EVENT(PlayerScoreChange, 0, false);

  SETUP_EVENT(ShotAdded,   0, false);
  SETUP_EVENT(ShotRemoved, 0, false);

  SETUP_EVENT(FlagAdded,       0, false);
  SETUP_EVENT(FlagRemoved,     0, false);
  SETUP_EVENT(FlagGrabbed,     0, false);
  SETUP_EVENT(FlagDropped,     0, false);
  SETUP_EVENT(FlagCaptured,    0, false);
  SETUP_EVENT(FlagTransferred, 0, false);

  SETUP_EVENT(ViewResize,    0, false);
  SETUP_EVENT(GLContextInit, 0, false);
  SETUP_EVENT(GLContextFree, 0, false);

  SETUP_EVENT(DrawGenesis,     0, true);
  SETUP_EVENT(DrawWorldStart,  0, true);
  SETUP_EVENT(DrawWorld,       0, true);
  SETUP_EVENT(DrawWorldAlpha,  0, true);
  SETUP_EVENT(DrawWorldShadow, 0, true);
  SETUP_EVENT(DrawScreenStart, 0, true);
  SETUP_EVENT(DrawScreen,      0, true);
  SETUP_EVENT(DrawRadar,       0, true);

  SETUP_EVENT(KeyPress,     REQ_INPUT_CTRL, false);
  SETUP_EVENT(KeyRelease,   REQ_INPUT_CTRL, false);
  SETUP_EVENT(MousePress,   REQ_INPUT_CTRL, false);
  SETUP_EVENT(MouseMove,    REQ_INPUT_CTRL, false);
  SETUP_EVENT(MouseRelease, REQ_INPUT_CTRL, false);
  SETUP_EVENT(MouseWheel,   REQ_INPUT_CTRL, false);
  SETUP_EVENT(IsAbove,      REQ_INPUT_CTRL, false);
  SETUP_EVENT(GetTooltip,   REQ_INPUT_CTRL, false);

  SETUP_EVENT(WordComplete, REQ_INPUT_CTRL, false);
}

EventHandler::~EventHandler()
{
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::AddClient(EventClient* ec)
{
  if (ec->GetName().empty()) {
    logDebugMessage(0, "EventClients must have valid names");
    return;
  }

  if (!clients.insert(ec)) {
    logDebugMessage(0, "Duplicate EventClient name: %s\n");
    return;
  }

  // add events that the clients wants (and is allowed to use)
  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    const EventInfo& ei = it->second;
    if (ei.IsManaged() && CanUseEvent(ec, ei) && ec->WantsEvent(ei.name)) {
      ei.GetList()->insert(ec);
    }
  }
}

void EventHandler::RemoveClient(EventClient* ec)
{
  if (mouseOwner == ec) {
    mouseOwner = NULL;
  }

  clients.remove(ec);

  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    const EventInfo& ei = it->second;
    if (ei.IsManaged() && (ei.GetList() != NULL)) {
      ei.GetList()->remove(ec);
    }
  }

  GfxBlockMgr::removeClient(ec);

//???  RemoveClientActions(ec, syncedActions);
//???  RemoveClientActions(ec, unsyncedActions);
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::GetEventList(vector<string>& list) const
{
  list.clear();
  EventMap::const_iterator it;
  for (it = eventMap.begin(); it != eventMap.end(); ++it) {
    list.push_back(it->first);
  }
}

const EventHandler::EventInfo*
  EventHandler::GetEventInfo(const std::string& eName) const
{
  EventMap::const_iterator it = eventMap.find(eName);
  return (it != eventMap.end()) ? &(it->second) : NULL;
}

bool EventHandler::IsKnown(const string& eName) const
{
  return GetEventInfo(eName) != NULL;
}

bool EventHandler::IsManaged(const string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && (ei->GetList() != NULL);
}

bool EventHandler::IsReversed(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->IsReversed();
}

bool EventHandler::ReqFullRead(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->ReqFullRead();
}

bool EventHandler::ReqInputCtrl(const std::string& eName) const
{
  const EventInfo* ei = GetEventInfo(eName);
  return (ei != NULL) && ei->ReqInputCtrl();
}

/******************************************************************************/
/******************************************************************************/

bool EventHandler::CanUseEvent(EventClient* ec, const EventInfo& ei) const
{
  if ((ei.ReqFullRead()  && !ec->HasFullRead()) ||
      (ei.ReqInputCtrl() && !ec->HasInputCtrl())) {
    return false;
  }
  return true;
}

bool EventHandler::InsertEvent(EventClient* ec, const string& ciName)
{
  EventMap::iterator it = eventMap.find(ciName);
  if (it == eventMap.end()) {
    return false;
  }
  const EventInfo& ei = it->second;
  EventClientList* ecList = ei.GetList();
  if (ecList == NULL) {
    return false;
  }
  if (!CanUseEvent(ec, ei)) {
    return false;
  }
  return ecList->insert(ec);
}

bool EventHandler::RemoveEvent(EventClient* ec, const string& ciName)
{
  EventMap::iterator it = eventMap.find(ciName);
  if ((it == eventMap.end()) || (it->second.GetList() == NULL)) {
    return false;
  }
  return it->second.GetList()->remove(ec);
}

/******************************************************************************/
/******************************************************************************/

void EventHandler::RecvLuaData(int srcPlayerID, int srcScriptID,
                               int dstPlayerID, int dstScriptID,
                               int status, const std::string& data)
{
  EventClientList& list = listRecvLuaData;
  if (list.empty()) { return; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if ((dstScriptID == 0) || (dstScriptID == ec->GetOrder())) {
      ec->RecvLuaData(srcPlayerID, srcScriptID,
                      dstPlayerID, dstScriptID,
                      status, data);
    }
  }
  list.finish();
}

/******************************************************************************/
/******************************************************************************/

#define DRAW_CALLIN(name)                 \
  void EventHandler:: name ()             \
  {                                       \
    EventClientList& list = list ## name; \
    if (list.empty()) { return; }         \
                                          \
    OpenGLPassState::Enable ## name ();   \
                                          \
    EventClient* ec = NULL;               \
    size_t i = 0;                         \
    list.start(i);                        \
    list.next(i, ec);                     \
    ec-> name ();                         \
                                          \
    while (list.next(i, ec)) {            \
      OpenGLPassState::Reset ## name ();  \
      ec-> name ();                       \
    }                                     \
    list.finish();                        \
                                          \
    OpenGLPassState::Disable ## name ();  \
  }

DRAW_CALLIN(DrawGenesis)
DRAW_CALLIN(DrawWorldStart)
DRAW_CALLIN(DrawWorld)
DRAW_CALLIN(DrawWorldAlpha)
DRAW_CALLIN(DrawWorldShadow)
DRAW_CALLIN(DrawScreenStart)
DRAW_CALLIN(DrawScreen)
DRAW_CALLIN(DrawRadar)

/******************************************************************************/
/******************************************************************************/

bool EventHandler::KeyPress(int key, bool isRepeat)
{
  EventClientList& list = listKeyPress;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->KeyPress(key, isRepeat)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::KeyRelease(int key)
{
  EventClientList& list = listKeyRelease;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->KeyRelease(key)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MousePress(int x, int y, int button)
{
  EventClientList& list = listMousePress;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MousePress(x, y, button)) {
      mouseOwner = ec;
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MouseRelease(int x, int y, int button)
{
  if (mouseOwner == NULL) {
    return false;
  }
  const bool retval = mouseOwner->MouseRelease(x, y, button);
  mouseOwner = NULL;
  return retval;
}

bool EventHandler::MouseMove(int x, int y)
{
  EventClientList& list = listMouseMove;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MouseMove(x, y) && (ec == mouseOwner)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::MouseWheel(float value)
{
  EventClientList& list = listMouseWheel;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->MouseWheel(value)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

bool EventHandler::IsAbove(int x, int y)
{
  EventClientList& list = listIsAbove;
  if (list.empty()) { return false; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    if (ec->IsAbove(x, y)) {
      list.finish();
      return true;
    }
  }
  list.finish();
  return false;
}

string EventHandler::GetTooltip(int x, int y)
{
  EventClientList& list = listGetTooltip;
  if (list.empty()) { return ""; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    const string tt = ec->GetTooltip(x, y);
    if (!tt.empty()) {
      list.finish();
      return tt;
    }
  }
  list.finish();
  return "";
}

void EventHandler::WordComplete(const string& line, set<string>& partials)
{
  EventClientList& list = listWordComplete;
  if (list.empty()) { return; }
  size_t i = 0;
  EventClient* ec;
  for (list.start(i); list.next(i, ec); /* no-op */) {
    set<string> safePartials;
    ec->WordComplete(line, safePartials);
    set<string>::const_iterator it;
    for (it = safePartials.begin(); it != safePartials.end(); ++it) {
      const string& partial = *it;
      if (!partial.empty()) {
        partials.insert(partial);
      }
    }
  }
  list.finish();
}

/******************************************************************************/
/******************************************************************************/
<|endoftext|>


<commit_before>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, are
    permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this list of
    conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice, this list
    of conditions and the following disclaimer in the documentation and/or other materials
    provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOE HERMASZEWSKI OR
    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are those of the
    authors and should not be interpreted as representing official policies, either expressed
    or implied, of Joe Hermaszewski.
*/

#include "translation_unit.hpp"

#include <iostream>
#include <memory>
#include <vector>

#include "declaration.hpp"
#include "parser.hpp"
#include "terminal_types.hpp"
#include "token.hpp"

namespace JoeLang
{
namespace Parser
{

TranslationUnit::TranslationUnit( std::vector< std::unique_ptr<DeclarationBase> >&& declarations )
    :m_declarations( std::move( declarations ) )
{
}

TranslationUnit::~TranslationUnit()
{
}

void TranslationUnit::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i)
        std::cout << " ";
    std::cout << "TranslationUnit\n";
    for( const auto& declaration : m_declarations )
        declaration->Print( depth + 1 );
}

bool TranslationUnit::Parse( Parser& parser, std::unique_ptr<TranslationUnit>& token )
{
    std::vector< std::unique_ptr<DeclarationBase> > declarations;

    if( !ExpectSequenceOf<DeclarationBase>( parser, declarations ) )
        return false;

    if( !parser.ExpectTerminal( Lexer::END_OF_INPUT ) )
        return false;

    token.reset( new TranslationUnit( std::move( declarations ) ) );
    return true;
}

} // namespace Parser
} // namespace JoeLang
<commit_msg>[~] Added comment<commit_after>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, are
    permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this list of
    conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice, this list
    of conditions and the following disclaimer in the documentation and/or other materials
    provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOE HERMASZEWSKI OR
    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are those of the
    authors and should not be interpreted as representing official policies, either expressed
    or implied, of Joe Hermaszewski.
*/

#include "translation_unit.hpp"

#include <iostream>
#include <memory>
#include <vector>

#include "declaration.hpp"
#include "parser.hpp"
#include "terminal_types.hpp"
#include "token.hpp"

namespace JoeLang
{
namespace Parser
{

//------------------------------------------------------------------------------
// TranslationUnit
//------------------------------------------------------------------------------

TranslationUnit::TranslationUnit( std::vector< std::unique_ptr<DeclarationBase> >&& declarations )
    :m_declarations( std::move( declarations ) )
{
}

TranslationUnit::~TranslationUnit()
{
}

void TranslationUnit::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i)
        std::cout << " ";
    std::cout << "TranslationUnit\n";
    for( const auto& declaration : m_declarations )
        declaration->Print( depth + 1 );
}

bool TranslationUnit::Parse( Parser& parser, std::unique_ptr<TranslationUnit>& token )
{
    std::vector< std::unique_ptr<DeclarationBase> > declarations;
    if( !ExpectSequenceOf<DeclarationBase>( parser, declarations ) )
        return false;

    if( !parser.ExpectTerminal( Lexer::END_OF_INPUT ) )
        return false;

    token.reset( new TranslationUnit( std::move( declarations ) ) );
    return true;
}

} // namespace Parser
} // namespace JoeLang
<|endoftext|>


<commit_before>/*
 * HtmlUtils.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/HtmlUtils.hpp>

#include <core/system/System.hpp>

#include <boost/format.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <core/Base64.hpp>
#include <core/FileSerializer.hpp>
#include <core/RegexUtils.hpp>

#include <core/http/Util.hpp>

namespace rstudio {
namespace core {
namespace html_utils {

HTML::HTML(const std::string& text, bool isHTML)
{
   if (!isHTML)
      text_ = string_utils::htmlEscape(text);
   else
      text_ = text;
}

std::string defaultTitle(const std::string& htmlContent)
{
   boost::regex re("<[Hh]([1-6]).*?>(.*?)</[Hh]\\1>");
   boost::smatch match;
   if (regex_utils::search(htmlContent, match, re))
      return match[2];
   else
      return "";
}

Base64ImageFilter::Base64ImageFilter(const FilePath& basePath)
   : boost::iostreams::regex_filter(
       boost::regex(
             R"((<\s*[Ii][Mm][Gg] [^\>]*[Ss][Rr][Cc]\s*=\s*)(["'])(.*?)(\2))"),
        boost::bind(&Base64ImageFilter::toBase64Image, this, _1)),
     basePath_(basePath)
{
}

std::string Base64ImageFilter::toBase64Image(const boost::cmatch& match)
{
   // extract image reference
   std::string imgRef = match[3];

   // url decode it
   imgRef = http::util::urlDecode(imgRef);

   // see if this is an image within the base directory. if it is then
   // base64 encode it
   FilePath imagePath = basePath_.childPath(imgRef);
   if (imagePath.exists() &&
       boost::algorithm::starts_with(imagePath.mimeContentType(), "image/"))
   {
      std::string imageBase64;
      Error error = core::base64::encode(imagePath, &imageBase64);
      if (!error)
      {
         imgRef = "data:" + imagePath.mimeContentType() + ";base64,";
         imgRef.append(imageBase64);
      }
      else
      {
         LOG_ERROR(error);
      }
   }

   // return the filtered result
   return match[1] + match[2] + imgRef + match[4];
}

// convert fonts to base64

CssUrlFilter::CssUrlFilter(const FilePath& basePath)
   : boost::iostreams::regex_filter(
        boost::regex("url\\('([^'']+)'\\)"),
        boost::bind(&CssUrlFilter::toBase64Url, this, _1)),
     basePath_(basePath)
{
}

std::string CssUrlFilter::toBase64Url(const boost::cmatch& match)
{
   // is this a local file?
   std::string urlRef = match[1];
   FilePath urlPath = basePath_.childPath(urlRef);
   std::string ext = urlPath.extensionLowerCase();
   if (urlPath.exists() && (ext == ".ttf" || ext == ".otf"))
   {
      std::string fontBase64;
      Error error = core::base64::encode(urlPath, &fontBase64);
      if (!error)
      {
         // return base64 encoded font
         std::string type = (ext == ".ttf") ? "truetype" : "opentype";
         boost::format fmt("url(data:font/%1%;base64,%2%)");
         return boost::str(fmt % type % fontBase64);
      }
      else
      {
         LOG_ERROR(error);
         return match[0];
      }
   }
   else
   {
      return match[0];
   }
}

TextRange findClosestRange(std::string::const_iterator pos,
                           const std::vector<TextRange>& ranges)
{
   TextRange closestRange = ranges.front();

   for (const auto& range : ranges)
   {
      if (std::abs(range.begin - pos) < std::abs(closestRange.begin - pos))
         closestRange = range;
   }

   return closestRange;
}

void HtmlPreserver::preserve(std::string* pInput)
{
   // begin and end regexes
   boost::regex beginPreserve("<!--html_preserve-->");
   boost::regex endPreserve("<!--\\/html_preserve-->");

   // discover ranges we need to preserve
   std::vector<TextRange> ranges;
   std::string::const_iterator pos = pInput->begin();
   std::string::const_iterator inputEnd = pInput->end();
   while (pos != inputEnd)
   {
      // look for begin marker
      boost::smatch m;
      if (regex_utils::search(pos, inputEnd, m, beginPreserve))
      {
         // set begin iterator
         std::string::const_iterator begin = m[0].first;
         std::string::const_iterator end = m[0].second;

         // look for end marker
         if (regex_utils::search(end, inputEnd, m, endPreserve))
         {
            // update end to be the end of the match
            end = m[0].second;
         }
         else
         {
            // didn't find a matching end pattern so set the end to the
            // end of the document -- this will cause us to exclude the
            // rest of the document from processing
            end = inputEnd;
         }

         // mark everything before the match as requiring processing
         ranges.push_back(TextRange(true, pos, begin));

         // add the matched range to our list
         ranges.push_back(TextRange(false, begin, end));

         // update the position
         pos = end + 1;

      }
      else
      {
         // no more preserve regions, set termination condition
         ranges.push_back(TextRange(true, pos, pInput->end()));
         pos = inputEnd;
      }
   }

   // substitute guids for all of the matched ranges
   std::string modifiedInput;
   for (auto& range : ranges)
   {
      if (range.process)
      {
         modifiedInput += std::string(range.begin, range.end);
      }
      else
      {
         std::string guid = core::system::generateUuid();
         std::string html = std::string(range.begin, range.end);
         preserved_[guid] = html;
         modifiedInput += guid;
      }
   }

   // return the modified input
   *pInput = modifiedInput;

}

void HtmlPreserver::restore(std::string* pOutput)
{
   using StringPair = std::pair<std::string,std::string>;
   for (const auto& preserve : preserved_)
   {
      boost::algorithm::replace_first(*pOutput,
                                      preserve.first,
                                      preserve.second);
   }
}

} // namespace html_utils
} // namespace core
} // namespace rstudio

<commit_msg>Fix warning introduced with some C++11 tweaks I made<commit_after>/*
 * HtmlUtils.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/HtmlUtils.hpp>

#include <core/system/System.hpp>

#include <boost/format.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <core/Base64.hpp>
#include <core/FileSerializer.hpp>
#include <core/RegexUtils.hpp>

#include <core/http/Util.hpp>

namespace rstudio {
namespace core {
namespace html_utils {

HTML::HTML(const std::string& text, bool isHTML)
{
   if (!isHTML)
      text_ = string_utils::htmlEscape(text);
   else
      text_ = text;
}

std::string defaultTitle(const std::string& htmlContent)
{
   boost::regex re("<[Hh]([1-6]).*?>(.*?)</[Hh]\\1>");
   boost::smatch match;
   if (regex_utils::search(htmlContent, match, re))
      return match[2];
   else
      return "";
}

Base64ImageFilter::Base64ImageFilter(const FilePath& basePath)
   : boost::iostreams::regex_filter(
       boost::regex(
             R"((<\s*[Ii][Mm][Gg] [^\>]*[Ss][Rr][Cc]\s*=\s*)(["'])(.*?)(\2))"),
        boost::bind(&Base64ImageFilter::toBase64Image, this, _1)),
     basePath_(basePath)
{
}

std::string Base64ImageFilter::toBase64Image(const boost::cmatch& match)
{
   // extract image reference
   std::string imgRef = match[3];

   // url decode it
   imgRef = http::util::urlDecode(imgRef);

   // see if this is an image within the base directory. if it is then
   // base64 encode it
   FilePath imagePath = basePath_.childPath(imgRef);
   if (imagePath.exists() &&
       boost::algorithm::starts_with(imagePath.mimeContentType(), "image/"))
   {
      std::string imageBase64;
      Error error = core::base64::encode(imagePath, &imageBase64);
      if (!error)
      {
         imgRef = "data:" + imagePath.mimeContentType() + ";base64,";
         imgRef.append(imageBase64);
      }
      else
      {
         LOG_ERROR(error);
      }
   }

   // return the filtered result
   return match[1] + match[2] + imgRef + match[4];
}

// convert fonts to base64

CssUrlFilter::CssUrlFilter(const FilePath& basePath)
   : boost::iostreams::regex_filter(
        boost::regex("url\\('([^'']+)'\\)"),
        boost::bind(&CssUrlFilter::toBase64Url, this, _1)),
     basePath_(basePath)
{
}

std::string CssUrlFilter::toBase64Url(const boost::cmatch& match)
{
   // is this a local file?
   std::string urlRef = match[1];
   FilePath urlPath = basePath_.childPath(urlRef);
   std::string ext = urlPath.extensionLowerCase();
   if (urlPath.exists() && (ext == ".ttf" || ext == ".otf"))
   {
      std::string fontBase64;
      Error error = core::base64::encode(urlPath, &fontBase64);
      if (!error)
      {
         // return base64 encoded font
         std::string type = (ext == ".ttf") ? "truetype" : "opentype";
         boost::format fmt("url(data:font/%1%;base64,%2%)");
         return boost::str(fmt % type % fontBase64);
      }
      else
      {
         LOG_ERROR(error);
         return match[0];
      }
   }
   else
   {
      return match[0];
   }
}

TextRange findClosestRange(std::string::const_iterator pos,
                           const std::vector<TextRange>& ranges)
{
   TextRange closestRange = ranges.front();

   for (const auto& range : ranges)
   {
      if (std::abs(range.begin - pos) < std::abs(closestRange.begin - pos))
         closestRange = range;
   }

   return closestRange;
}

void HtmlPreserver::preserve(std::string* pInput)
{
   // begin and end regexes
   boost::regex beginPreserve("<!--html_preserve-->");
   boost::regex endPreserve("<!--\\/html_preserve-->");

   // discover ranges we need to preserve
   std::vector<TextRange> ranges;
   std::string::const_iterator pos = pInput->begin();
   std::string::const_iterator inputEnd = pInput->end();
   while (pos != inputEnd)
   {
      // look for begin marker
      boost::smatch m;
      if (regex_utils::search(pos, inputEnd, m, beginPreserve))
      {
         // set begin iterator
         std::string::const_iterator begin = m[0].first;
         std::string::const_iterator end = m[0].second;

         // look for end marker
         if (regex_utils::search(end, inputEnd, m, endPreserve))
         {
            // update end to be the end of the match
            end = m[0].second;
         }
         else
         {
            // didn't find a matching end pattern so set the end to the
            // end of the document -- this will cause us to exclude the
            // rest of the document from processing
            end = inputEnd;
         }

         // mark everything before the match as requiring processing
         ranges.push_back(TextRange(true, pos, begin));

         // add the matched range to our list
         ranges.push_back(TextRange(false, begin, end));

         // update the position
         pos = end + 1;

      }
      else
      {
         // no more preserve regions, set termination condition
         ranges.push_back(TextRange(true, pos, pInput->end()));
         pos = inputEnd;
      }
   }

   // substitute guids for all of the matched ranges
   std::string modifiedInput;
   for (auto& range : ranges)
   {
      if (range.process)
      {
         modifiedInput += std::string(range.begin, range.end);
      }
      else
      {
         std::string guid = core::system::generateUuid();
         std::string html = std::string(range.begin, range.end);
         preserved_[guid] = html;
         modifiedInput += guid;
      }
   }

   // return the modified input
   *pInput = modifiedInput;

}

void HtmlPreserver::restore(std::string* pOutput)
{
   for (const auto& preserve : preserved_)
   {
      boost::algorithm::replace_first(*pOutput,
                                      preserve.first,
                                      preserve.second);
   }
}

} // namespace html_utils
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before>/*
 * Copyright 2012, 2013 Esrille Inc.
 *
 * 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 "CSSRuleListImp.h"

#include "CSSMediaRuleImp.h"
#include "CSSStyleDeclarationImp.h"
#include "CSSStyleSheetImp.h"

#include "DocumentImp.h"
#include "ViewCSSImp.h"

#include "html/MediaQueryListImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

using namespace css;

void CSSRuleListImp::append(css::CSSRule rule)
{
    ruleList.push_back(rule);
}

bool CSSRuleListImp::PrioritizedRule::getMatches() const
{
    return !mql || mql->getMatches();
}

bool CSSRuleListImp::PrioritizedRule::isActive(Element& element, ViewCSSImp* view) const
{
    CSSSelector* selector = getSelector();
    if (!selector)
        return true;
    return selector->match(element, view, true);
}

void CSSRuleListImp::appendMisc(CSSSelector* selector, CSSStyleDeclarationImp* declaration, MediaListImp* mediaList)
{
    misc.push_back(Rule{ selector, declaration, ++order, mediaList });
}

void CSSRuleListImp::appendID(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapID.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::appendClass(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapClass.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::appendType(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapType.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::append(css::CSSRule rule, DocumentImp* document, MediaListImp* mediaList)
{
    if (!rule)
        return;
    if (CSSStyleRuleImp* styleRule = dynamic_cast<CSSStyleRuleImp*>(rule.self())) {
        if (CSSSelectorsGroup* selectorsGroup = styleRule->getSelectorsGroup()) {
            for (auto j = selectorsGroup->begin(); j != selectorsGroup->end(); ++j) {
                CSSSelector* selector = *j;
                CSSStyleDeclarationImp* declaration = dynamic_cast<CSSStyleDeclarationImp*>(styleRule->getStyle().self());
                selector->registerToRuleList(this, declaration, mediaList);
            }
        }
    } else if (CSSMediaRuleImp* mediaRule = dynamic_cast<CSSMediaRuleImp*>(rule.self())) {
        auto ruleList = dynamic_cast<CSSRuleListImp*>(mediaRule->getCssRules().self());
        if (ruleList) {
            MediaListImp* mediaList = dynamic_cast<MediaListImp*>(mediaRule->getMedia().self());
            for (auto i = ruleList->ruleList.begin(); i != ruleList->ruleList.end(); ++i)
                append(*i, document, mediaList);
        }
    } else if (CSSImportRuleImp* importRule = dynamic_cast<CSSImportRuleImp*>(rule.self())) {
        if (document) {
            importRule->setDocument(document);
            importRule->getStyleSheet();  // to get the CSS file
            importList.push_back(importRule);
        }
    }
    if (!rule.getParentRule())
        ruleList.push_back(rule);
}

void CSSRuleListImp::collectRules(RuleSet& set, ViewCSSImp* view, Element& element, std::multimap<std::u16string, Rule>& map, const std::u16string& key, MediaListImp* mediaList)
{
    for (auto i = map.find(key); i != map.end() && i->first == key; ++i) {
        CSSSelector* selector = i->second.selector;
        if (!selector->match(element, view, false))
            continue;
        // TODO: emplace() seems to be not ready yet with libstdc++.
        if (!mediaList)
            mediaList = i->second.mediaList;
        // TODO: else ...
        PrioritizedRule rule(importance, i->second, view->matchMedia(mediaList));
        set.insert(rule);
    }
}

void CSSRuleListImp::collectRulesByID(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    Nullable<std::u16string> attr = element.getAttribute(u"id");
    if (attr.hasValue())
        collectRules(set, view, element, mapID, attr.value(), mediaList);
}

void CSSRuleListImp::collectRulesByClass(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    Nullable<std::u16string> attr = element.getAttribute(u"class");
    if (attr.hasValue()) {
        std::u16string classes = attr.value();
        for (size_t pos = 0; pos < classes.length();) {
            if (isSpace(classes[pos])) {
                ++pos;
                continue;
            }
            size_t start = pos++;
            while (pos < classes.length() && !isSpace(classes[pos]))
                ++pos;
            collectRules(set, view, element, mapClass, classes.substr(start, pos - start), mediaList);
        }
    }
}

void CSSRuleListImp::collectRulesByType(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    collectRules(set, view, element, mapType, element.getLocalName(), mediaList);
}

void CSSRuleListImp::collectRulesByMisc(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    for (auto i = misc.begin(); i != misc.end(); ++i) {
        CSSSelector* selector = i->selector;
        if (!selector->match(element, view, false))
            continue;
        // TODO: emplace() seems to be not ready yet with libstdc++.
        if (!mediaList)
            mediaList = i->mediaList;
        // TODO: else ...
        PrioritizedRule rule(importance, *i, view->matchMedia(mediaList));
        set.insert(rule);
    }
}

void CSSRuleListImp::collectRules(RuleSet& set, ViewCSSImp* view, Element& element, unsigned importance, MediaListImp* mediaList)
{
    this->importance = importance;

    // Declarations in imported style sheets are considered to be before any
    // declarations in the style sheet itself.
    // cf. http://www.w3.org/TR/CSS2/cascade.html#cascading-order
    for (auto i = importList.begin(); i != importList.end(); ++i) {
        if (CSSStyleSheetImp* sheet = dynamic_cast<CSSStyleSheetImp*>((*i)->getStyleSheet().self())) {
            if (CSSRuleListImp* ruleList = dynamic_cast<CSSRuleListImp*>(sheet->getCssRules().self()))
                ruleList->collectRules(set, view, element, importance, mediaList);
        }
    }

    collectRulesByMisc(set, view, element, mediaList);
    collectRulesByType(set, view, element, mediaList);
    collectRulesByClass(set, view, element, mediaList);
    collectRulesByID(set, view, element, mediaList);
}

bool CSSRuleListImp::hasHover(const RuleSet& set)
{
    for (auto i = set.begin(); i != set.end(); ++i) {
        CSSSelector* selector = i->getSelector();
        if (selector && selector->hasHover())
            return true;
    }
    return false;
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(CSSRuleListImp::collectRules, CSSRuleListImp::collectRulesByMisc) : Prioritize media rules over other media lists for now<commit_after>/*
 * Copyright 2012, 2013 Esrille Inc.
 *
 * 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 "CSSRuleListImp.h"

#include "CSSMediaRuleImp.h"
#include "CSSStyleDeclarationImp.h"
#include "CSSStyleSheetImp.h"

#include "DocumentImp.h"
#include "ViewCSSImp.h"

#include "html/MediaQueryListImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

using namespace css;

void CSSRuleListImp::append(css::CSSRule rule)
{
    ruleList.push_back(rule);
}

bool CSSRuleListImp::PrioritizedRule::getMatches() const
{
    return !mql || mql->getMatches();
}

bool CSSRuleListImp::PrioritizedRule::isActive(Element& element, ViewCSSImp* view) const
{
    CSSSelector* selector = getSelector();
    if (!selector)
        return true;
    return selector->match(element, view, true);
}

void CSSRuleListImp::appendMisc(CSSSelector* selector, CSSStyleDeclarationImp* declaration, MediaListImp* mediaList)
{
    misc.push_back(Rule{ selector, declaration, ++order, mediaList });
}

void CSSRuleListImp::appendID(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapID.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::appendClass(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapClass.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::appendType(CSSSelector* selector, CSSStyleDeclarationImp* declaration, const std::u16string& key, MediaListImp* mediaList)
{
    mapType.insert(std::pair<std::u16string, Rule>(key, Rule{ selector, declaration, ++order, mediaList }));
}

void CSSRuleListImp::append(css::CSSRule rule, DocumentImp* document, MediaListImp* mediaList)
{
    if (!rule)
        return;
    if (CSSStyleRuleImp* styleRule = dynamic_cast<CSSStyleRuleImp*>(rule.self())) {
        if (CSSSelectorsGroup* selectorsGroup = styleRule->getSelectorsGroup()) {
            for (auto j = selectorsGroup->begin(); j != selectorsGroup->end(); ++j) {
                CSSSelector* selector = *j;
                CSSStyleDeclarationImp* declaration = dynamic_cast<CSSStyleDeclarationImp*>(styleRule->getStyle().self());
                selector->registerToRuleList(this, declaration, mediaList);
            }
        }
    } else if (CSSMediaRuleImp* mediaRule = dynamic_cast<CSSMediaRuleImp*>(rule.self())) {
        auto ruleList = dynamic_cast<CSSRuleListImp*>(mediaRule->getCssRules().self());
        if (ruleList) {
            MediaListImp* mediaList = dynamic_cast<MediaListImp*>(mediaRule->getMedia().self());
            for (auto i = ruleList->ruleList.begin(); i != ruleList->ruleList.end(); ++i)
                append(*i, document, mediaList);
        }
    } else if (CSSImportRuleImp* importRule = dynamic_cast<CSSImportRuleImp*>(rule.self())) {
        if (document) {
            importRule->setDocument(document);
            importRule->getStyleSheet();  // to get the CSS file
            importList.push_back(importRule);
        }
    }
    if (!rule.getParentRule())
        ruleList.push_back(rule);
}

void CSSRuleListImp::collectRules(RuleSet& set, ViewCSSImp* view, Element& element, std::multimap<std::u16string, Rule>& map, const std::u16string& key, MediaListImp* mediaList)
{
    for (auto i = map.find(key); i != map.end() && i->first == key; ++i) {
        CSSSelector* selector = i->second.selector;
        if (!selector->match(element, view, false))
            continue;
        // TODO: emplace() seems to be not ready yet with libstdc++.
        if (i->second.mediaList)
            mediaList = i->second.mediaList;
        // TODO: else ...
        PrioritizedRule rule(importance, i->second, view->matchMedia(mediaList));
        set.insert(rule);
    }
}

void CSSRuleListImp::collectRulesByID(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    Nullable<std::u16string> attr = element.getAttribute(u"id");
    if (attr.hasValue())
        collectRules(set, view, element, mapID, attr.value(), mediaList);
}

void CSSRuleListImp::collectRulesByClass(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    Nullable<std::u16string> attr = element.getAttribute(u"class");
    if (attr.hasValue()) {
        std::u16string classes = attr.value();
        for (size_t pos = 0; pos < classes.length();) {
            if (isSpace(classes[pos])) {
                ++pos;
                continue;
            }
            size_t start = pos++;
            while (pos < classes.length() && !isSpace(classes[pos]))
                ++pos;
            collectRules(set, view, element, mapClass, classes.substr(start, pos - start), mediaList);
        }
    }
}

void CSSRuleListImp::collectRulesByType(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    collectRules(set, view, element, mapType, element.getLocalName(), mediaList);
}

void CSSRuleListImp::collectRulesByMisc(RuleSet& set, ViewCSSImp* view, Element& element, MediaListImp* mediaList)
{
    for (auto i = misc.begin(); i != misc.end(); ++i) {
        CSSSelector* selector = i->selector;
        if (!selector->match(element, view, false))
            continue;
        // TODO: emplace() seems to be not ready yet with libstdc++.
        if (i->mediaList)
            mediaList = i->mediaList;
        // TODO: else ...
        PrioritizedRule rule(importance, *i, view->matchMedia(mediaList));
        set.insert(rule);
    }
}

void CSSRuleListImp::collectRules(RuleSet& set, ViewCSSImp* view, Element& element, unsigned importance, MediaListImp* mediaList)
{
    this->importance = importance;

    // Declarations in imported style sheets are considered to be before any
    // declarations in the style sheet itself.
    // cf. http://www.w3.org/TR/CSS2/cascade.html#cascading-order
    for (auto i = importList.begin(); i != importList.end(); ++i) {
        if (CSSStyleSheetImp* sheet = dynamic_cast<CSSStyleSheetImp*>((*i)->getStyleSheet().self())) {
            if (CSSRuleListImp* ruleList = dynamic_cast<CSSRuleListImp*>(sheet->getCssRules().self()))
                ruleList->collectRules(set, view, element, importance, mediaList);
        }
    }

    collectRulesByMisc(set, view, element, mediaList);
    collectRulesByType(set, view, element, mediaList);
    collectRulesByClass(set, view, element, mediaList);
    collectRulesByID(set, view, element, mediaList);
}

bool CSSRuleListImp::hasHover(const RuleSet& set)
{
    for (auto i = set.begin(); i != set.end(); ++i) {
        CSSSelector* selector = i->getSelector();
        if (selector && selector->hasHover())
            return true;
    }
    return false;
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>

#include "rpc/client.h"
#include "rpc/server.h"
#include "benchmark_service.h"

using namespace benchmark;
using namespace rpc;
using namespace std;

const char *svr_addr = "127.0.0.1:8848";
int byte_size = 10;
int epoll_instances = 2;
bool fast_requests = false;
int seconds = 10;
int outgoing_requests = 1000;
int client_threads = 8;
int worker_threads = 16;

static string request_str;
PollMgr* poll;
ThreadPool* thrpool;

Counter req_counter;

bool should_stop = false;

pthread_mutex_t g_stop_mutex;
pthread_cond_t g_stop_cond;

static void signal_handler(int sig) {
    Log_info("caught signal %d, stopping server now", sig);
    should_stop = true;
    Pthread_mutex_lock(&g_stop_mutex);
    Pthread_cond_signal(&g_stop_cond);
    Pthread_mutex_unlock(&g_stop_mutex);
}

static void* stat_proc(void*) {
    i64 last_cnt = 0;
    for (int i = 0; i < seconds; i++) {
        int cnt = req_counter.peek_next();
        if (last_cnt != 0) {
            Log::debug("qps: %ld", cnt - last_cnt);
        }
        last_cnt = cnt;
        sleep(1);
    }
    should_stop = true;
    pthread_exit(nullptr);
    return nullptr;
}

static void* client_proc(void*) {
    Client* cl = new Client(poll);
    verify(cl->connect(svr_addr) == 0);
    i32 rpc_id;
    if (fast_requests) {
        rpc_id = BenchmarkService::FAST_NOP;
    } else {
        rpc_id = BenchmarkService::NOP;
    }
    FutureAttr fu_attr;
    auto do_work = [cl, &fu_attr, rpc_id] {
        if (!should_stop) {
            Future* fu = cl->begin_request(rpc_id, fu_attr);
            *cl << request_str;
            cl->end_request();
            Future::safe_release(fu);
            req_counter.next();
        }
    };
    fu_attr.callback = [&do_work] (Future* fu) {
        if (fu->get_error_code() != 0) {
            return;
        }
        thrpool->run_async([&do_work] {
            do_work();
        });
    };
    for (int i = 0; i < outgoing_requests; i++) {
        do_work();
    }
    while (!should_stop) {
        sleep(1);
    }

    cl->close_and_release();
    pthread_exit(nullptr);
    return nullptr;
}

int main(int argc, char **argv) {
    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    bool is_client = false, is_server = false;

    if (argc < 2) {
        printf("usage: perftest OPTIONS\n");
        printf("                -c|-s ip:port\n");
        printf("                -b    byte_size\n");
        printf("                -e    epoll_instances\n");
        printf("                -f    fast_requests\n");
        printf("                -n    seconds\n");
        printf("                -o    outgoing_requests\n");
        printf("                -t    client_threads\n");
        printf("                -w    worker_threads\n");
        exit(1);
    }

    char ch = 0;
    while ((ch = getopt(argc, argv, "c:s:b:e:fi:m:n:o:t:w:"))!= -1) {
        switch (ch) {
        case 'c':
            is_client = true;
            svr_addr = optarg;
            break;
        case 's':
            is_server = true;
            svr_addr = optarg;
            break;
        case 'b':
            byte_size = atoi(optarg);
            break;
        case 'e':
            epoll_instances = atoi(optarg);
            break;
        case 'f':
            fast_requests = true;
            break;
        case 'n':
            seconds = atoi(optarg);
            break;
        case 'o':
            outgoing_requests = atoi(optarg);
            break;
        case 't':
            client_threads = atoi(optarg);
            break;
        case 'w':
            worker_threads = atoi(optarg);
            break;
        default:
            break;
        }
    }
    verify(is_server || is_client);
    if (is_server) {
        Log::info("server will start at     %s", svr_addr);
    } else {
        Log::info("client will connect to   %s", svr_addr);
    }
    Log::info("packet byte size:        %d", byte_size);
    Log::info("epoll instances:         %d", epoll_instances);
    Log::info("fast reqeust:            %s", fast_requests ? "true" : "false");
    Log::info("running seconds:         %d", seconds);
    Log::info("outgoing requests:       %d", outgoing_requests);
    Log::info("client threads:          %d", client_threads);
    Log::info("worker threads:          %d", worker_threads);

    request_str = string(byte_size, 'x');
    poll_options poll_opt;
    poll_opt.n_threads = epoll_instances;
    poll = new PollMgr(poll_opt);
    thrpool = new ThreadPool(worker_threads);
    if (is_server) {
        Server svr(poll, thrpool);
        BenchmarkService svc;
        svr.reg(&svc);
        verify(svr.start(svr_addr) == 0);

        Pthread_mutex_init(&g_stop_mutex, nullptr);
        Pthread_cond_init(&g_stop_cond, nullptr);

        signal(SIGPIPE, SIG_IGN);
        signal(SIGHUP, SIG_IGN);
        signal(SIGCHLD, SIG_IGN);

        signal(SIGALRM, signal_handler);
        signal(SIGINT, signal_handler);
        signal(SIGQUIT, signal_handler);
        signal(SIGTERM, signal_handler);

        Pthread_mutex_lock(&g_stop_mutex);
        while (should_stop == false) {
            Pthread_cond_wait(&g_stop_cond, &g_stop_mutex);
        }
        Pthread_mutex_unlock(&g_stop_mutex);

    } else {
        pthread_t* client_th = new pthread_t[client_threads];
        for (int i = 0; i < client_threads; i++) {
            Pthread_create(&client_th[i], nullptr, client_proc, nullptr);
        }
        pthread_t stat_th;
        Pthread_create(&stat_th, nullptr, stat_proc, nullptr);
        Pthread_join(stat_th, nullptr);
        for (int i = 0; i < client_threads; i++) {
            Pthread_join(client_th[i], nullptr);
        }
        delete[] client_th;
    }

    poll->release();
    thrpool->release();
    return 0;
}
<commit_msg>minor update<commit_after>#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>

#include "rpc/client.h"
#include "rpc/server.h"
#include "benchmark_service.h"

using namespace benchmark;
using namespace rpc;
using namespace std;

const char *svr_addr = "127.0.0.1:8848";
int byte_size = 10;
int epoll_instances = 2;
bool fast_requests = false;
int seconds = 10;
int outgoing_requests = 1000;
int client_threads = 8;
int worker_threads = 16;

static string request_str;
PollMgr* poll;
ThreadPool* thrpool;

Counter req_counter;

bool should_stop = false;

pthread_mutex_t g_stop_mutex;
pthread_cond_t g_stop_cond;

static void signal_handler(int sig) {
    Log_info("caught signal %d, stopping server now", sig);
    should_stop = true;
    Pthread_mutex_lock(&g_stop_mutex);
    Pthread_cond_signal(&g_stop_cond);
    Pthread_mutex_unlock(&g_stop_mutex);
}

static void* stat_proc(void*) {
    i64 last_cnt = 0;
    for (int i = 0; i < seconds; i++) {
        int cnt = req_counter.peek_next();
        if (last_cnt != 0) {
            Log::debug("qps: %ld", cnt - last_cnt);
        }
        last_cnt = cnt;
        sleep(1);
    }
    should_stop = true;
    pthread_exit(nullptr);
    return nullptr;
}

static void* client_proc(void*) {
    Client* cl = new Client(poll);
    verify(cl->connect(svr_addr) == 0);
    i32 rpc_id;
    if (fast_requests) {
        rpc_id = BenchmarkService::FAST_NOP;
    } else {
        rpc_id = BenchmarkService::NOP;
    }
    FutureAttr fu_attr;
    auto do_work = [cl, &fu_attr, rpc_id] {
        if (!should_stop) {
            Future* fu = cl->begin_request(rpc_id, fu_attr);
            *cl << request_str;
            cl->end_request();
            Future::safe_release(fu);
            req_counter.next();
        }
    };
    fu_attr.callback = [&do_work] (Future* fu) {
        if (fu->get_error_code() != 0) {
            return;
        }
        thrpool->run_async([&do_work] {
            do_work();
        });
    };
    for (int i = 0; i < outgoing_requests; i++) {
        do_work();
    }
    while (!should_stop) {
        sleep(1);
    }

    cl->close_and_release();
    pthread_exit(nullptr);
    return nullptr;
}

int main(int argc, char **argv) {
    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    bool is_client = false, is_server = false;

    if (argc < 2) {
        printf("usage: perftest OPTIONS\n");
        printf("                -c|-s ip:port\n");
        printf("                -b    byte_size\n");
        printf("                -e    epoll_instances\n");
        printf("                -f    fast_requests\n");
        printf("                -n    seconds\n");
        printf("                -o    outgoing_requests\n");
        printf("                -t    client_threads\n");
        printf("                -w    worker_threads\n");
        exit(1);
    }

    char ch = 0;
    while ((ch = getopt(argc, argv, "c:s:b:e:fi:m:n:o:t:w:"))!= -1) {
        switch (ch) {
        case 'c':
            is_client = true;
            svr_addr = optarg;
            break;
        case 's':
            is_server = true;
            svr_addr = optarg;
            break;
        case 'b':
            byte_size = atoi(optarg);
            break;
        case 'e':
            epoll_instances = atoi(optarg);
            break;
        case 'f':
            fast_requests = true;
            break;
        case 'n':
            seconds = atoi(optarg);
            break;
        case 'o':
            outgoing_requests = atoi(optarg);
            break;
        case 't':
            client_threads = atoi(optarg);
            break;
        case 'w':
            worker_threads = atoi(optarg);
            break;
        default:
            break;
        }
    }
    verify(is_server || is_client);
    if (is_server) {
        Log::info("server will start at     %s", svr_addr);
    } else {
        Log::info("client will connect to   %s", svr_addr);
    }
    Log::info("packet byte size:        %d", byte_size);
    Log::info("epoll instances:         %d", epoll_instances);
    Log::info("fast reqeust:            %s", fast_requests ? "true" : "false");
    Log::info("running seconds:         %d", seconds);
    Log::info("outgoing requests:       %d", outgoing_requests);
    Log::info("client threads:          %d", client_threads);
    Log::info("worker threads:          %d", worker_threads);

    request_str = string(byte_size, 'x');
    poll_options poll_opt;
    poll_opt.n_threads = epoll_instances;
    poll = new PollMgr(poll_opt);
    thrpool = new ThreadPool(worker_threads);
    if (is_server) {
        Server svr(poll, thrpool);
        BenchmarkService svc;
        svr.reg(&svc);
        verify(svr.start(svr_addr) == 0);

        Pthread_mutex_init(&g_stop_mutex, nullptr);
        Pthread_cond_init(&g_stop_cond, nullptr);

        signal(SIGPIPE, SIG_IGN);
        signal(SIGHUP, SIG_IGN);
        signal(SIGCHLD, SIG_IGN);

        signal(SIGALRM, signal_handler);
        signal(SIGINT, signal_handler);
        signal(SIGQUIT, signal_handler);
        signal(SIGTERM, signal_handler);

        Pthread_mutex_lock(&g_stop_mutex);
        while (should_stop == false) {
            Pthread_cond_wait(&g_stop_cond, &g_stop_mutex);
        }
        Pthread_mutex_unlock(&g_stop_mutex);

        // release threadpool so that no worker will be running on BenchmarkService
        thrpool->release();

    } else {
        pthread_t* client_th = new pthread_t[client_threads];
        for (int i = 0; i < client_threads; i++) {
            Pthread_create(&client_th[i], nullptr, client_proc, nullptr);
        }
        pthread_t stat_th;
        Pthread_create(&stat_th, nullptr, stat_proc, nullptr);
        Pthread_join(stat_th, nullptr);
        for (int i = 0; i < client_threads; i++) {
            Pthread_join(client_th[i], nullptr);
        }
        delete[] client_th;

        thrpool->release();
    }

    poll->release();
    return 0;
}
<|endoftext|>