<commit_before>/**
 * @file kmeans_main.cpp
 * @author Ryan Curtin
 *
 * Executable for running K-Means.
 */
#include <mlpack/core.hpp>

#include "kmeans.hpp"
#include "allow_empty_clusters.hpp"
#include "refined_start.hpp"

using namespace mlpack;
using namespace mlpack::kmeans;
using namespace std;

// Define parameters for the executable.
PROGRAM_INFO("K-Means Clustering", "This program performs K-Means clustering "
    "on the given dataset, storing the learned cluster assignments either as "
    "a column of labels in the file containing the input dataset or in a "
    "separate file.  Empty clusters are not allowed by default; when a cluster "
    "becomes empty, the point furthest from the centroid of the cluster with "
    "maximum variance is taken to fill that cluster."
    "\n\n"
    "Optionally, the Bradley and Fayyad approach (\"Refining initial points for"
    " k-means clustering\", 1998) can be used to select initial points by "
    "specifying the --refined_start (-r) option.  This approach works by taking"
    " random samples of the dataset; to specify the number of samples, the "
    "--samples parameter is used, and to specify the percentage of the dataset "
    "to be used in each sample, the --percentage parameter is used (it should "
    "be a value between 0.0 and 1.0)."
    "\n\n"
    "If you want to specify your own initial cluster assignments or initial "
    "cluster centroids, this functionality is available in the C++ interface. "
    "Alternately, file a bug (well, a feature request) on the mlpack bug "
    "tracker.");

// Required options.
PARAM_STRING_REQ("inputFile", "Input dataset to perform clustering on.", "i");
PARAM_INT_REQ("clusters", "Number of clusters to find.", "c");

// Output options.
PARAM_FLAG("in_place", "If specified, a column of the learned cluster "
    "assignments will be added to the input dataset file.  In this case, "
    "--outputFile is not necessary.", "p");
PARAM_STRING("output_file", "File to write output labels or labeled data to.",
    "o", "output.csv");
PARAM_STRING("centroid_file", "If specified, the centroids of each cluster will"
    " be written to the given file.", "C", "");

// k-means configuration options.
PARAM_FLAG("allow_empty_clusters", "Allow empty clusters to be created.", "e");
PARAM_FLAG("labels_only", "Only output labels into output file.", "l");
PARAM_DOUBLE("overclustering", "Finds (overclustering * clusters) clusters, "
    "then merges them together until only the desired number of clusters are "
    "left.", "O", 1.0);
PARAM_INT("max_iterations", "Maximum number of iterations before K-Means "
    "terminates.", "m", 1000);
PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);

// This is known to not work (#251).
//PARAM_FLAG("fast_kmeans", "Use the experimental fast k-means algorithm by "
//    "Pelleg and Moore.", "f");

// Parameters for "refined start" k-means.
PARAM_FLAG("refined_start", "Use the refined initial point strategy by Bradley "
    "and Fayyad to choose initial points.", "r");
PARAM_INT("samplings", "Number of samplings to perform for refined start (use "
    "when --refined_start is specified).", "S", 100);
PARAM_DOUBLE("percentage", "Percentage of dataset to use for each refined start"
    " sampling (use when --refined_start is specified).", "p", 0.02);

int main(int argc, char** argv)
{
  CLI::ParseCommandLine(argc, argv);

  // Initialize random seed.
  if (CLI::GetParam<int>("seed") != 0)
    math::RandomSeed((size_t) CLI::GetParam<int>("seed"));
  else
    math::RandomSeed((size_t) std::time(NULL));

  // Now do validation of options.
  string inputFile = CLI::GetParam<string>("inputFile");
  int clusters = CLI::GetParam<int>("clusters");
  if (clusters < 1)
  {
    Log::Fatal << "Invalid number of clusters requested (" << clusters << ")! "
        << "Must be greater than or equal to 1." << std::endl;
  }

  int maxIterations = CLI::GetParam<int>("max_iterations");
  if (maxIterations < 0)
  {
    Log::Fatal << "Invalid value for maximum iterations (" << maxIterations <<
        ")! Must be greater than or equal to 0." << std::endl;
  }

  double overclustering = CLI::GetParam<double>("overclustering");
  if (overclustering < 1)
  {
    Log::Fatal << "Invalid value for overclustering (" << overclustering <<
        ")! Must be greater than or equal to 1." << std::endl;
  }

  // Make sure we have an output file if we're not doing the work in-place.
  if (!CLI::HasParam("in_place") && !CLI::HasParam("output_file"))
  {
    Log::Fatal << "--outputFile not specified (and --in_place not set)."
        << std::endl;
  }

  // Load our dataset.
  arma::mat dataset;
  data::Load(inputFile.c_str(), dataset, true); // Fatal upon failure.

  // Now create the KMeans object.  Because we could be using different types,
  // it gets a little weird...
  arma::Col<size_t> assignments;
  arma::mat centroids;

  if (CLI::HasParam("allow_empty_clusters"))
  {
    if (CLI::HasParam("refined_start"))
    {
      const int samplings = CLI::GetParam<int>("samplings");
      const double percentage = CLI::GetParam<int>("percentage");

      if (samplings < 0)
        Log::Fatal << "Number of samplings (" << samplings << ") must be "
            << "greater than 0!" << std::endl;
      if (percentage <= 0.0 || percentage > 1.0)
        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;

      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
          RefinedStart(samplings, percentage));

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
    else
    {
      KMeans<metric::SquaredEuclideanDistance, RandomPartition,
          AllowEmptyClusters> k(maxIterations, overclustering);

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
  }
  else
  {
    if (CLI::HasParam("refined_start"))
    {
      const int samplings = CLI::GetParam<int>("samplings");
      const double percentage = CLI::GetParam<int>("percentage");

      if (samplings < 0)
        Log::Fatal << "Number of samplings (" << samplings << ") must be "
            << "greater than 0!" << std::endl;
      if (percentage <= 0.0 || percentage > 1.0)
        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;

      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
          RefinedStart(samplings, percentage));

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
    else
    {
      KMeans<> k(maxIterations, overclustering);

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
  }

  // Now figure out what to do with our results.
  if (CLI::HasParam("in_place"))
  {
    // Add the column of assignments to the dataset; but we have to convert them
    // to type double first.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Save the dataset.
    data::Save(inputFile, dataset);
  }
  else
  {
    if (CLI::HasParam("labels_only"))
    {
      // Save only the labels.
      string outputFile = CLI::GetParam<string>("output_file");
      arma::Mat<size_t> output = trans(assignments);
      data::Save(outputFile, output);
    }
    else
    {
      // Convert the assignments to doubles.
      arma::vec converted(assignments.n_elem);
      for (size_t i = 0; i < assignments.n_elem; i++)
        converted(i) = (double) assignments(i);

      dataset.insert_rows(dataset.n_rows, trans(converted));

      // Now save, in the different file.
      string outputFile = CLI::GetParam<string>("output_file");
      data::Save(outputFile, dataset);
    }
  }

  // Should we write the centroids to a file?
  if (CLI::HasParam("centroid_file"))
    data::Save(CLI::GetParam<std::string>("centroid_file"), centroids);
}

<commit_msg>Add opportunity to set initial centroids.<commit_after>/**
 * @file kmeans_main.cpp
 * @author Ryan Curtin
 *
 * Executable for running K-Means.
 */
#include <mlpack/core.hpp>

#include "kmeans.hpp"
#include "allow_empty_clusters.hpp"
#include "refined_start.hpp"

using namespace mlpack;
using namespace mlpack::kmeans;
using namespace std;

// Define parameters for the executable.
PROGRAM_INFO("K-Means Clustering", "This program performs K-Means clustering "
    "on the given dataset, storing the learned cluster assignments either as "
    "a column of labels in the file containing the input dataset or in a "
    "separate file.  Empty clusters are not allowed by default; when a cluster "
    "becomes empty, the point furthest from the centroid of the cluster with "
    "maximum variance is taken to fill that cluster."
    "\n\n"
    "Optionally, the Bradley and Fayyad approach (\"Refining initial points for"
    " k-means clustering\", 1998) can be used to select initial points by "
    "specifying the --refined_start (-r) option.  This approach works by taking"
    " random samples of the dataset; to specify the number of samples, the "
    "--samples parameter is used, and to specify the percentage of the dataset "
    "to be used in each sample, the --percentage parameter is used (it should "
    "be a value between 0.0 and 1.0).\n");

// Required options.
PARAM_STRING_REQ("inputFile", "Input dataset to perform clustering on.", "i");
PARAM_INT_REQ("clusters", "Number of clusters to find.", "c");

// Output options.
PARAM_FLAG("in_place", "If specified, a column of the learned cluster "
    "assignments will be added to the input dataset file.  In this case, "
    "--outputFile is not necessary.", "p");
PARAM_STRING("output_file", "File to write output labels or labeled data to.",
    "o", "output.csv");
PARAM_STRING("centroid_file", "If specified, the centroids of each cluster will"
    " be written to the given file.", "C", "");

// k-means configuration options.
PARAM_FLAG("allow_empty_clusters", "Allow empty clusters to be created.", "e");
PARAM_FLAG("labels_only", "Only output labels into output file.", "l");
PARAM_DOUBLE("overclustering", "Finds (overclustering * clusters) clusters, "
    "then merges them together until only the desired number of clusters are "
    "left.", "O", 1.0);
PARAM_INT("max_iterations", "Maximum number of iterations before K-Means "
    "terminates.", "m", 1000);
PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);

// This is known to not work (#251).
//PARAM_FLAG("fast_kmeans", "Use the experimental fast k-means algorithm by "
//    "Pelleg and Moore.", "f");

// Parameters for "refined start" k-means.
PARAM_FLAG("refined_start", "Use the refined initial point strategy by Bradley "
    "and Fayyad to choose initial points.", "r");
PARAM_INT("samplings", "Number of samplings to perform for refined start (use "
    "when --refined_start is specified).", "S", 100);
PARAM_DOUBLE("percentage", "Percentage of dataset to use for each refined start"
    " sampling (use when --refined_start is specified).", "p", 0.02);

int main(int argc, char** argv)
{
  CLI::ParseCommandLine(argc, argv);

  // Initialize random seed.
  if (CLI::GetParam<int>("seed") != 0)
    math::RandomSeed((size_t) CLI::GetParam<int>("seed"));
  else
    math::RandomSeed((size_t) std::time(NULL));

  // Now do validation of options.
  string inputFile = CLI::GetParam<string>("inputFile");
  int clusters = CLI::GetParam<int>("clusters");
  if (clusters < 1)
  {
    Log::Fatal << "Invalid number of clusters requested (" << clusters << ")! "
        << "Must be greater than or equal to 1." << std::endl;
  }

  int maxIterations = CLI::GetParam<int>("max_iterations");
  if (maxIterations < 0)
  {
    Log::Fatal << "Invalid value for maximum iterations (" << maxIterations <<
        ")! Must be greater than or equal to 0." << std::endl;
  }

  double overclustering = CLI::GetParam<double>("overclustering");
  if (overclustering < 1)
  {
    Log::Fatal << "Invalid value for overclustering (" << overclustering <<
        ")! Must be greater than or equal to 1." << std::endl;
  }

  // Make sure we have an output file if we're not doing the work in-place.
  if (!CLI::HasParam("in_place") && !CLI::HasParam("output_file"))
  {
    Log::Fatal << "--outputFile not specified (and --in_place not set)."
        << std::endl;
  }

  // Load our dataset.
  arma::mat dataset;
  data::Load(inputFile.c_str(), dataset, true); // Fatal upon failure.

  // Now create the KMeans object.  Because we could be using different types,
  // it gets a little weird...
  arma::Col<size_t> assignments;
  arma::mat centroids;

  bool initialCentroidGuess = CLI::HasParam("initial_centroid");
  // Load initial centroids if the user asked for it.
  if (initialCentroidGuess)
  {
    string initialCentroidsFile = CLI::GetParam<string>("initial_centroid");
    data::Load(initialCentroidsFile.c_str(), centroids, true);
  }

  if (CLI::HasParam("allow_empty_clusters"))
  {
    if (CLI::HasParam("refined_start"))
    {
      const int samplings = CLI::GetParam<int>("samplings");
      const double percentage = CLI::GetParam<int>("percentage");

      if (samplings < 0)
        Log::Fatal << "Number of samplings (" << samplings << ") must be "
            << "greater than 0!" << std::endl;
      if (percentage <= 0.0 || percentage > 1.0)
        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;

      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
          RefinedStart(samplings, percentage));

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
    else
    {
      KMeans<metric::SquaredEuclideanDistance, RandomPartition,
          AllowEmptyClusters> k(maxIterations, overclustering);

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids, false,
            initialCentroidGuess);
      Timer::Stop("clustering");
    }
  }
  else
  {
    if (CLI::HasParam("refined_start"))
    {
      const int samplings = CLI::GetParam<int>("samplings");
      const double percentage = CLI::GetParam<int>("percentage");

      if (samplings < 0)
        Log::Fatal << "Number of samplings (" << samplings << ") must be "
            << "greater than 0!" << std::endl;
      if (percentage <= 0.0 || percentage > 1.0)
        Log::Fatal << "Percentage for sampling (" << percentage << ") must be "
            << "greater than 0.0 and less than or equal to 1.0!" << std::endl;

      KMeans<metric::SquaredEuclideanDistance, RefinedStart, AllowEmptyClusters>
          k(maxIterations, overclustering, metric::SquaredEuclideanDistance(),
          RefinedStart(samplings, percentage));

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids);
      Timer::Stop("clustering");
    }
    else
    {
      KMeans<> k(maxIterations, overclustering);

      Timer::Start("clustering");
//      if (CLI::HasParam("fast_kmeans"))
//        k.FastCluster(dataset, clusters, assignments);
//      else
        k.Cluster(dataset, clusters, assignments, centroids, false,
            initialCentroidGuess);
      Timer::Stop("clustering");
    }
  }

  // Now figure out what to do with our results.
  if (CLI::HasParam("in_place"))
  {
    // Add the column of assignments to the dataset; but we have to convert them
    // to type double first.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Save the dataset.
    data::Save(inputFile, dataset);
  }
  else
  {
    if (CLI::HasParam("labels_only"))
    {
      // Save only the labels.
      string outputFile = CLI::GetParam<string>("output_file");
      arma::Mat<size_t> output = trans(assignments);
      data::Save(outputFile, output);
    }
    else
    {
      // Convert the assignments to doubles.
      arma::vec converted(assignments.n_elem);
      for (size_t i = 0; i < assignments.n_elem; i++)
        converted(i) = (double) assignments(i);

      dataset.insert_rows(dataset.n_rows, trans(converted));

      // Now save, in the different file.
      string outputFile = CLI::GetParam<string>("output_file");
      data::Save(outputFile, dataset);
    }
  }

  // Should we write the centroids to a file?
  if (CLI::HasParam("centroid_file"))
    data::Save(CLI::GetParam<std::string>("centroid_file"), centroids);
}

<|endoftext|>


<commit_before>// Copyright (c) 2015 The Brick Authors.

#include "brick/avatar_client.h"

#include <fstream>

#include "include/base/cef_logging.h"
#include "brick/platform_util.h"
#include "brick/helper.h"

namespace {
  const char kTmpSuffix[] = ".tmp";
}  // namespace

AvatarClient::AvatarClient(const Callback& callback, const std::string& path)
    : callback_(callback),
      file_path_(path) {

  CEF_REQUIRE_UI_THREAD();
  DCHECK(!callback_.is_null());
  tmp_file_path_ = path + kTmpSuffix;
  tmp_file_.open(tmp_file_path_, std::ofstream::binary);
}

void
AvatarClient::Detach() {
  CEF_REQUIRE_UI_THREAD();
  if (!callback_.is_null())
    callback_.Reset();

  tmp_file_.close();
}

void
AvatarClient::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
  CEF_REQUIRE_UI_THREAD();
  if (callback_.is_null())
    return;

  tmp_file_.close();
  if (request->GetRequestError() == ERR_NONE && request->GetResponse()->GetStatus() == 200) {
    rename(tmp_file_path_.c_str(), file_path_.c_str());
    callback_.Run(true);
  } else {
    LOG(WARNING) << "Can't download notification icon '"
                 << request->GetRequest()->GetURL().ToString()
                 << "' to file '" << file_path_ << "'";

    callback_.Run(false);
  }

  callback_.Reset();
}

void
AvatarClient::OnDownloadData(CefRefPtr<CefURLRequest> request,
                           const void* data,
                           size_t data_length) {

  CEF_REQUIRE_UI_THREAD();
  tmp_file_.write(static_cast<const char*>(data), data_length);
}

// static methods

CefRefPtr<CefURLRequest>
AvatarClient::CreateRequest(
    const Callback& callback,
    const std::string& url,
    const std::string& path) {

  CEF_REQUIRE_UI_THREAD();

  if (!platform_util::MakeDirectory(helper::BaseDir(path)))
    return NULL;

  CefRefPtr<CefRequest> request = CefRequest::Create();
  request->SetURL(url);
  request->SetMethod("GET");
  request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);

  // Create and start the new CefURLRequest.
  return CefURLRequest::Create(request, new AvatarClient(callback, path));
}
<commit_msg>Не позволяем дважды запустится одной и той же закачке.<commit_after>// Copyright (c) 2015 The Brick Authors.

#include "brick/avatar_client.h"

#include <fstream>

#include "include/base/cef_logging.h"
#include "brick/platform_util.h"
#include "brick/helper.h"

namespace {
  const char kTmpSuffix[] = ".tmp";
}  // namespace

AvatarClient::AvatarClient(const Callback& callback, const std::string& path)
    : callback_(callback),
      file_path_(path) {

  CEF_REQUIRE_UI_THREAD();
  DCHECK(!callback_.is_null());
  tmp_file_path_ = path + kTmpSuffix;
  tmp_file_.open(tmp_file_path_, std::ofstream::binary);
}

void
AvatarClient::Detach() {
  CEF_REQUIRE_UI_THREAD();
  if (!callback_.is_null())
    callback_.Reset();

  tmp_file_.close();
}

void
AvatarClient::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
  CEF_REQUIRE_UI_THREAD();
  if (callback_.is_null())
    return;

  tmp_file_.close();
  if (request->GetRequestError() == ERR_NONE && request->GetResponse()->GetStatus() == 200) {
    rename(tmp_file_path_.c_str(), file_path_.c_str());
    callback_.Run(true);
  } else {
    LOG(WARNING) << "Can't download notification icon '"
                 << request->GetRequest()->GetURL().ToString()
                 << "' to file '" << file_path_ << "'";

    callback_.Run(false);
  }

  callback_.Reset();
}

void
AvatarClient::OnDownloadData(CefRefPtr<CefURLRequest> request,
                           const void* data,
                           size_t data_length) {

  CEF_REQUIRE_UI_THREAD();
  tmp_file_.write(static_cast<const char*>(data), data_length);
}

// static methods

CefRefPtr<CefURLRequest>
AvatarClient::CreateRequest(
    const Callback& callback,
    const std::string& url,
    const std::string& path) {

  CEF_REQUIRE_UI_THREAD();

  if (platform_util::IsPathExists(path + kTmpSuffix))
    return NULL;  // Probably we already started downloading for current avatar

  if (!platform_util::MakeDirectory(helper::BaseDir(path)))
    return NULL;

  CefRefPtr<CefRequest> request = CefRequest::Create();
  request->SetURL(url);
  request->SetMethod("GET");
  request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);

  // Create and start the new CefURLRequest.
  return CefURLRequest::Create(request, new AvatarClient(callback, path));
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm 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 "query_builder.hpp"
#include "parser.hpp"

#include <realm.hpp>
#include "object_store.hpp"
#include "schema.hpp"

#include <assert.h>

namespace realm {
namespace query_builder {
using namespace parser;

// check a precondition and throw an exception if it is not met
// this should be used iff the condition being false indicates a bug in the caller
// of the function checking its preconditions
static void precondition(bool condition, const std::string message) {
    if (__builtin_expect(condition, 1)) {
        return;
    }
    throw std::runtime_error(message);
}

// FIXME: TrueExpression and FalseExpression should be supported by core in some way
struct TrueExpression : realm::Expression {
    size_t find_first(size_t start, size_t end) const override
    {
        if (start != end)
            return start;

        return not_found;
    }
    void set_table() override {}
    const Table* get_table() const override { return nullptr; }
};

struct FalseExpression : realm::Expression {
    size_t find_first(size_t, size_t) const override { return not_found; }
    void set_table() override {}
    const Table* get_table() const override { return nullptr; }
};

// add a clause for numeric constraints based on operator type
template <typename A, typename B>
void add_numeric_constraint_to_query(Query& query,
                                     Predicate::Operator operatorType,
                                     A lhs,
                                     B rhs)
{
    switch (operatorType) {
        case Predicate::Operator::LessThan:
            query.and_query(lhs < rhs);
            break;
        case Predicate::Operator::LessThanOrEqual:
            query.and_query(lhs <= rhs);
            break;
        case Predicate::Operator::GreaterThan:
            query.and_query(lhs > rhs);
            break;
        case Predicate::Operator::GreaterThanOrEqual:
            query.and_query(lhs >= rhs);
            break;
        case Predicate::Operator::Equal:
            query.and_query(lhs == rhs);
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(lhs != rhs);
            break;
        default:
            throw std::runtime_error("Unsupported operator for numeric queries.");
    }
}

template <typename A, typename B>
void add_bool_constraint_to_query(Query &query, Predicate::Operator operatorType, A lhs, B rhs) {
    switch (operatorType) {
        case Predicate::Operator::Equal:
            query.and_query(lhs == rhs);
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(lhs != rhs);
            break;
        default:
            throw std::runtime_error("Unsupported operator for numeric queries.");
    }
}

void add_string_constraint_to_query(Query &query,
                                    Predicate::Operator op,
                                    Columns<String> &&column,
                                    StringData value) {
    bool case_sensitive = true;
    StringData sd = value;
    switch (op) {
        case Predicate::Operator::BeginsWith:
            query.and_query(column.begins_with(sd, case_sensitive));
            break;
        case Predicate::Operator::EndsWith:
            query.and_query(column.ends_with(sd, case_sensitive));
            break;
        case Predicate::Operator::Contains:
            query.and_query(column.contains(sd, case_sensitive));
            break;
        case Predicate::Operator::Equal:
            query.and_query(column.equal(sd, case_sensitive));
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(column.not_equal(sd, case_sensitive));
            break;
        default:
            throw std::runtime_error("Unsupported operator for string queries.");
    }
}

void add_string_constraint_to_query(realm::Query& query,
                                    Predicate::Operator op,
                                    StringData value,
                                    Columns<String> &&column) {
    bool case_sensitive = true;
    StringData sd = value;
    switch (op) {
        case Predicate::Operator::Equal:
            query.and_query(column.equal(sd, case_sensitive));
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(column.not_equal(sd, case_sensitive));
            break;
        default:
            throw std::runtime_error("Substring comparison not supported for keypath substrings.");
    }
}

using KeyPath = std::vector<std::string>;
KeyPath key_path_from_string(const std::string &s) {
    std::stringstream ss(s);
    std::string item;
    KeyPath key_path;
    while (std::getline(ss, item, '.')) {
        key_path.push_back(item);
    }
    return key_path;
}

struct PropertyExpression
{
    Property *prop = nullptr;
    std::vector<size_t> indexes;
    std::function<Table *()> table_getter;

    PropertyExpression(Query &query, Schema &schema, ObjectSchema &desc, const std::string &key_path_string)
    {
        KeyPath key_path = key_path_from_string(key_path_string);
        for (size_t index = 0; index < key_path.size(); index++) {
            if (prop) {
                precondition(prop->type == PropertyTypeObject || prop->type == PropertyTypeArray,
                             (std::string)"Property '" + key_path[index] + "' is not a link in object of type '" + desc.name + "'");
                indexes.push_back(prop->table_column);

            }
            prop = desc.property_for_name(key_path[index]);
            precondition(prop != nullptr, "No property '" + key_path[index] + "' on object of type '" + desc.name + "'");

            if (prop->object_type.size()) {
                desc = *schema.find(prop->object_type);
            }
        }

        table_getter = [&] {
            TableRef& tbl = query.get_table();
            for (size_t col : indexes) {
                tbl->link(col); // mutates m_link_chain on table
            }
            return tbl.get();
        };
    }
};

template <typename RetType, typename TableGetter>
struct ColumnGetter {
    static Columns<RetType> convert(TableGetter&& table, const PropertyExpression & expr, Arguments &args)
    {
        return table()->template column<RetType>(expr.prop->table_column);
    }
};

template <typename RequestedType, typename TableGetter>
struct ValueGetter;

template <typename TableGetter>
struct ValueGetter<DateTime, TableGetter> {
    static Int convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type != parser::Expression::Type::Argument) {
            throw std::runtime_error("You must pass in a date argument to compare");
        }
        DateTime dt = args.datetime_for_argument(std::stoi(value.s));
        return dt.get_datetime();
    }
};

template <typename TableGetter>
struct ValueGetter<bool, TableGetter> {
    static bool convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.bool_for_argument(std::stoi(value.s));
        }
        return value.type == parser::Expression::Type::True;
    }
};

template <typename TableGetter>
struct ValueGetter<Double, TableGetter> {
    static Double convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.double_for_argument(std::stoi(value.s));
        }
        return std::stod(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<Float, TableGetter> {
    static Float convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.float_for_argument(std::stoi(value.s));
        }
        return std::stof(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<Int, TableGetter> {
    static Int convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.long_for_argument(std::stoi(value.s));
        }
        return std::stoll(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<String, TableGetter> {
    static std::string convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.string_for_argument(std::stoi(value.s));
        }
        return value.s;
    }
};

template <typename RetType, typename Value, typename TableGetter>
auto value_of_type_for_query(TableGetter&& tables, Value&& value, Arguments &args)
{
    const bool isColumn = std::is_same<PropertyExpression, typename std::remove_reference<Value>::type>::value;
    using helper = std::conditional_t<isColumn, ColumnGetter<RetType, TableGetter>, ValueGetter<RetType, TableGetter>>;
    return helper::convert(std::forward<TableGetter>(tables), std::forward<Value>(value), args);
}

template <typename A, typename B>
void do_add_comparison_to_query(Query &query, Schema &schema, ObjectSchema &object_schema, Predicate::Operator op,
                                PropertyExpression &expr, A &lhs, B &rhs, Arguments &args)
{
    auto type = expr.prop->type;
    switch (type) {
        case PropertyTypeBool:
            add_bool_constraint_to_query(query, op, value_of_type_for_query<bool>(expr.table_getter, lhs, args),
                                                    value_of_type_for_query<bool>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeDate:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<DateTime>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<DateTime>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeDouble:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Double>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Double>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeFloat:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Float>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Float>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeInt:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Int>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Int>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeString:
        case PropertyTypeData:
            add_string_constraint_to_query(query, op, value_of_type_for_query<String>(expr.table_getter, lhs, args),
                                                      value_of_type_for_query<String>(expr.table_getter, rhs, args));
            break;
        default: {
            throw std::runtime_error((std::string)"Object type " + string_for_property_type(type) + " not supported");
        }
    }
}

void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, Schema &schema, ObjectSchema &object_schema)
{
    Predicate::Comparison &cmpr = pred.cmpr;
    auto t0 = cmpr.expr[0].type, t1 = cmpr.expr[1].type;
    if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) {
        PropertyExpression expr(query, schema, object_schema, cmpr.expr[0].s);
        do_add_comparison_to_query(query, schema, object_schema, cmpr.op, expr, expr, cmpr.expr[1], args);
    }
    else if (t0 != parser::Expression::Type::KeyPath && t1 == parser::Expression::Type::KeyPath) {
        PropertyExpression expr(query, schema, object_schema, cmpr.expr[1].s);
        do_add_comparison_to_query(query, schema, object_schema, cmpr.op, expr, cmpr.expr[0], expr, args);
    }
    else {
        throw std::runtime_error("Predicate expressions must compare a keypath and another keypath or a constant value");
    }
}

void update_query_with_predicate(Query &query, Predicate &pred, Arguments &arguments, Schema &schema, ObjectSchema &object_schema)
{
    if (pred.negate) {
        query.Not();
    }

    switch (pred.type) {
        case Predicate::Type::And:
            query.group();
            for (auto &sub : pred.cpnd.sub_predicates) {
                update_query_with_predicate(query, sub, arguments, schema, object_schema);
            }
            if (!pred.cpnd.sub_predicates.size()) {
                query.and_query(new TrueExpression);
            }
            query.end_group();
            break;

        case Predicate::Type::Or:
            query.group();
            for (auto &sub : pred.cpnd.sub_predicates) {
                query.Or();
                update_query_with_predicate(query, sub, arguments, schema, object_schema);
            }
            if (!pred.cpnd.sub_predicates.size()) {
                query.and_query(new FalseExpression);
            }
            query.end_group();
            break;

        case Predicate::Type::Comparison: {
            add_comparison_to_query(query, pred, arguments, schema, object_schema);
            break;
        }
        case Predicate::Type::True:
            query.and_query(new TrueExpression);
            break;

        case Predicate::Type::False:
            query.and_query(new FalseExpression);
            break;

        default:
            throw std::runtime_error("Invalid predicate type");
            break;
    }
}

void apply_predicate(Query &query, Predicate &predicate, Arguments &arguments, Schema &schema, std::string objectType)
{
    update_query_with_predicate(query, predicate, arguments, schema, *schema.find(objectType));

    // Test the constructed query in core
    std::string validateMessage = query.validate();
    precondition(validateMessage.empty(), validateMessage.c_str());
}

}}
<commit_msg>make precondition a macro<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm 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 "query_builder.hpp"
#include "parser.hpp"

#include <realm.hpp>
#include "object_store.hpp"
#include "schema.hpp"

#include <assert.h>

namespace realm {
namespace query_builder {
using namespace parser;

// check a precondition and throw an exception if it is not met
// this should be used iff the condition being false indicates a bug in the caller
// of the function checking its preconditions
#define precondition(condition, message) if (!__builtin_expect(condition, 1)) {  throw std::runtime_error(message); }

// FIXME: TrueExpression and FalseExpression should be supported by core in some way
struct TrueExpression : realm::Expression {
    size_t find_first(size_t start, size_t end) const override
    {
        if (start != end)
            return start;

        return not_found;
    }
    void set_table() override {}
    const Table* get_table() const override { return nullptr; }
};

struct FalseExpression : realm::Expression {
    size_t find_first(size_t, size_t) const override { return not_found; }
    void set_table() override {}
    const Table* get_table() const override { return nullptr; }
};

// add a clause for numeric constraints based on operator type
template <typename A, typename B>
void add_numeric_constraint_to_query(Query& query,
                                     Predicate::Operator operatorType,
                                     A lhs,
                                     B rhs)
{
    switch (operatorType) {
        case Predicate::Operator::LessThan:
            query.and_query(lhs < rhs);
            break;
        case Predicate::Operator::LessThanOrEqual:
            query.and_query(lhs <= rhs);
            break;
        case Predicate::Operator::GreaterThan:
            query.and_query(lhs > rhs);
            break;
        case Predicate::Operator::GreaterThanOrEqual:
            query.and_query(lhs >= rhs);
            break;
        case Predicate::Operator::Equal:
            query.and_query(lhs == rhs);
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(lhs != rhs);
            break;
        default:
            throw std::runtime_error("Unsupported operator for numeric queries.");
    }
}

template <typename A, typename B>
void add_bool_constraint_to_query(Query &query, Predicate::Operator operatorType, A lhs, B rhs) {
    switch (operatorType) {
        case Predicate::Operator::Equal:
            query.and_query(lhs == rhs);
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(lhs != rhs);
            break;
        default:
            throw std::runtime_error("Unsupported operator for numeric queries.");
    }
}

void add_string_constraint_to_query(Query &query,
                                    Predicate::Operator op,
                                    Columns<String> &&column,
                                    StringData value) {
    bool case_sensitive = true;
    StringData sd = value;
    switch (op) {
        case Predicate::Operator::BeginsWith:
            query.and_query(column.begins_with(sd, case_sensitive));
            break;
        case Predicate::Operator::EndsWith:
            query.and_query(column.ends_with(sd, case_sensitive));
            break;
        case Predicate::Operator::Contains:
            query.and_query(column.contains(sd, case_sensitive));
            break;
        case Predicate::Operator::Equal:
            query.and_query(column.equal(sd, case_sensitive));
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(column.not_equal(sd, case_sensitive));
            break;
        default:
            throw std::runtime_error("Unsupported operator for string queries.");
    }
}

void add_string_constraint_to_query(realm::Query& query,
                                    Predicate::Operator op,
                                    StringData value,
                                    Columns<String> &&column) {
    bool case_sensitive = true;
    StringData sd = value;
    switch (op) {
        case Predicate::Operator::Equal:
            query.and_query(column.equal(sd, case_sensitive));
            break;
        case Predicate::Operator::NotEqual:
            query.and_query(column.not_equal(sd, case_sensitive));
            break;
        default:
            throw std::runtime_error("Substring comparison not supported for keypath substrings.");
    }
}

using KeyPath = std::vector<std::string>;
KeyPath key_path_from_string(const std::string &s) {
    std::stringstream ss(s);
    std::string item;
    KeyPath key_path;
    while (std::getline(ss, item, '.')) {
        key_path.push_back(item);
    }
    return key_path;
}

struct PropertyExpression
{
    Property *prop = nullptr;
    std::vector<size_t> indexes;
    std::function<Table *()> table_getter;

    PropertyExpression(Query &query, Schema &schema, ObjectSchema &desc, const std::string &key_path_string)
    {
        KeyPath key_path = key_path_from_string(key_path_string);
        for (size_t index = 0; index < key_path.size(); index++) {
            if (prop) {
                precondition(prop->type == PropertyTypeObject || prop->type == PropertyTypeArray,
                             (std::string)"Property '" + key_path[index] + "' is not a link in object of type '" + desc.name + "'");
                indexes.push_back(prop->table_column);

            }
            prop = desc.property_for_name(key_path[index]);
            precondition(prop != nullptr, "No property '" + key_path[index] + "' on object of type '" + desc.name + "'");

            if (prop->object_type.size()) {
                desc = *schema.find(prop->object_type);
            }
        }

        table_getter = [&] {
            TableRef& tbl = query.get_table();
            for (size_t col : indexes) {
                tbl->link(col); // mutates m_link_chain on table
            }
            return tbl.get();
        };
    }
};

template <typename RetType, typename TableGetter>
struct ColumnGetter {
    static Columns<RetType> convert(TableGetter&& table, const PropertyExpression & expr, Arguments &args)
    {
        return table()->template column<RetType>(expr.prop->table_column);
    }
};

template <typename RequestedType, typename TableGetter>
struct ValueGetter;

template <typename TableGetter>
struct ValueGetter<DateTime, TableGetter> {
    static Int convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type != parser::Expression::Type::Argument) {
            throw std::runtime_error("You must pass in a date argument to compare");
        }
        DateTime dt = args.datetime_for_argument(std::stoi(value.s));
        return dt.get_datetime();
    }
};

template <typename TableGetter>
struct ValueGetter<bool, TableGetter> {
    static bool convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.bool_for_argument(std::stoi(value.s));
        }
        return value.type == parser::Expression::Type::True;
    }
};

template <typename TableGetter>
struct ValueGetter<Double, TableGetter> {
    static Double convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.double_for_argument(std::stoi(value.s));
        }
        return std::stod(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<Float, TableGetter> {
    static Float convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.float_for_argument(std::stoi(value.s));
        }
        return std::stof(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<Int, TableGetter> {
    static Int convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.long_for_argument(std::stoi(value.s));
        }
        return std::stoll(value.s);
    }
};

template <typename TableGetter>
struct ValueGetter<String, TableGetter> {
    static std::string convert(TableGetter&&, const parser::Expression & value, Arguments &args)
    {
        if (value.type == parser::Expression::Type::Argument) {
            return args.string_for_argument(std::stoi(value.s));
        }
        return value.s;
    }
};

template <typename RetType, typename Value, typename TableGetter>
auto value_of_type_for_query(TableGetter&& tables, Value&& value, Arguments &args)
{
    const bool isColumn = std::is_same<PropertyExpression, typename std::remove_reference<Value>::type>::value;
    using helper = std::conditional_t<isColumn, ColumnGetter<RetType, TableGetter>, ValueGetter<RetType, TableGetter>>;
    return helper::convert(std::forward<TableGetter>(tables), std::forward<Value>(value), args);
}

template <typename A, typename B>
void do_add_comparison_to_query(Query &query, Schema &schema, ObjectSchema &object_schema, Predicate::Operator op,
                                PropertyExpression &expr, A &lhs, B &rhs, Arguments &args)
{
    auto type = expr.prop->type;
    switch (type) {
        case PropertyTypeBool:
            add_bool_constraint_to_query(query, op, value_of_type_for_query<bool>(expr.table_getter, lhs, args),
                                                    value_of_type_for_query<bool>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeDate:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<DateTime>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<DateTime>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeDouble:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Double>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Double>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeFloat:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Float>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Float>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeInt:
            add_numeric_constraint_to_query(query, op, value_of_type_for_query<Int>(expr.table_getter, lhs, args),
                                                       value_of_type_for_query<Int>(expr.table_getter, rhs, args));
            break;
        case PropertyTypeString:
        case PropertyTypeData:
            add_string_constraint_to_query(query, op, value_of_type_for_query<String>(expr.table_getter, lhs, args),
                                                      value_of_type_for_query<String>(expr.table_getter, rhs, args));
            break;
        default: {
            throw std::runtime_error((std::string)"Object type " + string_for_property_type(type) + " not supported");
        }
    }
}

void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, Schema &schema, ObjectSchema &object_schema)
{
    Predicate::Comparison &cmpr = pred.cmpr;
    auto t0 = cmpr.expr[0].type, t1 = cmpr.expr[1].type;
    if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) {
        PropertyExpression expr(query, schema, object_schema, cmpr.expr[0].s);
        do_add_comparison_to_query(query, schema, object_schema, cmpr.op, expr, expr, cmpr.expr[1], args);
    }
    else if (t0 != parser::Expression::Type::KeyPath && t1 == parser::Expression::Type::KeyPath) {
        PropertyExpression expr(query, schema, object_schema, cmpr.expr[1].s);
        do_add_comparison_to_query(query, schema, object_schema, cmpr.op, expr, cmpr.expr[0], expr, args);
    }
    else {
        throw std::runtime_error("Predicate expressions must compare a keypath and another keypath or a constant value");
    }
}

void update_query_with_predicate(Query &query, Predicate &pred, Arguments &arguments, Schema &schema, ObjectSchema &object_schema)
{
    if (pred.negate) {
        query.Not();
    }

    switch (pred.type) {
        case Predicate::Type::And:
            query.group();
            for (auto &sub : pred.cpnd.sub_predicates) {
                update_query_with_predicate(query, sub, arguments, schema, object_schema);
            }
            if (!pred.cpnd.sub_predicates.size()) {
                query.and_query(new TrueExpression);
            }
            query.end_group();
            break;

        case Predicate::Type::Or:
            query.group();
            for (auto &sub : pred.cpnd.sub_predicates) {
                query.Or();
                update_query_with_predicate(query, sub, arguments, schema, object_schema);
            }
            if (!pred.cpnd.sub_predicates.size()) {
                query.and_query(new FalseExpression);
            }
            query.end_group();
            break;

        case Predicate::Type::Comparison: {
            add_comparison_to_query(query, pred, arguments, schema, object_schema);
            break;
        }
        case Predicate::Type::True:
            query.and_query(new TrueExpression);
            break;

        case Predicate::Type::False:
            query.and_query(new FalseExpression);
            break;

        default:
            throw std::runtime_error("Invalid predicate type");
            break;
    }
}

void apply_predicate(Query &query, Predicate &predicate, Arguments &arguments, Schema &schema, std::string objectType)
{
    update_query_with_predicate(query, predicate, arguments, schema, *schema.find(objectType));

    // Test the constructed query in core
    std::string validateMessage = query.validate();
    precondition(validateMessage.empty(), validateMessage.c_str());
}

}}
<|endoftext|>


<commit_before>// grubcut for video
// Author : reasonW
// Date   : 2016-12-29
// HomePage : http://github.com/reasonW
// Email  :charlewander@gmail.com
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;

const Scalar RED = Scalar(0,0,255);
const Scalar PINK = Scalar(230,130,255);
const Scalar BLUE = Scalar(255,0,0);
const Scalar LIGHTBLUE = Scalar(255,255,160);
const Scalar GREEN = Scalar(0,255,0);

const int BGD_KEY = CV_EVENT_FLAG_CTRLKEY;
const int FGD_KEY = CV_EVENT_FLAG_SHIFTKEY;
int iterCount;
static void getBinMask( const Mat& comMask, Mat& binMask )
{
      if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols )
        binMask.create( comMask.size(), CV_8UC1 );
    binMask = comMask & 1;
}

int main( int argc, char** argv )
{
   	VideoCapture cap;

   	if(argc<=1)
		cap.open(0);
 	else
 		cap.open(argv[1]);
    	if( !cap.isOpened() )
        		return -1;
        		const string winName = "image";
        	Mat image;

	cap>>image;
	if( image.empty() )
		return -1;
	resize(image, image, Size (640,630*image.rows/image.cols));
	Mat mask,res,binMask;
	Mat bgdModel, fgdModel;
	res.create(image.size(), CV_8UC3);
	res.setTo(Scalar(0,0,0));
	imshow(winName, res );
	binMask.setTo(0);

	mask.create( image.size(), CV_8UC1);
    	mask.setTo( GC_BGD );   //GC_BGD == 0
    	int n=0;
	Rect rect;
	rect.x=60;
	rect.y=40;
	rect.width=image.cols-100;
	rect.height=image.rows-80;
    	(mask(rect)).setTo( Scalar(GC_PR_FGD) );    //GC_PR_FGD == 3£¬
	grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
	while(1)
	{
		cap>>image;
		resize(image, image, Size (640,630*image.rows/image.cols));
		//uncomment this line code the programe will be normal
		//grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
		grabCut( image, mask, rect, bgdModel, fgdModel, 2,GC_EVAL );
		getBinMask( mask, binMask );
		image.copyTo( res, binMask );
		//rectangle( res, Point( rect.x, rect.y ), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);
		imshow( winName, res );
		char kk=waitKey(1);
		if (kk == 'q')break;
		else if(kk=='n')
		{
			cout<<n++<< "  ";
		}

	}

	destroyWindow( winName );
	return 0;
}
<commit_msg>move this file to opencv/<commit_after><|endoftext|>


<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

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

#include "EglContext.h"

#define None 0L // redef Xlib nonsense

/* Mask for X events */
#define INPUT_MASK KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask

using namespace std;

namespace Magnum { namespace Contexts {

EglContext::EglContext(int&, char**, const string& title, const Math::Vector2<GLsizei>& size): viewportSize(size) {
    /* Get default X display and root window, init EGL */
    xDisplay = XOpenDisplay(0);
    display = eglGetDisplay(xDisplay);
    eglInitialize(display, 0, 0);
    #ifndef MAGNUM_TARGET_GLES
    eglBindAPI(EGL_OPENGL_API);
    #else
    eglBindAPI(EGL_OPENGL_ES_API);
    #endif
    int screenNumber = DefaultScreen(xDisplay);
    Window root = RootWindow(xDisplay, screenNumber);

    /* Choose EGL config */
    static const EGLint attribs[] = {
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_DEPTH_SIZE, 1,
        #ifndef MAGNUM_TARGET_GLES
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        #else
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        #endif
        EGL_NONE
    };
    EGLConfig config;
    EGLint configCount;
    if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) {
        Error() << "Cannot get EGL visual config";
        exit(1);
    }

    /* Get X visual */
    EGLint visualId;
    if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
        Error() << "Cannot get native visual ID";
        exit(1);
    }
    XVisualInfo *visInfo, visTemplate;
    int visualCount;
    visTemplate.visualid = visualId;
    visInfo = XGetVisualInfo(xDisplay, VisualIDMask, &visTemplate, &visualCount);
    if(!visInfo) {
        Error() << "Cannot get X visual";
        exit(1);
    }

    /* Create X Window */
    XSetWindowAttributes attr;
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(xDisplay, root, visInfo->visual, AllocNone);
    attr.event_mask = StructureNotifyMask|ExposureMask|KeyPressMask;
    unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
    xWindow = XCreateWindow(xDisplay, root, 20, 20, size.x(), size.y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
    XSetStandardProperties(xDisplay, xWindow, title.c_str(), 0, None, 0, 0, 0);
    XFree(visInfo);

    /* Create context and window surface */
    static const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #endif
        EGL_NONE
    };
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
    if(!context) {
        Error() << "Cannot create EGL context";
        exit(1);
    }
    surface = eglCreateWindowSurface(display, config, xWindow, NULL);
    if(!surface) {
        Error() << "Cannot create window surface";
        exit(1);
    }

    /* Capture exposure, keyboard and mouse button events */
    XSelectInput(xDisplay, xWindow, INPUT_MASK);

    /* Set OpenGL context as current */
    eglMakeCurrent(display, surface, surface, context);

    /** @bug Fixme: GLEW initialization fails (thinks that the context is not created) */
    #ifndef MAGNUM_TARGET_GLES
    /* Init GLEW */
    GLenum err = glewInit();
    if(err != GLEW_OK) {
        Error() << "EglContext: cannot initialize GLEW:" << glewGetErrorString(err);
        exit(1);
    }
    #endif
}

EglContext::~EglContext() {
    /* Shut down EGL */
    eglDestroyContext(display, context);
    eglDestroySurface(display, surface);
    eglTerminate(display);

    /* Shut down X */
    XDestroyWindow(xDisplay, xWindow);
    XCloseDisplay(xDisplay);
}

int EglContext::exec() {
    /* Show window */
    XMapWindow(xDisplay, xWindow);

    /* Call viewportEvent for the first time */
    viewportEvent(viewportSize);

    while(true) {
        XEvent event;
        while(XCheckWindowEvent(xDisplay, xWindow, INPUT_MASK, &event)) {
            switch(event.type) {
                case KeyPress:
                    keyPressEvent(static_cast<Key>(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y});
                    break;
                case KeyRelease:
                    keyReleaseEvent(static_cast<Key>(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y});
                    break;
                case ButtonPress:
                    mousePressEvent(static_cast<MouseButton>(event.xbutton.button), {event.xbutton.x, event.xbutton.y});
                    break;
                case ButtonRelease:
                    mouseReleaseEvent(static_cast<MouseButton>(event.xbutton.button), {event.xbutton.x, event.xbutton.y});
                    break;
            }
        }

        /** @todo Handle at least window closing and resizing */
        drawEvent();
    }

    return 0;
}

}}
<commit_msg>EglContext: Not sure what this did, but this doesn't affect anything.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

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

#include "EglContext.h"

#define None 0L // redef Xlib nonsense

/* Mask for X events */
#define INPUT_MASK KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask

using namespace std;

namespace Magnum { namespace Contexts {

EglContext::EglContext(int&, char**, const string& title, const Math::Vector2<GLsizei>& size): viewportSize(size) {
    /* Get default X display and root window, init EGL */
    xDisplay = XOpenDisplay(0);
    display = eglGetDisplay(xDisplay);
    eglInitialize(display, 0, 0);
    #ifndef MAGNUM_TARGET_GLES
    eglBindAPI(EGL_OPENGL_API);
    #else
    eglBindAPI(EGL_OPENGL_ES_API);
    #endif
    int screenNumber = DefaultScreen(xDisplay);
    Window root = RootWindow(xDisplay, screenNumber);

    /* Choose EGL config */
    static const EGLint attribs[] = {
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_DEPTH_SIZE, 1,
        #ifndef MAGNUM_TARGET_GLES
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        #else
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        #endif
        EGL_NONE
    };
    EGLConfig config;
    EGLint configCount;
    if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) {
        Error() << "Cannot get EGL visual config";
        exit(1);
    }

    /* Get X visual */
    EGLint visualId;
    if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
        Error() << "Cannot get native visual ID";
        exit(1);
    }
    XVisualInfo *visInfo, visTemplate;
    int visualCount;
    visTemplate.visualid = visualId;
    visInfo = XGetVisualInfo(xDisplay, VisualIDMask, &visTemplate, &visualCount);
    if(!visInfo) {
        Error() << "Cannot get X visual";
        exit(1);
    }

    /* Create X Window */
    XSetWindowAttributes attr;
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(xDisplay, root, visInfo->visual, AllocNone);
    attr.event_mask = 0;
    unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
    xWindow = XCreateWindow(xDisplay, root, 20, 20, size.x(), size.y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
    XSetStandardProperties(xDisplay, xWindow, title.c_str(), 0, None, 0, 0, 0);
    XFree(visInfo);

    /* Create context and window surface */
    static const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #endif
        EGL_NONE
    };
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
    if(!context) {
        Error() << "Cannot create EGL context";
        exit(1);
    }
    surface = eglCreateWindowSurface(display, config, xWindow, NULL);
    if(!surface) {
        Error() << "Cannot create window surface";
        exit(1);
    }

    /* Capture exposure, keyboard and mouse button events */
    XSelectInput(xDisplay, xWindow, INPUT_MASK);

    /* Set OpenGL context as current */
    eglMakeCurrent(display, surface, surface, context);

    /** @bug Fixme: GLEW initialization fails (thinks that the context is not created) */
    #ifndef MAGNUM_TARGET_GLES
    /* Init GLEW */
    GLenum err = glewInit();
    if(err != GLEW_OK) {
        Error() << "EglContext: cannot initialize GLEW:" << glewGetErrorString(err);
        exit(1);
    }
    #endif
}

EglContext::~EglContext() {
    /* Shut down EGL */
    eglDestroyContext(display, context);
    eglDestroySurface(display, surface);
    eglTerminate(display);

    /* Shut down X */
    XDestroyWindow(xDisplay, xWindow);
    XCloseDisplay(xDisplay);
}

int EglContext::exec() {
    /* Show window */
    XMapWindow(xDisplay, xWindow);

    /* Call viewportEvent for the first time */
    viewportEvent(viewportSize);

    while(true) {
        XEvent event;
        while(XCheckWindowEvent(xDisplay, xWindow, INPUT_MASK, &event)) {
            switch(event.type) {
                case KeyPress:
                    keyPressEvent(static_cast<Key>(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y});
                    break;
                case KeyRelease:
                    keyReleaseEvent(static_cast<Key>(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y});
                    break;
                case ButtonPress:
                    mousePressEvent(static_cast<MouseButton>(event.xbutton.button), {event.xbutton.x, event.xbutton.y});
                    break;
                case ButtonRelease:
                    mouseReleaseEvent(static_cast<MouseButton>(event.xbutton.button), {event.xbutton.x, event.xbutton.y});
                    break;
            }
        }

        /** @todo Handle at least window closing and resizing */
        drawEvent();
    }

    return 0;
}

}}
<|endoftext|>


<commit_before>#include <Core/Index/IndexMap.hpp>

namespace Ra {
namespace Core {

/// ===============================================================================
/// CONSTRUCTOR
/// ===============================================================================
template < typename T >
IndexMap< T >::IndexMap() :
    m_data(),
    m_index(),
    m_free( 1, Index( 0 ) ) { }

template < typename T >
IndexMap< T >::IndexMap( const IndexMap& id_map ) :
    m_data( id_map.m_data ),
    m_index( id_map.m_index ),
    m_free( id_map.m_free ) { }

/// ===============================================================================
/// DESTRUCTOR
/// ===============================================================================
template < typename T >
IndexMap< T >::~IndexMap() { }

/// ===============================================================================
/// INSERT
/// ===============================================================================
template < typename T >
inline Index IndexMap< T >::insert( const T& obj ) {
    Index idx;
    if( pop_free_index( idx ) ) {
        typename std::deque< Index >::iterator it = std::lower_bound( m_index.begin(), m_index.end(), idx );
        if( it == m_index.end() ) {
            m_data.insert( m_data.end(), obj );
        } else {
            m_data.insert( ( m_data.begin() + ( it - m_index.begin() ) ), obj );
        }
        m_index.insert( it, idx );
    }
    return idx;
}

template < typename T >
inline bool IndexMap< T >::insert( const T& obj,
                                   Index&   idx ) {
    if( !pop_free_index( idx ) ) {
        return false;
    }
    typename std::deque< Index >::iterator it = std::lower_bound( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        m_data.insert( m_data.end(), obj );
    } else {
        m_data.insert( ( m_data.begin() + ( it - m_index.begin() ) ), obj );
    }
    m_index.insert( it, idx );
    return true;
}

/// ===============================================================================
/// REMOVE
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::remove( const Index& idx ) {
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    m_data.erase( m_data.begin() + ( it - m_index.begin() ) );
    m_index.erase( it );
    push_free_index( idx );
    return true;
}

template < typename T >
inline bool IndexMap< T >::remove( const uint i ) {
    if( i >= m_data.size() ) {
        return false;
    }
    push_free_index( m_index[i] );
    m_data.erase( m_data.begin() + i );
    m_index.erase( m_index.begin() + i );
    return true;
}

/// ===============================================================================
/// ACCESS
/// ===============================================================================
template < typename T >
inline T IndexMap< T >::at( const Index& idx ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    CORE_ASSERT( it != m_index.end(), "Index not found" );
    return m_data.at( it - m_index.begin() );
}

template < typename T >
inline T IndexMap< T >::at( const uint i ) const {
    CORE_ASSERT( ( i < m_data.size() ), "Index i out of bound" );
    return m_data.at( i );
}

template < typename T >
inline bool IndexMap< T >::at( const Index& idx,
                               T&           obj ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    obj = m_data.at( it - m_index.begin() );
    return true;
}

template < typename T >
inline bool IndexMap< T >::at( const uint i,
                               T&         obj ) const {
    if( i >= m_data.size() ) {
        return false;
    }
    obj = m_data.at( i );
    return true;
}

template < typename T >
inline T& IndexMap< T >::access( const Index& idx ) {
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    CORE_ASSERT( ( it != m_index.end() ), "Index not found" );
    return m_data[ it - m_index.begin() - 1 ];
}

template < typename T >
inline T& IndexMap< T >::access( const uint i ) {
    CORE_ASSERT( ( i < m_data.size() ) , "Index i out of bound");
    return m_data[i];
}

template < typename T >
inline bool IndexMap< T >::access( const Index& idx,
                                   T&           obj ) {
    if( m_data.empty() ) {
        return false;
    }
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    obj = m_data[ it - m_index.begin() - 1 ];
    return true;
}

template < typename T >
inline bool IndexMap< T >::access( const uint i,
                                   T&         obj ) {
    if( i >= m_data.size() ) {
        return false;
    }
    obj = m_data[i];
    return true;
}

/// ===============================================================================
/// SIZE
/// ===============================================================================
template < typename T >
inline uint IndexMap< T >::size() const {
    return m_data.size();
}

template < typename T >
inline void IndexMap< T >::clear() {
    m_index.clear();
    m_data.clear();
    m_free.clear();
    m_free.push_back( Index( 0 ) );
}

/// ===============================================================================
/// QUERY
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::empty() const {
    return  m_data.empty();
}

template < typename T >
inline bool IndexMap< T >::full() const {
    return m_free.empty();
}

template < typename T >
inline bool IndexMap< T >::contain( const Index& idx ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    return !( it == m_index.end() );
}

template < typename T >
inline bool IndexMap< T >::compact() const {
    return ( m_free.front() > m_data.size() );
}

template < typename T >
inline Index IndexMap< T >::index( const uint i ) const {
    if( i >= m_index.size() ) {
        return Index::INVALID_IDX();
    }
    return m_index.at( i );
}

template < typename T >
inline bool IndexMap< T >::index( const uint i, Index& idx ) const {
    if( i >= m_index.size() ) {
        return false;
    }
    idx = m_index.at( i );
    return true;
}

/// ===============================================================================
/// OPERATOR
/// ===============================================================================
template < typename T >
inline T& IndexMap< T >::operator[]( const Index& idx ) {
    return access( idx );
}

template < typename T >
inline T& IndexMap< T >::operator[]( const uint i ) {
    return access( i );
}

template < typename T >
inline Index& IndexMap< T >::operator<<( const T& obj ) {
    return insert( obj );
}

template < typename T >
inline IndexMap< T >& IndexMap< T >::operator>>( const Index& idx ) {
    remove( idx );
    return *this;
}

template < typename T >
inline IndexMap< T >& IndexMap< T >::operator>>( const uint i ) {
    remove( i );
    return *this;
}

/// ===============================================================================
/// INDEX ITERATOR
/// ===============================================================================
template <typename T>
inline typename IndexMap< T >::ConstIndexIterator IndexMap< T >::cbegin_index() const {
    return m_index.cbegin();
}

template <typename T>
inline typename IndexMap< T >::ConstIndexIterator IndexMap< T >::cend_index() const {
    return m_index.cend();
}

/// ===============================================================================
/// DATA ITERATOR
/// ===============================================================================
template <typename T>
inline typename IndexMap< T >::Iterator IndexMap< T >::begin() {
    return m_data.begin();
}

template <typename T>
inline typename IndexMap< T >::Iterator IndexMap< T >::end() {
    return m_data.end();
}

template <typename T>
inline typename IndexMap< T >::ConstIterator IndexMap< T >::cbegin() const {
    return m_data.cbegin();
}

template <typename T>
inline typename IndexMap< T >::ConstIterator IndexMap< T >::cend() const {
    return m_data.cend();
}

/// ===============================================================================
/// PUSH
/// ===============================================================================
template < typename T >
inline void IndexMap< T >::push_free_index( const Index& idx ) {
    std::deque<Index>::iterator free_it = std::lower_bound( m_free.begin(), m_free.end(), idx );
    m_free.insert( free_it, idx );
    if( m_data.empty() ) {
        m_free.clear();
        m_free.push_back( Index( 0 ) );
    }
}

/// ===============================================================================
/// POP
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::pop_free_index( Index& idx ) {
    if( m_free.empty() ) {
        idx = Index::INVALID_IDX();
        return false;
    }
    idx = m_free.front();
    m_free.pop_front();
    if( m_free.empty() ) {
        Index next = idx + 1;
        if( next.isValid() ) {
            if( uint( next.getValue() ) > m_data.size() ) {
                m_free.push_back( next );
            }
        }
    }
    return true;
}

} // namespace Core
} // namespace Ra
<commit_msg>Fix stupid off by one error<commit_after>#include <Core/Index/IndexMap.hpp>

namespace Ra {
namespace Core {

/// ===============================================================================
/// CONSTRUCTOR
/// ===============================================================================
template < typename T >
IndexMap< T >::IndexMap() :
    m_data(),
    m_index(),
    m_free( 1, Index( 0 ) ) { }

template < typename T >
IndexMap< T >::IndexMap( const IndexMap& id_map ) :
    m_data( id_map.m_data ),
    m_index( id_map.m_index ),
    m_free( id_map.m_free ) { }

/// ===============================================================================
/// DESTRUCTOR
/// ===============================================================================
template < typename T >
IndexMap< T >::~IndexMap() { }

/// ===============================================================================
/// INSERT
/// ===============================================================================
template < typename T >
inline Index IndexMap< T >::insert( const T& obj ) {
    Index idx;
    if( pop_free_index( idx ) ) {
        typename std::deque< Index >::iterator it = std::lower_bound( m_index.begin(), m_index.end(), idx );
        if( it == m_index.end() ) {
            m_data.insert( m_data.end(), obj );
        } else {
            m_data.insert( ( m_data.begin() + ( it - m_index.begin() ) ), obj );
        }
        m_index.insert( it, idx );
    }
    return idx;
}

template < typename T >
inline bool IndexMap< T >::insert( const T& obj,
                                   Index&   idx ) {
    if( !pop_free_index( idx ) ) {
        return false;
    }
    typename std::deque< Index >::iterator it = std::lower_bound( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        m_data.insert( m_data.end(), obj );
    } else {
        m_data.insert( ( m_data.begin() + ( it - m_index.begin() ) ), obj );
    }
    m_index.insert( it, idx );
    return true;
}

/// ===============================================================================
/// REMOVE
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::remove( const Index& idx ) {
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    m_data.erase( m_data.begin() + ( it - m_index.begin() ) );
    m_index.erase( it );
    push_free_index( idx );
    return true;
}

template < typename T >
inline bool IndexMap< T >::remove( const uint i ) {
    if( i >= m_data.size() ) {
        return false;
    }
    push_free_index( m_index[i] );
    m_data.erase( m_data.begin() + i );
    m_index.erase( m_index.begin() + i );
    return true;
}

/// ===============================================================================
/// ACCESS
/// ===============================================================================
template < typename T >
inline T IndexMap< T >::at( const Index& idx ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    CORE_ASSERT( it != m_index.end(), "Index not found" );
    return m_data.at( it - m_index.begin() );
}

template < typename T >
inline T IndexMap< T >::at( const uint i ) const {
    CORE_ASSERT( ( i < m_data.size() ), "Index i out of bound" );
    return m_data.at( i );
}

template < typename T >
inline bool IndexMap< T >::at( const Index& idx,
                               T&           obj ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    obj = m_data.at( it - m_index.begin() );
    return true;
}

template < typename T >
inline bool IndexMap< T >::at( const uint i,
                               T&         obj ) const {
    if( i >= m_data.size() ) {
        return false;
    }
    obj = m_data.at( i );
    return true;
}

template < typename T >
inline T& IndexMap< T >::access( const Index& idx ) {
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    CORE_ASSERT( ( it != m_index.end() ), "Index not found" );
    return m_data[ it - m_index.begin()  ];
}

template < typename T >
inline T& IndexMap< T >::access( const uint i ) {
    CORE_ASSERT( ( i < m_data.size() ) , "Index i out of bound");
    return m_data[i];
}

template < typename T >
inline bool IndexMap< T >::access( const Index& idx,
                                   T&           obj ) {
    if( m_data.empty() ) {
        return false;
    }
    typename std::deque< Index >::iterator it = std::find( m_index.begin(), m_index.end(), idx );
    if( it == m_index.end() ) {
        return false;
    }
    obj = m_data[ it - m_index.begin() ];
    return true;
}

template < typename T >
inline bool IndexMap< T >::access( const uint i,
                                   T&         obj ) {
    if( i >= m_data.size() ) {
        return false;
    }
    obj = m_data[i];
    return true;
}

/// ===============================================================================
/// SIZE
/// ===============================================================================
template < typename T >
inline uint IndexMap< T >::size() const {
    return m_data.size();
}

template < typename T >
inline void IndexMap< T >::clear() {
    m_index.clear();
    m_data.clear();
    m_free.clear();
    m_free.push_back( Index( 0 ) );
}

/// ===============================================================================
/// QUERY
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::empty() const {
    return  m_data.empty();
}

template < typename T >
inline bool IndexMap< T >::full() const {
    return m_free.empty();
}

template < typename T >
inline bool IndexMap< T >::contain( const Index& idx ) const {
    typename std::deque< Index >::const_iterator it = std::find( m_index.begin(), m_index.end(), idx );
    return !( it == m_index.end() );
}

template < typename T >
inline bool IndexMap< T >::compact() const {
    return ( m_free.front() > m_data.size() );
}

template < typename T >
inline Index IndexMap< T >::index( const uint i ) const {
    if( i >= m_index.size() ) {
        return Index::INVALID_IDX();
    }
    return m_index.at( i );
}

template < typename T >
inline bool IndexMap< T >::index( const uint i, Index& idx ) const {
    if( i >= m_index.size() ) {
        return false;
    }
    idx = m_index.at( i );
    return true;
}

/// ===============================================================================
/// OPERATOR
/// ===============================================================================
template < typename T >
inline T& IndexMap< T >::operator[]( const Index& idx ) {
    return access( idx );
}

template < typename T >
inline T& IndexMap< T >::operator[]( const uint i ) {
    return access( i );
}

template < typename T >
inline Index& IndexMap< T >::operator<<( const T& obj ) {
    return insert( obj );
}

template < typename T >
inline IndexMap< T >& IndexMap< T >::operator>>( const Index& idx ) {
    remove( idx );
    return *this;
}

template < typename T >
inline IndexMap< T >& IndexMap< T >::operator>>( const uint i ) {
    remove( i );
    return *this;
}

/// ===============================================================================
/// INDEX ITERATOR
/// ===============================================================================
template <typename T>
inline typename IndexMap< T >::ConstIndexIterator IndexMap< T >::cbegin_index() const {
    return m_index.cbegin();
}

template <typename T>
inline typename IndexMap< T >::ConstIndexIterator IndexMap< T >::cend_index() const {
    return m_index.cend();
}

/// ===============================================================================
/// DATA ITERATOR
/// ===============================================================================
template <typename T>
inline typename IndexMap< T >::Iterator IndexMap< T >::begin() {
    return m_data.begin();
}

template <typename T>
inline typename IndexMap< T >::Iterator IndexMap< T >::end() {
    return m_data.end();
}

template <typename T>
inline typename IndexMap< T >::ConstIterator IndexMap< T >::cbegin() const {
    return m_data.cbegin();
}

template <typename T>
inline typename IndexMap< T >::ConstIterator IndexMap< T >::cend() const {
    return m_data.cend();
}

/// ===============================================================================
/// PUSH
/// ===============================================================================
template < typename T >
inline void IndexMap< T >::push_free_index( const Index& idx ) {
    std::deque<Index>::iterator free_it = std::lower_bound( m_free.begin(), m_free.end(), idx );
    m_free.insert( free_it, idx );
    if( m_data.empty() ) {
        m_free.clear();
        m_free.push_back( Index( 0 ) );
    }
}

/// ===============================================================================
/// POP
/// ===============================================================================
template < typename T >
inline bool IndexMap< T >::pop_free_index( Index& idx ) {
    if( m_free.empty() ) {
        idx = Index::INVALID_IDX();
        return false;
    }
    idx = m_free.front();
    m_free.pop_front();
    if( m_free.empty() ) {
        Index next = idx + 1;
        if( next.isValid() ) {
            if( uint( next.getValue() ) > m_data.size() ) {
                m_free.push_back( next );
            }
        }
    }
    return true;
}

} // namespace Core
} // namespace Ra
<|endoftext|>


<commit_before>/* Copyright (C) 2013 Slawomir Cygan <slawomir.cygan@gmail.com>
*
* 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 "dgltraceview.h"
#include "dglgui.h"

#include <QScrollBar>
#include <QStyledItemDelegate>
#include <QPainter>

class DGLTraceViewDelegate : public QStyledItemDelegate {
public:
    DGLTraceViewDelegate(QObject *parent=0) : QStyledItemDelegate (parent){}

    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const{

        if(option.state & QStyle::State_Selected){
            painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
        }

        int glErrorI = index.data(Qt::UserRole + 1).toInt();
        GLenum glError = static_cast<GLenum>(glErrorI);
        QString error;
        if (glErrorI != -1) {
            error = (glError == GL_NO_ERROR)?"GL_NO_ERROR":QString::fromStdString(GetGLEnumName(glError));
        }

        QPen backup = painter->pen();

        QRect r = option.rect.adjusted(15, 0, -160,  - option.rect.height() / 2);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignLeft, index.data(Qt::UserRole).toString());

        if (glError == GL_NO_ERROR) {
            painter->setPen(QPen(QColor("#20ff20")));
        } else {
            painter->setPen(QPen(QColor("#ff2020")));
        }

        r = QRect(option.rect.width() - 160, option.rect.y(), 150, option.rect.height() / 2);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignRight, error);

        painter->setPen(QPen(QColor("#2020ff")));
        r = option.rect.adjusted(15, option.rect.height() / 2, 0, 0);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignLeft, index.data(Qt::UserRole + 2).toString());

        painter->setPen(backup);
    }

    QSize sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const{
        return QSize(200, 40);
    }
};

DGLTraceViewList::DGLTraceViewList(QWidget* parrent):QListWidget(parrent) {
    CONNASSERT(connect(this, SIGNAL(resized()), parrent, SLOT(mayNeedNewElements())));
    CONNASSERT(connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), parrent, SLOT(mayNeedNewElements())));
    setItemDelegate(new DGLTraceViewDelegate(this));
}

uint DGLTraceViewList::getVisibleRowCount() {
    QListWidgetItem* minimumItem = itemAt(5, 5);
    QListWidgetItem* maximumItem = itemAt(5, height() - 5);
    if ( !minimumItem ) { minimumItem = item(0); }
    if ( !maximumItem ) { maximumItem = item(count() - 1); }
    return indexFromItem(maximumItem).row() - indexFromItem(minimumItem).row() + 1;
}

int DGLTraceViewList::getFirstVisibleElementIdx() {
    QListWidgetItem* minimumItem = itemAt(5, 5);
    if ( !minimumItem ) { minimumItem = item(0); }
    return indexFromItem(minimumItem).row();
}

void DGLTraceViewList::resizeEvent(QResizeEvent* /*e*/) {
    resized();
}

DGLTraceView::DGLTraceView(QWidget* parrent, DglController* controller):QDockWidget(tr("Call trace"), parrent),m_traceList(this) {
    setObjectName("DGLTraceView");

    setEnabled(false);

    setWidget(&m_traceList);
    //inbound
    CONNASSERT(connect(controller, SIGNAL(setConnected(bool)), this, SLOT(setEnabled(bool))));
    CONNASSERT(connect(controller, SIGNAL(setRunning(bool)), this, SLOT(setRunning(bool))));
    CONNASSERT(connect(controller, SIGNAL(breaked(CalledEntryPoint, uint)), this, SLOT(breaked(CalledEntryPoint, uint))));
    CONNASSERT(connect(controller, SIGNAL(gotCallTraceChunkChunk(uint, const std::vector<CalledEntryPoint>&)), this, SLOT(gotCallTraceChunkChunk(uint, const std::vector<CalledEntryPoint>&))));
    //outbound
    CONNASSERT(connect(this, SIGNAL(queryCallTrace(uint, uint)), controller, SLOT(queryCallTrace(uint, uint))));
}

void DGLTraceView::setEnabled(bool enabled) {
    m_traceList.clear();
    m_Enabled = enabled;
    m_QueryUpperBound = 0;
}

void DGLTraceView::setRunning(bool running) {
    if (running) {
        m_traceList.clear();
        m_QueryUpperBound = 0;
    }
}

void DGLTraceView::mayNeedNewElements() {
    if (m_Enabled) {
        if (m_traceList.getFirstVisibleElementIdx() < m_traceList.count() - m_QueryUpperBound - 1) {
            //we are starving of entrypoints to display, try to query new entrypoints up to this bound
            int nextUpperBound = m_QueryUpperBound + 2 * m_traceList.getVisibleRowCount();
            queryCallTrace(m_QueryUpperBound, nextUpperBound);
            m_QueryUpperBound = nextUpperBound;
        }
    }
}

void DGLTraceView::breaked(CalledEntryPoint entryp, uint traceSize) {
    m_traceList.clear();
    m_QueryUpperBound = 0;
    for (uint i = 0; i < traceSize; i++) {
        QListWidgetItem *item = new QListWidgetItem();
        item->setData(Qt::UserRole, "<unknown>");
        m_traceList.addItem(item);
    }
    QListWidgetItem *item = new QListWidgetItem();
    item->setData(Qt::UserRole, QString("BREAKED :  ") + QString::fromStdString(entryp.toString()));
    item->setData(Qt::UserRole + 1, -1); //do not display GL error
    m_traceList.addItem(item);
    m_traceList.setCurrentRow(m_traceList.count() - 1);
    m_traceList.scrollToBottom();
    m_QueryUpperBound = 0;
    mayNeedNewElements();
}

void DGLTraceView::gotCallTraceChunkChunk(uint offset, const std::vector<CalledEntryPoint>& trace) {
    for (uint i = offset; i < offset + trace.size(); i++) {
        int row = m_traceList.count() - i - 2;
        delete m_traceList.takeItem(row);
        /*
        if (m_glError != GL_NO_ERROR) {
        ret << " -> " << GetGLEnumName(m_glError);
        }
        if (m_DebugOutput.size()) {
        ret << " debug: " << m_DebugOutput;
        }*/
        std::string func = trace[trace.size() - 1 - i + offset].toString();
        gl_t error = trace[trace.size() - 1 - i + offset].getError();
        std::string debugOutput = trace[trace.size() - 1 - i + offset].getDebugOutput();

        QListWidgetItem *item = new QListWidgetItem();
        item->setData(Qt::UserRole, func.c_str());
        item->setData(Qt::UserRole + 1, error);
        if (debugOutput.length()) {
            item->setData(Qt::UserRole + 2, debugOutput.c_str());
        }

        m_traceList.insertItem(row, item);
    }
}
<commit_msg>Fix ambiguous gl_t => QVariant conversion<commit_after>/* Copyright (C) 2013 Slawomir Cygan <slawomir.cygan@gmail.com>
*
* 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 "dgltraceview.h"
#include "dglgui.h"

#include <QScrollBar>
#include <QStyledItemDelegate>
#include <QPainter>

class DGLTraceViewDelegate : public QStyledItemDelegate {
public:
    DGLTraceViewDelegate(QObject *parent=0) : QStyledItemDelegate (parent){}

    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const{

        if(option.state & QStyle::State_Selected){
            painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
        }

        int glErrorI = index.data(Qt::UserRole + 1).toInt();
        GLenum glError = static_cast<GLenum>(glErrorI);
        QString error;
        if (glErrorI != -1) {
            error = (glError == GL_NO_ERROR)?"GL_NO_ERROR":QString::fromStdString(GetGLEnumName(glError));
        }

        QPen backup = painter->pen();

        QRect r = option.rect.adjusted(15, 0, -160,  - option.rect.height() / 2);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignLeft, index.data(Qt::UserRole).toString());

        if (glError == GL_NO_ERROR) {
            painter->setPen(QPen(QColor("#20ff20")));
        } else {
            painter->setPen(QPen(QColor("#ff2020")));
        }

        r = QRect(option.rect.width() - 160, option.rect.y(), 150, option.rect.height() / 2);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignRight, error);

        painter->setPen(QPen(QColor("#2020ff")));
        r = option.rect.adjusted(15, option.rect.height() / 2, 0, 0);
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignTop|Qt::AlignLeft, index.data(Qt::UserRole + 2).toString());

        painter->setPen(backup);
    }

    QSize sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const{
        return QSize(200, 40);
    }
};

DGLTraceViewList::DGLTraceViewList(QWidget* parrent):QListWidget(parrent) {
    CONNASSERT(connect(this, SIGNAL(resized()), parrent, SLOT(mayNeedNewElements())));
    CONNASSERT(connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), parrent, SLOT(mayNeedNewElements())));
    setItemDelegate(new DGLTraceViewDelegate(this));
}

uint DGLTraceViewList::getVisibleRowCount() {
    QListWidgetItem* minimumItem = itemAt(5, 5);
    QListWidgetItem* maximumItem = itemAt(5, height() - 5);
    if ( !minimumItem ) { minimumItem = item(0); }
    if ( !maximumItem ) { maximumItem = item(count() - 1); }
    return indexFromItem(maximumItem).row() - indexFromItem(minimumItem).row() + 1;
}

int DGLTraceViewList::getFirstVisibleElementIdx() {
    QListWidgetItem* minimumItem = itemAt(5, 5);
    if ( !minimumItem ) { minimumItem = item(0); }
    return indexFromItem(minimumItem).row();
}

void DGLTraceViewList::resizeEvent(QResizeEvent* /*e*/) {
    resized();
}

DGLTraceView::DGLTraceView(QWidget* parrent, DglController* controller):QDockWidget(tr("Call trace"), parrent),m_traceList(this) {
    setObjectName("DGLTraceView");

    setEnabled(false);

    setWidget(&m_traceList);
    //inbound
    CONNASSERT(connect(controller, SIGNAL(setConnected(bool)), this, SLOT(setEnabled(bool))));
    CONNASSERT(connect(controller, SIGNAL(setRunning(bool)), this, SLOT(setRunning(bool))));
    CONNASSERT(connect(controller, SIGNAL(breaked(CalledEntryPoint, uint)), this, SLOT(breaked(CalledEntryPoint, uint))));
    CONNASSERT(connect(controller, SIGNAL(gotCallTraceChunkChunk(uint, const std::vector<CalledEntryPoint>&)), this, SLOT(gotCallTraceChunkChunk(uint, const std::vector<CalledEntryPoint>&))));
    //outbound
    CONNASSERT(connect(this, SIGNAL(queryCallTrace(uint, uint)), controller, SLOT(queryCallTrace(uint, uint))));
}

void DGLTraceView::setEnabled(bool enabled) {
    m_traceList.clear();
    m_Enabled = enabled;
    m_QueryUpperBound = 0;
}

void DGLTraceView::setRunning(bool running) {
    if (running) {
        m_traceList.clear();
        m_QueryUpperBound = 0;
    }
}

void DGLTraceView::mayNeedNewElements() {
    if (m_Enabled) {
        if (m_traceList.getFirstVisibleElementIdx() < m_traceList.count() - m_QueryUpperBound - 1) {
            //we are starving of entrypoints to display, try to query new entrypoints up to this bound
            int nextUpperBound = m_QueryUpperBound + 2 * m_traceList.getVisibleRowCount();
            queryCallTrace(m_QueryUpperBound, nextUpperBound);
            m_QueryUpperBound = nextUpperBound;
        }
    }
}

void DGLTraceView::breaked(CalledEntryPoint entryp, uint traceSize) {
    m_traceList.clear();
    m_QueryUpperBound = 0;
    for (uint i = 0; i < traceSize; i++) {
        QListWidgetItem *item = new QListWidgetItem();
        item->setData(Qt::UserRole, "<unknown>");
        m_traceList.addItem(item);
    }
    QListWidgetItem *item = new QListWidgetItem();
    item->setData(Qt::UserRole, QString("BREAKED :  ") + QString::fromStdString(entryp.toString()));
    item->setData(Qt::UserRole + 1, -1); //do not display GL error
    m_traceList.addItem(item);
    m_traceList.setCurrentRow(m_traceList.count() - 1);
    m_traceList.scrollToBottom();
    m_QueryUpperBound = 0;
    mayNeedNewElements();
}

void DGLTraceView::gotCallTraceChunkChunk(uint offset, const std::vector<CalledEntryPoint>& trace) {
    for (uint i = offset; i < offset + trace.size(); i++) {
        int row = m_traceList.count() - i - 2;
        delete m_traceList.takeItem(row);
        /*
        if (m_glError != GL_NO_ERROR) {
        ret << " -> " << GetGLEnumName(m_glError);
        }
        if (m_DebugOutput.size()) {
        ret << " debug: " << m_DebugOutput;
        }*/
        std::string func = trace[trace.size() - 1 - i + offset].toString();
        gl_t error = trace[trace.size() - 1 - i + offset].getError();
        std::string debugOutput = trace[trace.size() - 1 - i + offset].getDebugOutput();

        QListWidgetItem *item = new QListWidgetItem();
        item->setData(Qt::UserRole, func.c_str());
        item->setData(Qt::UserRole + 1, (uint)error);
        if (debugOutput.length()) {
            item->setData(Qt::UserRole + 2, debugOutput.c_str());
        }

        m_traceList.insertItem(row, item);
    }
}
<|endoftext|>