<commit_before>#include "Distribution.h"

// From:
// http://stackoverflow.com/questions/6142576/sample-from-multivariate-normal-gaussian-distribution-in-c

#include <iostream>
#include <chrono>
#include <functional>

#include <Eigen/Dense>

#include "ThreadVector.hpp"

#include "omp_util.h"

using namespace std;
using namespace Eigen;
using namespace std::chrono;

#ifdef USE_BOOST_RANDOM
#include <boost/random.hpp>
#define MERSENNE_TWISTER boost::random::mt19937
#define UNIFORM_REAL_DISTRIBUTION boost::random::uniform_real_distribution<double>
#define GAMMA_DISTRIBUTION boost::random::gamma_distribution<double>
#else
#include <random>
#define MERSENNE_TWISTER std::mt19937
#define UNIFORM_REAL_DISTRIBUTION std::uniform_real_distribution<double>
#define GAMMA_DISTRIBUTION std::gamma_distribution<double>
#endif

static smurff::thread_vector<MERSENNE_TWISTER> *bmrngs;

double smurff::randn0()
{
   return smurff::bmrandn_single_thread();
}

double smurff::randn(double)
{
   return smurff::bmrandn_single_thread();
}

void smurff::bmrandn(double* x, long n)
{
   #pragma omp parallel
   {
      UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
      auto& bmrng = bmrngs->local();

      #pragma omp for schedule(static)
      for (long i = 0; i < n; i += 2)
      {
         double x1, x2, w;
         do
         {
           x1 = unif(bmrng);
           x2 = unif(bmrng);
           w = x1 * x1 + x2 * x2;
         } while ( w >= 1.0 );

         w = std::sqrt( (-2.0 * std::log( w ) ) / w );
         x[i] = x1 * w;

         if (i + 1 < n)
         {
           x[i+1] = x2 * w;
         }
      }
   }
}

void smurff::bmrandn(MatrixXd & X)
{
   long n = X.rows() * (long)X.cols();
   smurff::bmrandn(X.data(), n);
}

double smurff::bmrandn_single_thread()
{
   //TODO: add bmrng as input
   UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
   auto& bmrng = bmrngs->local();

   double x1, x2, w;
   do
   {
      x1 = unif(bmrng);
      x2 = unif(bmrng);
      w = x1 * x1 + x2 * x2;
   } while ( w >= 1.0 );

   w = std::sqrt( (-2.0 * std::log( w ) ) / w );
   return x1 * w;
}

// to be called within OpenMP parallel loop (also from serial code is fine)
void smurff::bmrandn_single_thread(double* x, long n)
{
   UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
   auto& bmrng = bmrngs->local();

   for (long i = 0; i < n; i += 2)
   {
      double x1, x2, w;

      do
      {
         x1 = unif(bmrng);
         x2 = unif(bmrng);
         w = x1 * x1 + x2 * x2;
      } while ( w >= 1.0 );

      w = std::sqrt( (-2.0 * std::log( w ) ) / w );
      x[i] = x1 * w;

      if (i + 1 < n)
      {
         x[i+1] = x2 * w;
      }
   }
}

void smurff::bmrandn_single_thread(Eigen::VectorXd & x)
{
   smurff::bmrandn_single_thread(x.data(), x.size());
}

void smurff::bmrandn_single_thread(MatrixXd & X)
{
   long n = X.rows() * (long)X.cols();
   smurff::bmrandn_single_thread(X.data(), n);
}

void smurff::init_bmrng()
{
   auto ms = (duration_cast< milliseconds >(system_clock::now().time_since_epoch())).count();
   smurff::init_bmrng(ms);
}

void smurff::init_bmrng(int seed)
{
    std::vector<MERSENNE_TWISTER> v;
    for (int i = 0; i < threads::get_max_threads(); i++)
    {
        v.push_back(MERSENNE_TWISTER(seed + i * 1999));
    }
    bmrngs = new smurff::thread_vector<MERSENNE_TWISTER>();
    bmrngs->init(v);
}

double smurff::rand_unif()
{
   UNIFORM_REAL_DISTRIBUTION unif(0.0, 1.0);
   auto& bmrng = bmrngs->local();
   return unif(bmrng);
}

double smurff::rand_unif(double low, double high)
{
   UNIFORM_REAL_DISTRIBUTION unif(low, high);
   auto& bmrng = bmrngs->local();
   return unif(bmrng);
}

// returns random number according to Gamma distribution
// with the given shape (k) and scale (theta). See wiki.
double smurff::rgamma(double shape, double scale)
{
   GAMMA_DISTRIBUTION gamma(shape, scale);
   return gamma(bmrngs->local());
}

auto smurff::nrandn(int n) -> decltype(VectorXd::NullaryExpr(n, std::cref(randn)))
{
   return VectorXd::NullaryExpr(n, std::cref(randn));
}

auto smurff::nrandn(int n, int m) -> decltype(ArrayXXd::NullaryExpr(n, m, std::ptr_fun(randn)))
{
   return ArrayXXd::NullaryExpr(n, m, std::ptr_fun(randn));
}

MatrixXd WishartUnit(int m, int df)
{
   MatrixXd c(m,m);
   c.setZero();
   auto& rng = bmrngs->local();

   for ( int i = 0; i < m; i++ )
   {
      GAMMA_DISTRIBUTION gam(0.5*(df - i));
      c(i,i) = std::sqrt(2.0 * gam(rng));
      VectorXd r = smurff::nrandn(m-i-1);
      c.block(i,i+1,1,m-i-1) = r.transpose();
   }

   MatrixXd ret = c.transpose() * c;

   #ifdef TEST_MVNORMAL
   cout << "WISHART UNIT {\n" << endl;
   cout << "  m:\n" << m << endl;
   cout << "  df:\n" << df << endl;
   cout << "  ret;\n" << ret << endl;
   cout << "  c:\n" << c << endl;
   cout << "}\n" << ret << endl;
   #endif

   return ret;
}

MatrixXd Wishart(const MatrixXd &sigma, const int df)
{
   //  Get R, the upper triangular Cholesky factor of SIGMA.
   auto chol = sigma.llt();
   MatrixXd r = chol.matrixL();

   //  Get AU, a sample from the unit Wishart distribution.
   MatrixXd au = WishartUnit(sigma.cols(), df);

   //  Construct the matrix A = R' * AU * R.
   MatrixXd a = r * au * chol.matrixU();

   #ifdef TEST_MVNORMAL
   cout << "WISHART {\n" << endl;
   cout << "  sigma:\n" << sigma << endl;
   cout << "  r:\n" << r << endl;
   cout << "  au:\n" << au << endl;
   cout << "  df:\n" << df << endl;
   cout << "  a:\n" << a << endl;
   cout << "}\n" << endl;
   #endif

  return a;
}

// from julia package Distributions: conjugates/normalwishart.jl
std::pair<VectorXd, MatrixXd> smurff::NormalWishart(const VectorXd & mu, double kappa, const MatrixXd & T, double nu)
{
   MatrixXd Lam = Wishart(T, nu);
   MatrixXd mu_o = smurff::MvNormal_prec(Lam * kappa, mu);

   #ifdef TEST_MVNORMAL
   cout << "NORMAL WISHART {\n" << endl;
   cout << "  mu:\n" << mu << endl;
   cout << "  kappa:\n" << kappa << endl;
   cout << "  T:\n" << T << endl;
   cout << "  nu:\n" << nu << endl;
   cout << "  mu_o\n" << mu_o << endl;
   cout << "  Lam\n" << Lam << endl;
   cout << "}\n" << endl;
   #endif

   return std::make_pair(mu_o , Lam);
}

std::pair<VectorXd, MatrixXd> smurff::CondNormalWishart(const int N, const MatrixXd &NS, const VectorXd &NU, const VectorXd &mu, const double kappa, const MatrixXd &T, const int nu)
{
   int nu_c = nu + N;

   double kappa_c = kappa + N;
   auto mu_c = (kappa * mu + NU) / (kappa + N);
   auto X    = (T + NS + kappa * mu * mu.adjoint() - kappa_c * mu_c * mu_c.adjoint());
   Eigen::MatrixXd T_c = X.inverse();

   return NormalWishart(mu_c, kappa_c, T_c, nu_c);
}

std::pair<VectorXd, MatrixXd> smurff::CondNormalWishart(const MatrixXd &U, const VectorXd &mu, const double kappa, const MatrixXd &T, const int nu)
{
   auto N = U.cols();
   auto NS = U * U.adjoint();
   auto NU = U.rowwise().sum();
   return CondNormalWishart(N, NS, NU, mu, kappa, T, nu);
}

// Normal(0, Lambda^-1) for nn columns
MatrixXd smurff::MvNormal_prec(const MatrixXd & Lambda, int ncols)
{
   int nrows = Lambda.rows(); // Dimensionality (rows)
   LLT<MatrixXd> chol(Lambda);

   MatrixXd r(nrows, ncols);
   smurff::bmrandn(r);

   return chol.matrixU().solve(r);
}

MatrixXd smurff::MvNormal_prec(const MatrixXd & Lambda, const VectorXd & mean, int nn)
{
   MatrixXd r = MvNormal_prec(Lambda, nn);
   return r.colwise() + mean;
}

// Draw nn samples from a size-dimensional normal distribution
// with a specified mean and covariance
MatrixXd smurff::MvNormal(const MatrixXd covar, const VectorXd mean, int nn)
{
   int size = mean.rows(); // Dimensionality (rows)
   MatrixXd normTransform(size,size);

   LLT<MatrixXd> cholSolver(covar);
   normTransform = cholSolver.matrixL();

   auto normSamples = MatrixXd::NullaryExpr(size, nn, std::cref(randn));
   MatrixXd samples = (normTransform * normSamples).colwise() + mean;

   return samples;
}
<commit_msg>FIX: change order of includes to make GCC 4.8, Boost 1.54 and LAPACKE play nice together<commit_after>
// From:
// http://stackoverflow.com/questions/6142576/sample-from-multivariate-normal-gaussian-distribution-in-c

#include <iostream>
#include <chrono>
#include <functional>

#include "ThreadVector.hpp"

#include "omp_util.h"

#ifdef USE_BOOST_RANDOM
#include <boost/random.hpp>
#define MERSENNE_TWISTER boost::random::mt19937
#define UNIFORM_REAL_DISTRIBUTION boost::random::uniform_real_distribution<double>
#define GAMMA_DISTRIBUTION boost::random::gamma_distribution<double>
#else
#include <random>
#define MERSENNE_TWISTER std::mt19937
#define UNIFORM_REAL_DISTRIBUTION std::uniform_real_distribution<double>
#define GAMMA_DISTRIBUTION std::gamma_distribution<double>
#endif

#include <Eigen/Dense>

#include "Distribution.h"

using namespace Eigen;

static smurff::thread_vector<MERSENNE_TWISTER> *bmrngs;

double smurff::randn0()
{
   return smurff::bmrandn_single_thread();
}

double smurff::randn(double)
{
   return smurff::bmrandn_single_thread();
}

void smurff::bmrandn(double* x, long n)
{
   #pragma omp parallel
   {
      UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
      auto& bmrng = bmrngs->local();

      #pragma omp for schedule(static)
      for (long i = 0; i < n; i += 2)
      {
         double x1, x2, w;
         do
         {
           x1 = unif(bmrng);
           x2 = unif(bmrng);
           w = x1 * x1 + x2 * x2;
         } while ( w >= 1.0 );

         w = std::sqrt( (-2.0 * std::log( w ) ) / w );
         x[i] = x1 * w;

         if (i + 1 < n)
         {
           x[i+1] = x2 * w;
         }
      }
   }
}

void smurff::bmrandn(MatrixXd & X)
{
   long n = X.rows() * (long)X.cols();
   smurff::bmrandn(X.data(), n);
}

double smurff::bmrandn_single_thread()
{
   //TODO: add bmrng as input
   UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
   auto& bmrng = bmrngs->local();

   double x1, x2, w;
   do
   {
      x1 = unif(bmrng);
      x2 = unif(bmrng);
      w = x1 * x1 + x2 * x2;
   } while ( w >= 1.0 );

   w = std::sqrt( (-2.0 * std::log( w ) ) / w );
   return x1 * w;
}

// to be called within OpenMP parallel loop (also from serial code is fine)
void smurff::bmrandn_single_thread(double* x, long n)
{
   UNIFORM_REAL_DISTRIBUTION unif(-1.0, 1.0);
   auto& bmrng = bmrngs->local();

   for (long i = 0; i < n; i += 2)
   {
      double x1, x2, w;

      do
      {
         x1 = unif(bmrng);
         x2 = unif(bmrng);
         w = x1 * x1 + x2 * x2;
      } while ( w >= 1.0 );

      w = std::sqrt( (-2.0 * std::log( w ) ) / w );
      x[i] = x1 * w;

      if (i + 1 < n)
      {
         x[i+1] = x2 * w;
      }
   }
}

void smurff::bmrandn_single_thread(Eigen::VectorXd & x)
{
   smurff::bmrandn_single_thread(x.data(), x.size());
}

void smurff::bmrandn_single_thread(MatrixXd & X)
{
   long n = X.rows() * (long)X.cols();
   smurff::bmrandn_single_thread(X.data(), n);
}

void smurff::init_bmrng()
{
   using namespace std::chrono;
   auto ms = (duration_cast< milliseconds >(system_clock::now().time_since_epoch())).count();
   smurff::init_bmrng(ms);
}

void smurff::init_bmrng(int seed)
{
    std::vector<MERSENNE_TWISTER> v;
    for (int i = 0; i < threads::get_max_threads(); i++)
    {
        v.push_back(MERSENNE_TWISTER(seed + i * 1999));
    }
    bmrngs = new smurff::thread_vector<MERSENNE_TWISTER>();
    bmrngs->init(v);
}

double smurff::rand_unif()
{
   UNIFORM_REAL_DISTRIBUTION unif(0.0, 1.0);
   auto& bmrng = bmrngs->local();
   return unif(bmrng);
}

double smurff::rand_unif(double low, double high)
{
   UNIFORM_REAL_DISTRIBUTION unif(low, high);
   auto& bmrng = bmrngs->local();
   return unif(bmrng);
}

// returns random number according to Gamma distribution
// with the given shape (k) and scale (theta). See wiki.
double smurff::rgamma(double shape, double scale)
{
   GAMMA_DISTRIBUTION gamma(shape, scale);
   return gamma(bmrngs->local());
}

auto smurff::nrandn(int n) -> decltype(VectorXd::NullaryExpr(n, std::cref(randn)))
{
   return VectorXd::NullaryExpr(n, std::cref(randn));
}

auto smurff::nrandn(int n, int m) -> decltype(ArrayXXd::NullaryExpr(n, m, std::ptr_fun(randn)))
{
   return ArrayXXd::NullaryExpr(n, m, std::ptr_fun(randn));
}

MatrixXd WishartUnit(int m, int df)
{
   MatrixXd c(m,m);
   c.setZero();
   auto& rng = bmrngs->local();

   for ( int i = 0; i < m; i++ )
   {
      GAMMA_DISTRIBUTION gam(0.5*(df - i));
      c(i,i) = std::sqrt(2.0 * gam(rng));
      VectorXd r = smurff::nrandn(m-i-1);
      c.block(i,i+1,1,m-i-1) = r.transpose();
   }

   MatrixXd ret = c.transpose() * c;

   #ifdef TEST_MVNORMAL
   cout << "WISHART UNIT {\n" << endl;
   cout << "  m:\n" << m << endl;
   cout << "  df:\n" << df << endl;
   cout << "  ret;\n" << ret << endl;
   cout << "  c:\n" << c << endl;
   cout << "}\n" << ret << endl;
   #endif

   return ret;
}

MatrixXd Wishart(const MatrixXd &sigma, const int df)
{
   //  Get R, the upper triangular Cholesky factor of SIGMA.
   auto chol = sigma.llt();
   MatrixXd r = chol.matrixL();

   //  Get AU, a sample from the unit Wishart distribution.
   MatrixXd au = WishartUnit(sigma.cols(), df);

   //  Construct the matrix A = R' * AU * R.
   MatrixXd a = r * au * chol.matrixU();

   #ifdef TEST_MVNORMAL
   cout << "WISHART {\n" << endl;
   cout << "  sigma:\n" << sigma << endl;
   cout << "  r:\n" << r << endl;
   cout << "  au:\n" << au << endl;
   cout << "  df:\n" << df << endl;
   cout << "  a:\n" << a << endl;
   cout << "}\n" << endl;
   #endif

  return a;
}

// from julia package Distributions: conjugates/normalwishart.jl
std::pair<VectorXd, MatrixXd> smurff::NormalWishart(const VectorXd & mu, double kappa, const MatrixXd & T, double nu)
{
   MatrixXd Lam = Wishart(T, nu);
   MatrixXd mu_o = smurff::MvNormal_prec(Lam * kappa, mu);

   #ifdef TEST_MVNORMAL
   cout << "NORMAL WISHART {\n" << endl;
   cout << "  mu:\n" << mu << endl;
   cout << "  kappa:\n" << kappa << endl;
   cout << "  T:\n" << T << endl;
   cout << "  nu:\n" << nu << endl;
   cout << "  mu_o\n" << mu_o << endl;
   cout << "  Lam\n" << Lam << endl;
   cout << "}\n" << endl;
   #endif

   return std::make_pair(mu_o , Lam);
}

std::pair<VectorXd, MatrixXd> smurff::CondNormalWishart(const int N, const MatrixXd &NS, const VectorXd &NU, const VectorXd &mu, const double kappa, const MatrixXd &T, const int nu)
{
   int nu_c = nu + N;

   double kappa_c = kappa + N;
   auto mu_c = (kappa * mu + NU) / (kappa + N);
   auto X    = (T + NS + kappa * mu * mu.adjoint() - kappa_c * mu_c * mu_c.adjoint());
   Eigen::MatrixXd T_c = X.inverse();

   return NormalWishart(mu_c, kappa_c, T_c, nu_c);
}

std::pair<VectorXd, MatrixXd> smurff::CondNormalWishart(const MatrixXd &U, const VectorXd &mu, const double kappa, const MatrixXd &T, const int nu)
{
   auto N = U.cols();
   auto NS = U * U.adjoint();
   auto NU = U.rowwise().sum();
   return CondNormalWishart(N, NS, NU, mu, kappa, T, nu);
}

// Normal(0, Lambda^-1) for nn columns
MatrixXd smurff::MvNormal_prec(const MatrixXd & Lambda, int ncols)
{
   int nrows = Lambda.rows(); // Dimensionality (rows)
   LLT<MatrixXd> chol(Lambda);

   MatrixXd r(nrows, ncols);
   smurff::bmrandn(r);

   return chol.matrixU().solve(r);
}

MatrixXd smurff::MvNormal_prec(const MatrixXd & Lambda, const VectorXd & mean, int nn)
{
   MatrixXd r = MvNormal_prec(Lambda, nn);
   return r.colwise() + mean;
}

// Draw nn samples from a size-dimensional normal distribution
// with a specified mean and covariance
MatrixXd smurff::MvNormal(const MatrixXd covar, const VectorXd mean, int nn)
{
   int size = mean.rows(); // Dimensionality (rows)
   MatrixXd normTransform(size,size);

   LLT<MatrixXd> cholSolver(covar);
   normTransform = cholSolver.matrixL();

   auto normSamples = MatrixXd::NullaryExpr(size, nn, std::cref(randn));
   MatrixXd samples = (normTransform * normSamples).colwise() + mean;

   return samples;
}
<|endoftext|>


<commit_before>#include <tansa/trajectory.h>

double LightTrajectory::evaluate(double t) {

	// Calculate percent intensities between start and end times
	double totalIntensityChange = endIntensity - startIntensity;
	double totalTimeChange = endTime - startTime;
	double requestedTimeChange = t - startTime;
	assert(requestedTimeChange >= 0);
	assert(totalTimeChange > 0);

	// Calculate the intensity percent from start time to passed in time
	double percentTotalChange = requestedTimeChange / totalTimeChange;
	double requestedIntensityChange = percentTotalChange * totalIntensityChange;

	// Return the whole intensity at this time
	return startIntensity + totalIntensityChange;
}<commit_msg>Light fading should work now<commit_after>#include <tansa/trajectory.h>

double LightTrajectory::evaluate(double t) {

	// Calculate percent intensities between start and end times
	double totalTimeChange = endTime - startTime;
	double requestedTimeChange = t - startTime;
	assert(requestedTimeChange >= 0);
	assert(totalTimeChange > 0);

	// Calculate the intensity percent from start time to passed in time
	double percentTotalChange = requestedTimeChange / totalTimeChange;
	double requestedIntensityChange = percentTotalChange * (endIntensity - startIntensity);

	// Return the whole intensity at this time
	return startIntensity + requestedIntensityChange;
}<|endoftext|>


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

#include "chrome/browser/component_updater/flash_component_installer.h"

#include "base/bind.h"
#include "base/base_paths.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/common/chrome_paths.h"
#include "content/browser/browser_thread.h"
#include "content/browser/plugin_service.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/webplugininfo.h"

namespace {

// CRX hash. The extension id is: immdilkhigodmjbnngapbehchmihabbg.
const uint8 sha2_hash[] = {0x5c, 0x40, 0x30, 0xe3, 0x5d, 0x83, 0x2b, 0xd9,
                           0x7b, 0xa3, 0x69, 0xae, 0xbc, 0x7c, 0x5e, 0x5a,
                           0xef, 0xa5, 0xdf, 0x64, 0x6a, 0xe1, 0xc6, 0xdf,
                           0x23, 0x47, 0x30, 0x2a, 0xde, 0xae, 0x9d, 0xf7};

// File name of the internal Flash plugin on different platforms.
const FilePath::CharType kFlashPluginFileName[] =
#if defined(OS_MACOSX)
    FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
#elif defined(OS_WIN)
    FILE_PATH_LITERAL("gcswf32.dll");
#else  // OS_LINUX, etc.
    FILE_PATH_LITERAL("libgcflashplayer.so");
#endif

const char kNPAPIFlashManifestName[] = "NPAPIFlash";

// The NPAPI flash plugins are in a directory with this name.
const FilePath::CharType kNPAPIFlashBaseDirectory[] =
    FILE_PATH_LITERAL("NPAPIFlash");

// The base directory on windows looks like:
// <profile>\AppData\Local\Google\Chrome\User Data\NPAPIFlash\.
FilePath GetNPAPIFlashBaseDirectory() {
  FilePath result;
  PathService::Get(chrome::DIR_USER_DATA, &result);
  return result.Append(kNPAPIFlashBaseDirectory);
}

std::string NormalizeVersion(const string16& version) {
  std::string ascii_ver = UTF16ToASCII(version);
  std::replace(ascii_ver.begin(), ascii_ver.end(), ',', '.');
  return ascii_ver;
}

}  // namespace

class NPAPIFlashComponentInstaller : public ComponentInstaller {
 public:
  explicit NPAPIFlashComponentInstaller(const Version& version);

  virtual ~NPAPIFlashComponentInstaller() {}

  virtual void OnUpdateError(int error) OVERRIDE;

  virtual bool Install(base::DictionaryValue* manifest,
                       const FilePath& unpack_path) OVERRIDE;

 private:
  Version current_version_;
};

NPAPIFlashComponentInstaller::NPAPIFlashComponentInstaller(
    const Version& version) : current_version_(version) {
  DCHECK(version.IsValid());
}

void NPAPIFlashComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "NPAPI flash update error: " << error;
}

bool NPAPIFlashComponentInstaller::Install(base::DictionaryValue* manifest,
                                           const FilePath& unpack_path) {
  std::string name;
  manifest->GetStringASCII("name", &name);
  if (name != kNPAPIFlashManifestName)
    return false;
  std::string proposed_version;
  manifest->GetStringASCII("version", &proposed_version);
  Version version(proposed_version.c_str());
  if (!version.IsValid())
    return false;
  if (current_version_.CompareTo(version) >= 0)
    return false;
  if (!file_util::PathExists(unpack_path.Append(kFlashPluginFileName)))
    return false;
  // Passed the basic tests. Time to install it.
  if (!file_util::Move(unpack_path, GetNPAPIFlashBaseDirectory()))
    return false;
  // Installation is done. Now tell the rest of chrome.
  current_version_ = version;
  webkit::npapi::PluginList::Singleton()->RefreshPlugins();
  return true;
}

void FinishFlashUpdateRegistration(ComponentUpdateService* cus,
                                   const webkit::WebPluginInfo& info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // todo(cpu): Add PluginPrefs code here to determine if what we update
  // is actually going to be used.

  Version version(NormalizeVersion(info.version));
  if (!version.IsValid()) {
    NOTREACHED();
    return;
  }

  CrxComponent flash;
  flash.name = "npapi_flash";
  flash.installer = new NPAPIFlashComponentInstaller(version);
  flash.version = version;
  flash.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
  if (cus->RegisterComponent(flash) != ComponentUpdateService::kOk) {
    NOTREACHED() << "Flash component registration fail";
  }
}

// The code in this function is only concerned about learning what flash plugin
// chrome is using and what is its version. This will determine if we register
// for component update or not. Read the comments on RegisterNPAPIFlashComponent
// for more background.
void StartFlashUpdateRegistration(ComponentUpdateService* cus,
                                  const std::vector<webkit::WebPluginInfo>&) {
  FilePath builtin_plugin_path;
  if (!PathService::Get(chrome::FILE_FLASH_PLUGIN, &builtin_plugin_path))
    return;

  FilePath updated_plugin_path =
      GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);

  PluginService* plugins = PluginService::GetInstance();
  webkit::WebPluginInfo plugin_info;

  if (plugins->GetPluginInfoByPath(updated_plugin_path, &plugin_info)) {
    // The updated plugin is newer. Since flash is used by pretty much every
    // webpage out there, odds are it is going to be loaded, which means
    // receiving an update is pointless since we can't swap them. You might
    // find this pessimistic. The way we get out of this situation is when
    // we update the whole product.
    DLOG(INFO) << "updated plugin overriding built-in flash";
    return;
  } else if (plugins->GetPluginInfoByPath(builtin_plugin_path, &plugin_info)) {
    // The built plugin is newer. Delete the updated plugin and register for
    // updates. This should be the normal case.
    file_util::Delete(GetNPAPIFlashBaseDirectory(), true);
  } else {
    // Strange installation. Log and abort registration.
    DLOG(WARNING) << "Strange flash npapi configuration";
    return;
  }

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&FinishFlashUpdateRegistration, cus, plugin_info));
}

// Here is the general plan of action: we are going to update flash and we have
// the following cases:
// 1- The active flash is not the built-in flash (user override).
// 2- The active flash is the built-in flash.
// 3- The active flash is the one from the component updater.
// In case 1 we do nothing. In cases 2 and 3 we need to compare versions
// and if the higher version is:
// case 2: remove the component update flash, register with component updater.
// case 3: register with component updater.
//
// In practice, it's complicated. First off, to learn the version of the plugin
// we have to do file IO, which PluginList will do for us but we have to be
// careful not to trigger this on the UI thread: AddExtraPluginPath and
// RefreshPlugins don't trigger file IO, but most of the others calls do.
//
// Secondly, we can do this in a delayed task. Right now we just need to
// register the right plugin before chrome loads the first flash-ladden page.
//
// Interestingly, if PluginList finds two plugins with the same filename and
// same mimetypes, it will only keep the one with the higher version. This is
// our case in the sense that a component updated flash is very much the same
// thing as built-in flash: sometimes newer or sometimes older. That is why
// you don't see version comparison in this code.
//
// So to kick off the magic we add the updated flash path here, even though
// there might not be a flash player in that location. If there is and it is
// newer, it will take its place then we fire StartFlashUpdateRegistration
// on the IO thread to learn which one won. Since we do it in a delayed task
// probably somebody (unknowingly) will pay for the file IO, so usually get
// the information for free.
void RegisterNPAPIFlashComponent(ComponentUpdateService* cus) {
#if defined(OS_WIN)
  webkit::npapi::PluginList* plugins = webkit::npapi::PluginList::Singleton();
  FilePath path = GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);
  plugins->AddExtraPluginPath(path);
  plugins->RefreshPlugins();

  // Post the task to the FILE thread because IO may be done once the plugins
  // are loaded.
  BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&PluginService::GetPlugins,
                 base::Unretained(PluginService::GetInstance()),
                 base::Bind(&StartFlashUpdateRegistration, cus)),
      8000);
#endif
}
<commit_msg>Enable flash npapi component updater for all platforms except chromeOs<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/component_updater/flash_component_installer.h"

#include "base/bind.h"
#include "base/base_paths.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/common/chrome_paths.h"
#include "content/browser/browser_thread.h"
#include "content/browser/plugin_service.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/webplugininfo.h"

namespace {

// CRX hash. The extension id is: immdilkhigodmjbnngapbehchmihabbg.
const uint8 sha2_hash[] = {0x8c, 0xc3, 0x8b, 0xa7, 0x86, 0xe3, 0xc9, 0x1d,
                           0xd6, 0x0f, 0x14, 0x72, 0x7c, 0x87, 0x01, 0x16,
                           0xe2, 0x00, 0x6c, 0x98, 0xbc, 0xfb, 0x14, 0x1b,
                           0x5c, 0xcd, 0xff, 0x3d, 0xa3, 0x2e, 0x2c, 0x49};

// File name of the internal Flash plugin on different platforms.
const FilePath::CharType kFlashPluginFileName[] =
#if defined(OS_MACOSX)
    FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
#elif defined(OS_WIN)
    FILE_PATH_LITERAL("gcswf32.dll");
#else  // OS_LINUX, etc.
    FILE_PATH_LITERAL("libgcflashplayer.so");
#endif

const char kNPAPIFlashManifestName[] = "NPAPIFlash";

// The NPAPI flash plugins are in a directory with this name.
const FilePath::CharType kNPAPIFlashBaseDirectory[] =
    FILE_PATH_LITERAL("NPAPIFlash");

// The base directory on windows looks like:
// <profile>\AppData\Local\Google\Chrome\User Data\NPAPIFlash\.
FilePath GetNPAPIFlashBaseDirectory() {
  FilePath result;
  PathService::Get(chrome::DIR_USER_DATA, &result);
  return result.Append(kNPAPIFlashBaseDirectory);
}

std::string NormalizeVersion(const string16& version) {
  std::string ascii_ver = UTF16ToASCII(version);
  std::replace(ascii_ver.begin(), ascii_ver.end(), ',', '.');
  return ascii_ver;
}

}  // namespace

class NPAPIFlashComponentInstaller : public ComponentInstaller {
 public:
  explicit NPAPIFlashComponentInstaller(const Version& version);

  virtual ~NPAPIFlashComponentInstaller() {}

  virtual void OnUpdateError(int error) OVERRIDE;

  virtual bool Install(base::DictionaryValue* manifest,
                       const FilePath& unpack_path) OVERRIDE;

 private:
  Version current_version_;
};

NPAPIFlashComponentInstaller::NPAPIFlashComponentInstaller(
    const Version& version) : current_version_(version) {
  DCHECK(version.IsValid());
}

void NPAPIFlashComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "NPAPI flash update error: " << error;
}

bool NPAPIFlashComponentInstaller::Install(base::DictionaryValue* manifest,
                                           const FilePath& unpack_path) {
  std::string name;
  manifest->GetStringASCII("name", &name);
  if (name != kNPAPIFlashManifestName)
    return false;
  std::string proposed_version;
  manifest->GetStringASCII("version", &proposed_version);
  Version version(proposed_version.c_str());
  if (!version.IsValid())
    return false;
  if (current_version_.CompareTo(version) >= 0)
    return false;
  if (!file_util::PathExists(unpack_path.Append(kFlashPluginFileName)))
    return false;
  // Passed the basic tests. Time to install it.
  if (!file_util::Move(unpack_path, GetNPAPIFlashBaseDirectory()))
    return false;
  // Installation is done. Now tell the rest of chrome.
  current_version_ = version;
  webkit::npapi::PluginList::Singleton()->RefreshPlugins();
  return true;
}

void FinishFlashUpdateRegistration(ComponentUpdateService* cus,
                                   const webkit::WebPluginInfo& info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // todo(cpu): Add PluginPrefs code here to determine if what we update
  // is actually going to be used.

  Version version(NormalizeVersion(info.version));
  if (!version.IsValid()) {
    NOTREACHED();
    return;
  }

  CrxComponent flash;
  flash.name = "npapi_flash";
  flash.installer = new NPAPIFlashComponentInstaller(version);
  flash.version = version;
  flash.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
  if (cus->RegisterComponent(flash) != ComponentUpdateService::kOk) {
    NOTREACHED() << "Flash component registration fail";
  }
}

// The code in this function is only concerned about learning what flash plugin
// chrome is using and what is its version. This will determine if we register
// for component update or not. Read the comments on RegisterNPAPIFlashComponent
// for more background.
void StartFlashUpdateRegistration(ComponentUpdateService* cus,
                                  const std::vector<webkit::WebPluginInfo>&) {
  FilePath builtin_plugin_path;
  if (!PathService::Get(chrome::FILE_FLASH_PLUGIN, &builtin_plugin_path))
    return;

  FilePath updated_plugin_path =
      GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);

  PluginService* plugins = PluginService::GetInstance();
  webkit::WebPluginInfo plugin_info;

  if (plugins->GetPluginInfoByPath(updated_plugin_path, &plugin_info)) {
    // The updated plugin is newer. Since flash is used by pretty much every
    // webpage out there, odds are it is going to be loaded, which means
    // receiving an update is pointless since we can't swap them. You might
    // find this pessimistic. The way we get out of this situation is when
    // we update the whole product.
    DLOG(INFO) << "updated plugin overriding built-in flash";
    return;
  } else if (plugins->GetPluginInfoByPath(builtin_plugin_path, &plugin_info)) {
    // The built plugin is newer. Delete the updated plugin and register for
    // updates. This should be the normal case.
    file_util::Delete(GetNPAPIFlashBaseDirectory(), true);
  } else {
    // Strange installation. Log and abort registration.
    DLOG(WARNING) << "Strange flash npapi configuration";
    return;
  }

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&FinishFlashUpdateRegistration, cus, plugin_info));
}

// Here is the general plan of action: we are going to update flash and we have
// the following cases:
// 1- The active flash is not the built-in flash (user override).
// 2- The active flash is the built-in flash.
// 3- The active flash is the one from the component updater.
// In case 1 we do nothing. In cases 2 and 3 we need to compare versions
// and if the higher version is:
// case 2: remove the component update flash, register with component updater.
// case 3: register with component updater.
//
// In practice, it's complicated. First off, to learn the version of the plugin
// we have to do file IO, which PluginList will do for us but we have to be
// careful not to trigger this on the UI thread: AddExtraPluginPath and
// RefreshPlugins don't trigger file IO, but most of the others calls do.
//
// Secondly, we can do this in a delayed task. Right now we just need to
// register the right plugin before chrome loads the first flash-ladden page.
//
// Interestingly, if PluginList finds two plugins with the same filename and
// same mimetypes, it will only keep the one with the higher version. This is
// our case in the sense that a component updated flash is very much the same
// thing as built-in flash: sometimes newer or sometimes older. That is why
// you don't see version comparison in this code.
//
// So to kick off the magic we add the updated flash path here, even though
// there might not be a flash player in that location. If there is and it is
// newer, it will take its place then we fire StartFlashUpdateRegistration
// on the IO thread to learn which one won. Since we do it in a delayed task
// probably somebody (unknowingly) will pay for the file IO, so usually get
// the information for free.
void RegisterNPAPIFlashComponent(ComponentUpdateService* cus) {
#if !defined(OS_CHROMEOS)
  webkit::npapi::PluginList* plugins = webkit::npapi::PluginList::Singleton();
  FilePath path = GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);
  plugins->AddExtraPluginPath(path);
  plugins->RefreshPlugins();

  // Post the task to the FILE thread because IO may be done once the plugins
  // are loaded.
  BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&PluginService::GetPlugins,
                 base::Unretained(PluginService::GetInstance()),
                 base::Bind(&StartFlashUpdateRegistration, cus)),
      8000);
#endif
}
<|endoftext|>


<commit_before><commit_msg>NProjectを使うようにした<commit_after><|endoftext|>


<commit_before>#ifndef TYPES_H
#define TYPES_H
#include<stack>
#include<set>
#include<vector>
#include"heaps.hpp"
#include"hashes.hpp"
#include"variables.hpp"
#include"executors.hpp"

class Semispace;
void* operator new(size_t, Semispace&);
void operator delete(void*, Semispace&);

class ToPointerLock;

class Generic {
private:
	Generic* to_pointer;
protected:
	Generic(void) : to_pointer(NULL) {};
	Generic(Generic const&) : to_pointer(NULL) {};
	virtual boost::shared_ptr<Atom> type_atom(void) const =0;
public:
	friend class Semispace;
	friend class ToPointerLock;

	/*hash should return pretty much just any
	size_t, provided that an unmutated copy of
	that object will have the same hash().
	There is NO NEED TO PROPERLY DISTRIBUTE BITS,
	and it would probably be better not to: the
	table lookup function will use several int-
	to-int hashing functions for the bloom
	filter.
	*/
	virtual size_t hash(void) const =0;
	virtual Generic* clone(Semispace&) const =0;
	/* clone should always have the following code:
	virtual Type* clone(Semispace& sp) const{
		return new(sp) Type(*this);
	}
	*/

	/*gets addresses of references to other objects*/
	virtual void get_refs(std::stack<Generic**>&){};

	/*comparisons*/
	virtual bool is(Generic const* gp) const{return gp == this;}
	virtual bool iso(Generic const* gp) const{return is(gp);}

	virtual size_t get_size(void) const =0;
	/*get_size should always have the following code:
	virtual size_t get_size(void) const {
		return sizeof(Type);
	}
	*/

	virtual Generic* type(Process&) const;
	virtual Generic* rep(void) {return this;};

	/*symbols should change this to check that it's nil*/
	virtual bool isnil(void) const {return 0;};
	bool istrue(void) const {return !isnil();};

	virtual void probe(size_t indent) =0;//for debugging

	virtual ~Generic(){};

	size_t total_size(ToPointerLock&, std::stack<Generic**>&);
};

inline bool is(Generic const* a, Generic const* b){ return a->is(b);}
inline bool iso(Generic const* a, Generic const* b){ return a->iso(b);}

/*RAII class to handle the to-pointers
This is used to protect the to-pointers in case of
an exception.  The invariant is, to-pointers are
NULL during normal operation.  If to-pointers must
be used, access to them should be via
ToPointerLock's, so that the to-pointers are reset
to NULL once the non-normal operation (GC,
tracing) are complete.  When the operation
determines that the to-pointers can be left used
(i.e. after a GC run) then it can call the good()
member function so that it won't bother resetting
the to-pointers.
*/
class ToPointerLock{
private:
	std::set<Generic*> enset;
public:
	void pointto(Generic* from, Generic* to){
		enset.insert(from);
		from->to_pointer = to;
	}
	Generic* to(Generic* from){
		return from->to_pointer;
	}
	/*used to ignore the to-pointers in a successful
	copy-and-sweep GC cycle
	*/
	void good(void){
		enset.clear();
	}
	~ToPointerLock(){
		std::set<Generic*>::iterator i;
		for(i = enset.begin(); i != enset.end(); ++i){
			(*i)->to_pointer = NULL;
		}
	}
};

class Cons : public Generic{
protected:
	Cons(Cons const& s) : Generic(), a(s.a), d(s.d){};
	virtual boost::shared_ptr<Atom> type_atom(void) const {return CONSATOM;};
public:
	Generic* a;
	Generic* d;
	/*standard stuff*/
	virtual size_t hash(void) const {
		return a->hash() ^ d->hash();
	}
	virtual Cons* clone(Semispace& sp) const{
		return new(sp) Cons(*this);
	}
	virtual size_t get_size(void) const {
		return sizeof(Cons);
	}

	/*comparisons*/
	virtual bool iso(Generic*gp) const{
		if(is(gp)) {
			return 1;
		} else {
			Cons* cp = dynamic_cast<Cons*>(gp);
			if(cp != NULL){
				return a->iso(cp->a) && d->iso(cp->d);
			} else return 0;
		}
	}

	/*references*/
	virtual void get_refs(std::stack<Generic**>&s){
		s.push(&a);
		s.push(&d);
	}

	virtual void probe(size_t);

	Cons(void) : Generic() {};
	virtual ~Cons(){};

};

class MetadataCons : public Cons {
protected:
	MetadataCons(MetadataCons const& s):Cons(s), line(s.line), file(s.file){};
public:
	Generic* line;
	Generic* file;
	virtual MetadataCons* clone(Semispace& sp) const{
		return new(sp) MetadataCons(*this);
	}
	virtual size_t get_size(void) const {
		return sizeof(MetadataCons);
	}
	virtual void get_refs(std::stack<Generic**>& s){
		Cons::get_refs(s);
		s.push(&line);
		s.push(&file);
	}

	virtual void probe(size_t);

	MetadataCons() : Cons() {};
	virtual ~MetadataCons(){};

};

class Sym : public Generic{
private:
	Sym(void){}; //disallowed!
protected:
	Sym(Sym const& s) : Generic(), a(s.a){};
	virtual boost::shared_ptr<Atom> type_atom(void) const {return SYMATOM;};
public:
	/*standard stuff*/
	virtual size_t hash(void) const{
		return (size_t) &(*a);
	}
	virtual Sym* clone(Semispace& sp) const{
		return new(sp) Sym(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Sym);
	};

	virtual bool is(Generic* gp) const{
		if(gp == this) return 1;
		Sym* sp = dynamic_cast<Sym*>(gp);
		if(sp != NULL){
			return sp->a == a;
		} else return 0;
	};

	virtual bool isnil(void) const {
		return a == NILATOM;
	}

	virtual void probe(size_t);

	Sym(boost::shared_ptr<Atom> const& na) : Generic(), a(na){};
	virtual ~Sym(){};

	/*new stuff*/
	Atom& atom(void){return *a;};
	boost::shared_ptr<Atom> a;
};

class Executor;

class Closure : public Generic {
private:
	boost::shared_ptr<Executor> cd;
	/*possibly add a parallel vector of variable name atoms for
	debugging?
	*/
	std::vector<Generic*> vars;
protected:
	Closure(Closure const& o) : Generic(), cd(o.cd), vars(o.vars) {}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return FNATOM;};
public:
	/*standard stuff*/
	virtual size_t hash(void) const{
		return (size_t) &*cd;
	}
	virtual Closure* clone(Semispace& sp) const{
		return new(sp) Closure(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Closure);
	}

	virtual void get_refs(std::stack<Generic**>& s){
		for(size_t i = 0; i < vars.size(); ++i){
			s.push(&vars[i]);
		}
	}

	virtual void probe(size_t);

	Closure(Executor* c, size_t s) :
		Generic(), cd(c), vars(s) {};
	Closure(boost::shared_ptr<Executor> c, size_t s) :
		Generic(), cd(c), vars(s) {};

	/*new stuff*/
	Executor const& code(void) {return *cd;};
	/*WARNING
	arc2c references closure values starting at index 1 (index 0
	is the function's code itself, and is never used in practice).
	We will have to translate the numbers properly for those cases
	*/
	Generic* & operator[](int i) {return vars[i];}
	Generic* const & operator[](int i) const {return vars[i];}
};

class Integer : public Generic {
private:
	int val;
protected:
	Integer(Integer const& o) : Generic(), val(o.val){}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return INTATOM;};
public:
	/*standard stuff*/
	virtual size_t hash() const {
		return (size_t) val;
	}
	virtual Integer* clone(Semispace& sp) const{
		return new(sp) Integer(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Integer);
	}

	virtual void probe(size_t);

	/*new stuff*/
	int integer(void){return val;}
	Integer(int x) : Generic(), val(x) {}
};

/*Used during compilation to hold a bytecode sequence while
converting from a symbolcode list to an internal bytecode
format.
*/
class ArcBytecodeSequence : public Generic {
protected:
	ArcBytecodeSequence(ArcBytecodeSequence const & o)
		: Generic(), seq(o.seq) {}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return INTERNALATOM;};
public:
	/*standard stuff*/
	virtual size_t hash() const{
		return (size_t)(void*) &*seq;
	}
	virtual ArcBytecodeSequence* clone(Semispace& sp) const{
		return new(sp) ArcBytecodeSequence(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(ArcBytecodeSequence);
	}

	virtual void probe(size_t);

	/*new stuff*/
	void append(Bytecode* b){
		seq->append(b);
	}
	boost::shared_ptr<BytecodeSequence> seq;
	ArcBytecodeSequence(void) : Generic(), seq(new BytecodeSequence()) {}
};

#endif //TYPES_H

<commit_msg>types: rearranged declarations, added tagged types<commit_after>#ifndef TYPES_H
#define TYPES_H
#include<stack>
#include<set>
#include<vector>
#include"heaps.hpp"
#include"hashes.hpp"
#include"variables.hpp"
#include"executors.hpp"

class Semispace;
void* operator new(size_t, Semispace&);
void operator delete(void*, Semispace&);

class ToPointerLock;

class Generic {
private:
	Generic* to_pointer;
protected:
	Generic(void) : to_pointer(NULL) {};
	Generic(Generic const&) : to_pointer(NULL) {};
	virtual boost::shared_ptr<Atom> type_atom(void) const =0;
public:
	friend class Semispace;
	friend class ToPointerLock;

	/*standard stuff*/
	/*hash should return pretty much just any
	size_t, provided that an unmutated copy of
	that object will have the same hash().
	There is NO NEED TO PROPERLY DISTRIBUTE BITS,
	and it would probably be better not to: the
	table lookup function will use several int-
	to-int hashing functions for the bloom
	filter.
	*/
	virtual size_t hash(void) const =0;
	virtual Generic* clone(Semispace&) const =0;
	/* clone should always have the following code:
	virtual Type* clone(Semispace& sp) const{
		return new(sp) Type(*this);
	}
	*/
	virtual size_t get_size(void) const =0;
	/*get_size should always have the following code:
	virtual size_t get_size(void) const {
		return sizeof(Type);
	}
	*/
	virtual void probe(size_t indent) =0;//for debugging

	/*overridable stuff*/

	/*gets addresses of references to other objects*/
	virtual void get_refs(std::stack<Generic**>&){};

	/*comparisons*/
	virtual bool is(Generic const* gp) const{return gp == this;}
	virtual bool iso(Generic const* gp) const{return is(gp);}
	virtual bool isnil(void) const {return 0;};
	bool istrue(void) const {return !isnil();};

	virtual Generic* type(Process&) const;
	virtual Generic* rep(void) {return this;};

	virtual ~Generic(){};

	/*truly generic stuff*/
	size_t total_size(ToPointerLock&, std::stack<Generic**>&);
};

inline bool is(Generic const* a, Generic const* b){ return a->is(b);}
inline bool iso(Generic const* a, Generic const* b){ return a->iso(b);}

/*RAII class to handle the to-pointers
This is used to protect the to-pointers in case of
an exception.  The invariant is, to-pointers are
NULL during normal operation.  If to-pointers must
be used, access to them should be via
ToPointerLock's, so that the to-pointers are reset
to NULL once the non-normal operation (GC,
tracing) are complete.  When the operation
determines that the to-pointers can be left used
(i.e. after a GC run) then it can call the good()
member function so that it won't bother resetting
the to-pointers.
*/
class ToPointerLock{
private:
	std::set<Generic*> enset;
public:
	void pointto(Generic* from, Generic* to){
		enset.insert(from);
		from->to_pointer = to;
	}
	Generic* to(Generic* from){
		return from->to_pointer;
	}
	/*used to ignore the to-pointers in a successful
	copy-and-sweep GC cycle
	*/
	void good(void){
		enset.clear();
	}
	~ToPointerLock(){
		std::set<Generic*>::iterator i;
		for(i = enset.begin(); i != enset.end(); ++i){
			(*i)->to_pointer = NULL;
		}
	}
};

class Cons : public Generic{
protected:
	Cons(Cons const& s) : Generic(), a(s.a), d(s.d){};
	virtual boost::shared_ptr<Atom> type_atom(void) const {return CONSATOM;};
public:
	/*standard stuff*/
	virtual size_t hash(void) const {
		return a->hash() ^ d->hash();
	}
	virtual Cons* clone(Semispace& sp) const{
		return new(sp) Cons(*this);
	}
	virtual size_t get_size(void) const {
		return sizeof(Cons);
	}
	virtual void probe(size_t);

	/*overridden stuff*/
	/*comparisons*/
	virtual bool iso(Generic*gp) const{
		if(is(gp)) {
			return 1;
		} else {
			Cons* cp = dynamic_cast<Cons*>(gp);
			if(cp != NULL){
				return a->iso(cp->a) && d->iso(cp->d);
			} else return 0;
		}
	}

	/*references*/
	virtual void get_refs(std::stack<Generic**>&s){
		s.push(&a);
		s.push(&d);
	}

	Generic* a;
	Generic* d;

	Cons(void) : Generic() {};
	virtual ~Cons(){};

};

class MetadataCons : public Cons {
protected:
	MetadataCons(MetadataCons const& s):Cons(s), line(s.line), file(s.file){};
public:
	/*standard stuff*/
	virtual MetadataCons* clone(Semispace& sp) const{
		return new(sp) MetadataCons(*this);
	}
	virtual size_t get_size(void) const {
		return sizeof(MetadataCons);
	}
	virtual void probe(size_t);

	/*overrideable stuff*/
	virtual void get_refs(std::stack<Generic**>& s){
		Cons::get_refs(s);
		s.push(&line);
		s.push(&file);
	}

	Generic* line;
	Generic* file;
	MetadataCons() : Cons() {};
	virtual ~MetadataCons(){};

};

class Sym : public Generic{
private:
	Sym(void){}; //disallowed!
protected:
	Sym(Sym const& s) : Generic(), a(s.a){};
	virtual boost::shared_ptr<Atom> type_atom(void) const {return SYMATOM;};
public:
	/*standard stuff*/
	virtual size_t hash(void) const{
		return (size_t) &(*a);
	}
	virtual Sym* clone(Semispace& sp) const{
		return new(sp) Sym(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Sym);
	};
	virtual void probe(size_t);

	/*overrideable stuff*/
	virtual bool is(Generic* gp) const{
		if(gp == this) return 1;
		Sym* sp = dynamic_cast<Sym*>(gp);
		if(sp != NULL){
			return sp->a == a;
		} else return 0;
	};

	virtual bool isnil(void) const {
		return a == NILATOM;
	}

	Sym(boost::shared_ptr<Atom> const& na) : Generic(), a(na){};
	virtual ~Sym(){};

	/*new stuff*/
	Atom& atom(void){return *a;};
	boost::shared_ptr<Atom> a;
};

class Executor;

class Closure : public Generic {
private:
	boost::shared_ptr<Executor> cd;
	/*possibly add a parallel vector of variable name atoms for
	debugging?
	*/
	std::vector<Generic*> vars;
protected:
	Closure(Closure const& o) : Generic(), cd(o.cd), vars(o.vars) {}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return FNATOM;};
public:
	/*standard stuff*/
	virtual size_t hash(void) const{
		return (size_t) &*cd;
	}
	virtual Closure* clone(Semispace& sp) const{
		return new(sp) Closure(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Closure);
	}
	virtual void probe(size_t);

	/*overrideable stuff*/
	virtual void get_refs(std::stack<Generic**>& s){
		for(size_t i = 0; i < vars.size(); ++i){
			s.push(&vars[i]);
		}
	}

	Closure(Executor* c, size_t s) :
		Generic(), cd(c), vars(s) {};
	Closure(boost::shared_ptr<Executor> c, size_t s) :
		Generic(), cd(c), vars(s) {};

	/*new stuff*/
	Executor const& code(void) {return *cd;};
	/*WARNING
	arc2c references closure values starting at index 1 (index 0
	is the function's code itself, and is never used in practice).
	We will have to translate the numbers properly for those cases
	*/
	Generic* & operator[](int i) {return vars[i];}
	Generic* const & operator[](int i) const {return vars[i];}
};

class Integer : public Generic {
private:
	int val;
protected:
	Integer(Integer const& o) : Generic(), val(o.val){}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return INTATOM;};
public:
	/*standard stuff*/
	virtual size_t hash() const {
		return (size_t) val;
	}
	virtual Integer* clone(Semispace& sp) const{
		return new(sp) Integer(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Integer);
	}

	virtual void probe(size_t);

	/*new stuff*/
	int integer(void){return val;}
	Integer(int x) : Generic(), val(x) {}
};

/*Used during compilation to hold a bytecode sequence while
converting from a symbolcode list to an internal bytecode
format.
*/
class ArcBytecodeSequence : public Generic {
protected:
	ArcBytecodeSequence(ArcBytecodeSequence const & o)
		: Generic(), seq(o.seq) {}
	virtual boost::shared_ptr<Atom> type_atom(void) const {return INTERNALATOM;};
public:
	/*standard stuff*/
	virtual size_t hash() const{
		return (size_t)(void*) &*seq;
	}
	virtual ArcBytecodeSequence* clone(Semispace& sp) const{
		return new(sp) ArcBytecodeSequence(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(ArcBytecodeSequence);
	}
	virtual void probe(size_t);

	/*new stuff*/
	void append(Bytecode* b){
		seq->append(b);
	}
	boost::shared_ptr<BytecodeSequence> seq;
	ArcBytecodeSequence(void) : Generic(), seq(new BytecodeSequence()) {}
};

/*created by 'annotate*/
class Tagged : public Generic {
protected:
	Tagged(Tagged const& o)
		: Generic(), type_o(o.type_o), rep_o(o.rep_o) {}
	/*shouldn't be used*/
	virtual boost::shared_ptr<Atom> type_atom(void) const {return INTERNALATOM;};
public:
	/*standard stuff*/
	virtual size_t hash() const{
		return type_o->hash() + rep_o->hash();
	}
	virtual Tagged* clone(Semispace& sp) const{
		return new(sp) Tagged(*this);
	}
	virtual size_t get_size(void) const{
		return sizeof(Tagged);
	}
	virtual void probe(size_t);

	/*overridden stuff*/
	virtual void get_refs(std::stack<Generic**>& s){
		s.push(&type_o);
		s.push(&rep_o);
	}
	virtual Generic* type(Process&) const {
		return type_o;
	}
	virtual Generic* rep(void) {
		return rep_o;
	}

	/*new stuff*/
	Generic* type_o;
	Generic* rep_o;
	Tagged(void) : Generic() {}
};

#endif //TYPES_H

<|endoftext|>


<commit_before>#include "TMC2130Stepper.h"
#include "TMC2130Stepper_MACROS.h"

// PWMCONF
uint32_t TMC2130Stepper::PWMCONF() { READ_REG(PWMCONF); }
void TMC2130Stepper::PWMCONF(uint32_t input) {
	PWMCONF_sr = input;
	WRITE_REG(PWMCONF);
}

void TMC2130Stepper::pwm_ampl(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_AMPL);		}
void TMC2130Stepper::pwm_grad(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_GRAD);		}
void TMC2130Stepper::pwm_freq(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_FREQ);		}
void TMC2130Stepper::pwm_autoscale(	bool 	B )	{ MOD_REG(PWMCONF, PWM_AUTOSCALE);	}
void TMC2130Stepper::pwm_symmetric(	bool 	B )	{ MOD_REG(PWMCONF, PWM_SYMMETRIC);	}
void TMC2130Stepper::freewheel(		uint8_t B )	{ MOD_REG(PWMCONF, FREEWHEEL);		}

uint8_t TMC2130Stepper::pwm_ampl()		{ GET_BYTE(PWMCONF, PWM_AMPL);		}
uint8_t TMC2130Stepper::pwm_grad()		{ GET_BYTE(PWMCONF, PWM_GRAD);		}
uint8_t TMC2130Stepper::pwm_freq()		{ GET_BYTE(PWMCONF, PWM_FREQ);		}
bool 	TMC2130Stepper::pwm_autoscale()	{ GET_BYTE(PWMCONF, PWM_AUTOSCALE);	}
bool 	TMC2130Stepper::pwm_symmetric()	{ GET_BYTE(PWMCONF, PWM_SYMMETRIC);	}
uint8_t TMC2130Stepper::freewheel()		{ GET_BYTE(PWMCONF, FREEWHEEL);		}
<commit_msg>Fix reading PWMCONF<commit_after>#include "TMC2130Stepper.h"
#include "TMC2130Stepper_MACROS.h"

// PWMCONF
uint32_t TMC2130Stepper::PWMCONF() { return PWMCONF_sr; }
void TMC2130Stepper::PWMCONF(uint32_t input) {
	PWMCONF_sr = input;
	WRITE_REG(PWMCONF);
}

void TMC2130Stepper::pwm_ampl(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_AMPL);		}
void TMC2130Stepper::pwm_grad(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_GRAD);		}
void TMC2130Stepper::pwm_freq(		uint8_t B )	{ MOD_REG(PWMCONF, PWM_FREQ);		}
void TMC2130Stepper::pwm_autoscale(	bool 	B )	{ MOD_REG(PWMCONF, PWM_AUTOSCALE);	}
void TMC2130Stepper::pwm_symmetric(	bool 	B )	{ MOD_REG(PWMCONF, PWM_SYMMETRIC);	}
void TMC2130Stepper::freewheel(		uint8_t B )	{ MOD_REG(PWMCONF, FREEWHEEL);		}

uint8_t TMC2130Stepper::pwm_ampl()		{ GET_BYTE(PWMCONF, PWM_AMPL);		}
uint8_t TMC2130Stepper::pwm_grad()		{ GET_BYTE(PWMCONF, PWM_GRAD);		}
uint8_t TMC2130Stepper::pwm_freq()		{ GET_BYTE(PWMCONF, PWM_FREQ);		}
bool 	TMC2130Stepper::pwm_autoscale()	{ GET_BYTE(PWMCONF, PWM_AUTOSCALE);	}
bool 	TMC2130Stepper::pwm_symmetric()	{ GET_BYTE(PWMCONF, PWM_SYMMETRIC);	}
uint8_t TMC2130Stepper::freewheel()		{ GET_BYTE(PWMCONF, FREEWHEEL);		}
<|endoftext|>


<commit_before>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include "../matlab/position.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver)
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;

	while (!stop) {
		CameraData data = dequeue();

		if (data.valid) {
			// ROS_DEBUG("Got valid data");
			receivedFirstPosition = true;
			Vector position = tracker.updatePosition(data.cameraVector, data.camNo, data.quadcopterId);

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data.quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				long int startTime = getNanoTime();
				receiver->updatePositions(positions, ids, updates);
				double duration = getNanoTime() - startTime;
				duration /= 1e6;

				ROS_DEBUG("Updating position of quadcopter %d took %.3f ms", data.quadcopterId, duration);
			} else {
				// ROS_DEBUG("Not enough information to get position of quadcopter %d", data.quadcopterId);
			}
		} else if (receivedFirstPosition) {
			ROS_WARN("Position update buffer is empty!");
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	// ROS_DEBUG("updatePosition: called");

	enqueue(data);

	// ROS_DEBUG("updatePosition: Inserted CameraData for camera %d and quadcopter %d", data.camNo, data.quadcopterId);
}

void TrackingWorker::enqueue(CameraData data)
{
	// ROS_DEBUG("enqueue: Inserting CameraData");

	{
		boost::mutex::scoped_lock lock(positionsMutex);
		// ROS_DEBUG("enqueue: Got positions lock");
		positions.push(data);

		if (positions.size() > 25) {
			ROS_WARN("Position update buffer is running full (%ld entries). Seems like the position updating can't keep up!", positions.size());
		}
	}

	// ROS_DEBUG("enqueue: Released positions lock");
	// ROS_DEBUG("enqueue: Notifying about new CameraData");

	positionsEmpty.notify_one();

	// ROS_DEBUG("enqueue: Finished insertion process");
}

CameraData TrackingWorker::dequeue()
{
	// ROS_DEBUG("dequeue: Getting positions lock");

	{
		boost::mutex::scoped_lock lock(positionsMutex);

		// ROS_DEBUG("dequeue: Got positions lock");

		if (!dataAvailable()) {
			positionsEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
		}

		if (dataAvailable()) {
			CameraData data = positions.back();
			positions.pop();

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		} else {
			CameraData data;
			data.valid = false;

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		}
	}
}

bool TrackingWorker::dataAvailable()
{
	return positions.size() > 0;
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}<commit_msg>Corrected time measurement<commit_after>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include "../matlab/position.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver)
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;

	while (!stop) {
		CameraData data = dequeue();

		if (data.valid) {
			// ROS_DEBUG("Got valid data");
			receivedFirstPosition = true;

			long int startTime = getNanoTime();
			Vector position = tracker.updatePosition(data.cameraVector, data.camNo, data.quadcopterId);
			double duration = getNanoTime() - startTime;
			duration /= 1e6;

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data.quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				receiver->updatePositions(positions, ids, updates);
			} else {
				// ROS_DEBUG("Not enough information to get position of quadcopter %d", data.quadcopterId);
			}

			ROS_DEBUG("Updating position of quadcopter %d took %.3f ms", data.quadcopterId, duration);
		} else if (receivedFirstPosition) {
			ROS_WARN("Position update buffer is empty!");
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	// ROS_DEBUG("updatePosition: called");

	enqueue(data);

	// ROS_DEBUG("updatePosition: Inserted CameraData for camera %d and quadcopter %d", data.camNo, data.quadcopterId);
}

void TrackingWorker::enqueue(CameraData data)
{
	// ROS_DEBUG("enqueue: Inserting CameraData");

	{
		boost::mutex::scoped_lock lock(positionsMutex);
		// ROS_DEBUG("enqueue: Got positions lock");
		positions.push(data);

		if (positions.size() > 25) {
			ROS_WARN("Position update buffer is running full (%ld entries). Seems like the position updating can't keep up!", positions.size());
		}
	}

	// ROS_DEBUG("enqueue: Released positions lock");
	// ROS_DEBUG("enqueue: Notifying about new CameraData");

	positionsEmpty.notify_one();

	// ROS_DEBUG("enqueue: Finished insertion process");
}

CameraData TrackingWorker::dequeue()
{
	// ROS_DEBUG("dequeue: Getting positions lock");

	{
		boost::mutex::scoped_lock lock(positionsMutex);

		// ROS_DEBUG("dequeue: Got positions lock");

		if (!dataAvailable()) {
			positionsEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
		}

		if (dataAvailable()) {
			CameraData data = positions.back();
			positions.pop();

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		} else {
			CameraData data;
			data.valid = false;

			// ROS_DEBUG("dequeue: Released positions lock");
			return data;
		}
	}
}

bool TrackingWorker::dataAvailable()
{
	return positions.size() > 0;
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}<|endoftext|>


<commit_before>/*
    This file is part of KMail.

    Copyright (c) 2005 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "distributionlistdialog.h"

#include <kpimutils/email.h>
#include <kabc/resource.h>
#include <kabc/stdaddressbook.h>
#include <kabc/distributionlist.h>

#include <KLocale>
#include <KDebug>
#include <KLineEdit>
#include <KMessageBox>
#include <KInputDialog>

#include <QLabel>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include "distributionlistdialog.moc"

class DistributionListItem : public QTreeWidgetItem
{
  public:
    DistributionListItem( QTreeWidget *tree )
      : QTreeWidgetItem( tree )
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
    }

    void setAddressee( const KABC::Addressee &a, const QString &email )
    {
      mIsTransient = false;
      init( a, email );
    }

    void setTransientAddressee( const KABC::Addressee &a, const QString &email )
    {
      mIsTransient = true;
      init( a, email );
    }

    void init( const KABC::Addressee &a, const QString &email )
    {
      mAddressee = a;
      mEmail = email;
      setText( 0, mAddressee.realName() );
      setText( 1, mEmail );
    }

    KABC::Addressee addressee() const
    {
      return mAddressee;
    }

    QString email() const
    {
      return mEmail;
    }

    bool isTransient() const
    {
      return mIsTransient;
    }

  private:
    KABC::Addressee mAddressee;
    QString mEmail;
    bool mIsTransient;
};

DistributionListDialog::DistributionListDialog( QWidget *parent )
  : KDialog( parent )
{
  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  setCaption( i18nc("@title:window", "Save Distribution List") );
  setButtons( User1 | Cancel );
  setDefaultButton( User1 );
  setModal( false );
  setButtonText( User1, i18nc("@action:button","Save List") );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );
  topLayout->setSpacing( spacingHint() );

  QBoxLayout *titleLayout = new QHBoxLayout();
  titleLayout->setSpacing( spacingHint() );
  topLayout->addItem( titleLayout );

  QLabel *label = new QLabel(
    i18nc("@label:textbox Name of the distribution list.", "&Name:"), topFrame );
  titleLayout->addWidget( label );

  mTitleEdit = new KLineEdit( topFrame );
  titleLayout->addWidget( mTitleEdit );
  mTitleEdit->setFocus();
  mTitleEdit->setClearButtonShown( true );
  label->setBuddy( mTitleEdit );

  mRecipientsList = new QTreeWidget( topFrame );
  mRecipientsList->setHeaderLabels(
                     QStringList() << i18nc( "@title:column Name of the recipient","Name" )
                                   << i18nc( "@title:column Email of the recipient", "Email" )
                                  );
  mRecipientsList->setRootIsDecorated( false );
  topLayout->addWidget( mRecipientsList );
  connect( this, SIGNAL( user1Clicked() ),
           this, SLOT( slotUser1() ) );
}

void DistributionListDialog::setRecipients( const Recipient::List &recipients )
{
  Recipient::List::ConstIterator it;
  for( it = recipients.constBegin(); it != recipients.constEnd(); ++it ) {
    QStringList emails = KPIMUtils::splitAddressList( (*it).email() );
    QStringList::ConstIterator it2;
    for( it2 = emails.constBegin(); it2 != emails.constEnd(); ++it2 ) {
      QString name;
      QString email;
      KABC::Addressee::parseEmailAddress( *it2, name, email );
      if ( !email.isEmpty() ) {
        DistributionListItem *item = new DistributionListItem( mRecipientsList );
        KABC::Addressee::List addressees =
          KABC::StdAddressBook::self( true )->findByEmail( email );
        if ( addressees.isEmpty() ) {
          KABC::Addressee a;
          a.setNameFromString( name );
          a.insertEmail( email );
          item->setTransientAddressee( a, email );
          item->setCheckState( 0, Qt::Checked );
        } else {
          KABC::Addressee::List::ConstIterator it3;
          for( it3 = addressees.constBegin(); it3 != addressees.constEnd(); ++it3 ) {
            item->setAddressee( *it3, email );
            if ( it3 == addressees.constBegin() ) item->setCheckState( 0, Qt::Checked );
          }
        }
      }
    }
  }
}

void DistributionListDialog::slotUser1()
{
  bool isEmpty = true;

  KABC::AddressBook *ab = KABC::StdAddressBook::self( true );

  for (int i = 0; i < mRecipientsList->topLevelItemCount(); ++i) {
    DistributionListItem *item = static_cast<DistributionListItem *>(
        mRecipientsList->topLevelItem( i ));
    if ( item && item->checkState( 0 ) == Qt::Checked ) {
      isEmpty = false;
      break;
    }
  }

  if ( isEmpty ) {
    KMessageBox::information( this,
                              i18nc("@info", "There are no recipients in your list. "
                                   "First select some recipients, "
                                   "then try again.") );
    return;
  }

  QString name = mTitleEdit->text();

  if ( name.isEmpty() ) {
    bool ok = false;
    name = KInputDialog::getText( i18nc("@title:window","New Distribution List"),
      i18nc("@label:textbox","Please enter name:"), QString(), &ok, this );
    if ( !ok || name.isEmpty() )
      return;
  }

  if ( ab->findDistributionListByName( name ) ) {
    KMessageBox::information( this,
      i18nc( "@info", "<para>Distribution list with the given name <resource>%1</resource> "
        "already exists. Please select a different name.</para>", name ) );
    return;
  }

  KABC::DistributionList *dlist = ab->createDistributionList( name );

  for (int i = 0; i < mRecipientsList->topLevelItemCount(); ++i) {
    DistributionListItem *item = static_cast<DistributionListItem *>(
        mRecipientsList->topLevelItem( i ));
    if ( item && item->checkState( 0 ) == Qt::Checked ) {
      kDebug() << item->addressee().fullEmail() << item->addressee().uid();
      if ( item->isTransient() ) {
        ab->insertAddressee( item->addressee() );
      }
      if ( item->email() == item->addressee().preferredEmail() ) {
        dlist->insertEntry( item->addressee() );
      } else {
        dlist->insertEntry( item->addressee(), item->email() );
      }
    }
  }

  // FIXME: Ask the user which resource to save to instead of the default
  bool saveError = true;
  KABC::Ticket *ticket = ab->requestSaveTicket( 0 /*default resource */ );
  if ( ticket ) {
    if ( ab->save( ticket ) ) {
      saveError = false;
    }
    else
      ab->releaseSaveTicket( ticket );
  }

  if ( saveError )
    kWarning() <<" Couldn't save new addresses in the distribution list just created to the address book";

  close();
}
<commit_msg>Backport r986576 by tmcguire from trunk to the 4.3 branch:<commit_after>/*
    This file is part of KMail.

    Copyright (c) 2005 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "distributionlistdialog.h"

#include <kpimutils/email.h>
#include <kabc/resource.h>
#include <kabc/stdaddressbook.h>
#include <kabc/distributionlist.h>

#include <KLocale>
#include <KDebug>
#include <KLineEdit>
#include <KMessageBox>
#include <KInputDialog>

#include <QLabel>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include "distributionlistdialog.moc"

class DistributionListItem : public QTreeWidgetItem
{
  public:
    DistributionListItem( QTreeWidget *tree )
      : QTreeWidgetItem( tree )
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
    }

    void setAddressee( const KABC::Addressee &a, const QString &email )
    {
      mIsTransient = false;
      init( a, email );
    }

    void setTransientAddressee( const KABC::Addressee &a, const QString &email )
    {
      mIsTransient = true;
      init( a, email );
    }

    void init( const KABC::Addressee &a, const QString &email )
    {
      mAddressee = a;
      mEmail = email;
      setText( 0, mAddressee.realName() );
      setText( 1, mEmail );
    }

    KABC::Addressee addressee() const
    {
      return mAddressee;
    }

    QString email() const
    {
      return mEmail;
    }

    bool isTransient() const
    {
      return mIsTransient;
    }

  private:
    KABC::Addressee mAddressee;
    QString mEmail;
    bool mIsTransient;
};

DistributionListDialog::DistributionListDialog( QWidget *parent )
  : KDialog( parent )
{
  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  setCaption( i18nc("@title:window", "Save Distribution List") );
  setButtons( User1 | Cancel );
  setDefaultButton( User1 );
  setModal( false );
  setButtonText( User1, i18nc("@action:button","Save List") );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );
  topLayout->setSpacing( spacingHint() );

  QBoxLayout *titleLayout = new QHBoxLayout();
  titleLayout->setSpacing( spacingHint() );
  topLayout->addItem( titleLayout );

  QLabel *label = new QLabel(
    i18nc("@label:textbox Name of the distribution list.", "&Name:"), topFrame );
  titleLayout->addWidget( label );

  mTitleEdit = new KLineEdit( topFrame );
  titleLayout->addWidget( mTitleEdit );
  mTitleEdit->setFocus();
  mTitleEdit->setClearButtonShown( true );
  label->setBuddy( mTitleEdit );

  mRecipientsList = new QTreeWidget( topFrame );
  mRecipientsList->setHeaderLabels(
                     QStringList() << i18nc( "@title:column Name of the recipient","Name" )
                                   << i18nc( "@title:column Email of the recipient", "Email" )
                                  );
  mRecipientsList->setRootIsDecorated( false );
  topLayout->addWidget( mRecipientsList );
  connect( this, SIGNAL( user1Clicked() ),
           this, SLOT( slotUser1() ) );
}

void DistributionListDialog::setRecipients( const Recipient::List &recipients )
{
  Recipient::List::ConstIterator it;
  for( it = recipients.constBegin(); it != recipients.constEnd(); ++it ) {
    QStringList emails = KPIMUtils::splitAddressList( (*it).email() );
    QStringList::ConstIterator it2;
    for( it2 = emails.constBegin(); it2 != emails.constEnd(); ++it2 ) {
      QString name;
      QString email;
      KABC::Addressee::parseEmailAddress( *it2, name, email );
      if ( !email.isEmpty() ) {
        DistributionListItem *item = new DistributionListItem( mRecipientsList );
        KABC::Addressee::List addressees =
          KABC::StdAddressBook::self( true )->findByEmail( email );
        if ( addressees.isEmpty() ) {
          KABC::Addressee a;
          a.setNameFromString( name );
          a.insertEmail( email );
          item->setTransientAddressee( a, email );
          item->setCheckState( 0, Qt::Checked );
        } else {
          KABC::Addressee::List::ConstIterator it3;
          for( it3 = addressees.constBegin(); it3 != addressees.constEnd(); ++it3 ) {
            item->setAddressee( *it3, email );
            if ( it3 == addressees.constBegin() ) item->setCheckState( 0, Qt::Checked );
          }
        }
      }
    }
  }
}

void DistributionListDialog::slotUser1()
{
  bool isEmpty = true;

  KABC::AddressBook *ab = KABC::StdAddressBook::self( true );

  for (int i = 0; i < mRecipientsList->topLevelItemCount(); ++i) {
    DistributionListItem *item = static_cast<DistributionListItem *>(
        mRecipientsList->topLevelItem( i ));
    if ( item && item->checkState( 0 ) == Qt::Checked ) {
      isEmpty = false;
      break;
    }
  }

  if ( isEmpty ) {
    KMessageBox::information( this,
                              i18nc("@info", "There are no recipients in your list. "
                                   "First select some recipients, "
                                   "then try again.") );
    return;
  }

  QString name = mTitleEdit->text();

  if ( name.isEmpty() ) {
    bool ok = false;
    name = KInputDialog::getText( i18nc("@title:window","New Distribution List"),
      i18nc("@label:textbox","Please enter name:"), QString(), &ok, this );
    if ( !ok || name.isEmpty() )
      return;
  }

  if ( ab->findDistributionListByName( name ) ) {
    KMessageBox::information( this,
      i18nc( "@info", "<para>Distribution list with the given name <resource>%1</resource> "
        "already exists. Please select a different name.</para>", name ) );
    return;
  }

  KABC::DistributionList *dlist = ab->createDistributionList( name );

  for (int i = 0; i < mRecipientsList->topLevelItemCount(); ++i) {
    DistributionListItem *item = static_cast<DistributionListItem *>(
        mRecipientsList->topLevelItem( i ));
    if ( item && item->checkState( 0 ) == Qt::Checked ) {
      kDebug() << item->addressee().fullEmail() << item->addressee().uid();
      if ( item->isTransient() ) {
        ab->insertAddressee( item->addressee() );
      }
      if ( item->email() == item->addressee().preferredEmail() ) {
        dlist->insertEntry( item->addressee() );
      } else {
        dlist->insertEntry( item->addressee(), item->email() );
      }
    }
  }

  // let the resource know that the data has changed
  KABC::Resource *resource = dlist->resource();
  resource->insertDistributionList( dlist );

  // save the resource
  bool saveError = true;
  KABC::Ticket *ticket = ab->requestSaveTicket( resource );
  if ( ticket ) {
    if ( ab->save( ticket ) ) {
      saveError = false;
    }
    else
      ab->releaseSaveTicket( ticket );
  }

  if ( saveError )
    kWarning() <<" Couldn't save new addresses in the distribution list just created to the address book";

  close();
}
<|endoftext|>


<commit_before>/*
 * This file is part of krss
 *
 * Copyright (C) 2009 Frank Osterfeld <osterfeld@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include <QCoreApplication>

#include <krss/importitemsjob.h>
#include <krss/resource.h>
#include <krss/resourcemanager.h>

#include <iostream>

using namespace KRss;

static void printUsage() {
    std::cerr << "Usage: itemimporter <resourceIdentifier> <feedUrl> <itemfile>" << std::endl;
}

class JobExecutor : public QObject {
  Q_OBJECT
public:
    void execJob( KJob* job ) {
        connect( job, SIGNAL(finished(KJob*)), this, SLOT(finished(KJob*)) );
        job->start();
    }

private Q_SLOTS:
    void finished( KJob* job ) {
        if ( job->error() )
            std::cerr << job->error() << qPrintable( job->errorString() ) << std::endl;
        QCoreApplication::quit();
    }
};

int main( int argc, char** argv ) {
    QCoreApplication app( argc, argv );

    if ( argc != 4 ) {
        printUsage();
        return 1;
    }

    const QString resourceId = QString::fromLocal8Bit( argv[1] );
    const QString url = QString::fromLocal8Bit( argv[2] );
    const QString file = QString::fromLocal8Bit( argv[3] );

    const Resource* const r = ResourceManager::self()->resource( resourceId );
    if ( !r ) {
        std::cerr << "Resource does not exist: " << qPrintable(resourceId) << std::endl;
        return 1;
    }

    ImportItemsJob* job = r->createImportItemsJob( url, file );
    JobExecutor exec;
    exec.execJob( job );
    return app.exec();
}

#include "itemimporter.moc"

<commit_msg>build with Dmitry's latest changes<commit_after>/*
 * This file is part of krss
 *
 * Copyright (C) 2009 Frank Osterfeld <osterfeld@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include <QCoreApplication>

#include <krss/importitemsjob.h>
#include <krss/netresource.h>
#include <krss/resourcemanager.h>

#include <iostream>

using namespace boost;
using namespace KRss;

static void printUsage() {
    std::cerr << "Usage: itemimporter <resourceIdentifier> <feedUrl> <itemfile>" << std::endl;
}

class JobExecutor : public QObject {
  Q_OBJECT
public:
    void execJob( KJob* job ) {
        connect( job, SIGNAL(finished(KJob*)), this, SLOT(finished(KJob*)) );
        job->start();
    }

private Q_SLOTS:
    void finished( KJob* job ) {
        if ( job->error() )
            std::cerr << job->error() << qPrintable( job->errorString() ) << std::endl;
        QCoreApplication::quit();
    }
};

int main( int argc, char** argv ) {
    QCoreApplication app( argc, argv );

    if ( argc != 4 ) {
        printUsage();
        return 1;
    }

    const QString resourceId = QString::fromLocal8Bit( argv[1] );
    const QString url = QString::fromLocal8Bit( argv[2] );
    const QString file = QString::fromLocal8Bit( argv[3] );

    const shared_ptr<const NetResource> r = ResourceManager::self()->resource( resourceId );
    if ( !r ) {
        std::cerr << "Resource does not exist: " << qPrintable(resourceId) << std::endl;
        return 1;
    }

    ImportItemsJob* job = r->createImportItemsJob( url, file );
    JobExecutor exec;
    exec.execJob( job );
    return app.exec();
}

#include "itemimporter.moc"

<|endoftext|>


<commit_before>#include "NdefRecord.h"

NdefRecord::NdefRecord()
{
    //Serial.println("NdefRecord Constructor 1");
    _tnf = 0;
    _typeLength = 0;
    _payloadLength = 0;
    _idLength = 0;
    _type = (byte *)NULL;
    _payload = (byte *)NULL;
    _id = (byte *)NULL;
}

NdefRecord::NdefRecord(const NdefRecord& rhs)
{
    //Serial.println("NdefRecord Constructor 2 (copy)");

    _tnf = rhs._tnf;
    _typeLength = rhs._typeLength;
    _payloadLength = rhs._payloadLength;
    _idLength = rhs._idLength;
    _type = (byte *)NULL;
    _payload = (byte *)NULL;
    _id = (byte *)NULL;

    if (_typeLength)
    {
        _type = (byte*)malloc(_typeLength);
        memcpy(_type, rhs._type, _typeLength);
    }

    if (_payloadLength)
    {
        _payload = (byte*)malloc(_payloadLength);
        memcpy(_payload, rhs._payload, _payloadLength);
    }

    if (_idLength)
    {
        _id = (byte*)malloc(_idLength);
        memcpy(_id, rhs._id, _idLength);
    }

}

// TODO NdefRecord::NdefRecord(tnf, type, payload, id)

NdefRecord::~NdefRecord()
{
    //Serial.println("NdefRecord Destructor");
    if (_typeLength)
    {
        free(_type);
    }

    if (_payloadLength)
    {
        free(_payload);
    }

    if (_idLength)
    {
        free(_id);
    }
}

NdefRecord& NdefRecord::operator=(const NdefRecord& rhs)
{
    //Serial.println("NdefRecord ASSIGN");

    if (this != &rhs)
    {
        // free existing
        if (_typeLength)
        {
            free(_type);
        }

        if (_payloadLength)
        {
            free(_payload);
        }

        if (_idLength)
        {
            free(_id);
        }

        _tnf = rhs._tnf;
        _typeLength = rhs._typeLength;
        _payloadLength = rhs._payloadLength;
        _idLength = rhs._idLength;

        if (_typeLength)
        {
            _type = (byte*)malloc(_typeLength);
            memcpy(_type, rhs._type, _typeLength);
        }

        if (_payloadLength)
        {
            _payload = (byte*)malloc(_payloadLength);
            memcpy(_payload, rhs._payload, _payloadLength);
        }

        if (_idLength)
        {
            _id = (byte*)malloc(_idLength);
            memcpy(_id, rhs._id, _idLength);
        }
    }
    return *this;
}

// size of records in bytes
int NdefRecord::getEncodedSize()
{
    int size = 2; // tnf + typeLength
    if (_payloadLength > 0xFF)
    {
        size += 4;
    }
    else
    {
        size += 1;
    }

    if (_idLength)
    {
        size += 1;
    }

    size += (_typeLength + _payloadLength + _idLength);

    return size;
}

void NdefRecord::encode(byte *data, bool firstRecord, bool lastRecord)
{
    // assert data > getEncodedSize()

    uint8_t* data_ptr = &data[0];

    *data_ptr = getTnfByte(firstRecord, lastRecord);
    data_ptr += 1;

    *data_ptr = _typeLength;
    data_ptr += 1;

    if (_payloadLength <= 0xFF) {  // short record
        *data_ptr = _payloadLength;
        data_ptr += 1;
    } else { // long format
        // 4 bytes but we store length as an int
        data_ptr[0] = 0x0; // (_payloadLength >> 24) & 0xFF;
        data_ptr[1] = 0x0; // (_payloadLength >> 16) & 0xFF;
        data_ptr[2] = (_payloadLength >> 8) & 0xFF;
        data_ptr[3] = _payloadLength & 0xFF;
        data_ptr += 4;
    }

    if (_idLength)
    {
        *data_ptr = _idLength;
        data_ptr += 1;
    }

    //Serial.println(2);
    memcpy(data_ptr, _type, _typeLength);
    data_ptr += _typeLength;

    memcpy(data_ptr, _payload, _payloadLength);
    data_ptr += _payloadLength;

    if (_idLength)
    {
        memcpy(data_ptr, _id, _idLength);
        data_ptr += _idLength;
    }
}

byte NdefRecord::getTnfByte(bool firstRecord, bool lastRecord)
{
    int value = _tnf;

    if (firstRecord) { // mb
        value = value | 0x80;
    }

    if (lastRecord) { //
        value = value | 0x40;
    }

    // chunked flag is always false for now
    // if (cf) {
    //     value = value | 0x20;
    // }

    if (_payloadLength <= 0xFF) {
        value = value | 0x10;
    }

    if (_idLength) {
        value = value | 0x8;
    }

    return value;
}

byte NdefRecord::getTnf()
{
    return _tnf;
}

void NdefRecord::setTnf(byte tnf)
{
    _tnf = tnf;
}

unsigned int NdefRecord::getTypeLength()
{
    return _typeLength;
}

int NdefRecord::getPayloadLength()
{
    return _payloadLength;
}

unsigned int NdefRecord::getIdLength()
{
    return _idLength;
}

String NdefRecord::getType()
{
    // TODO is there a simpler way to do this?
    char* type = (char*)malloc(_typeLength);
    memset(type, 0, sizeof(type));
    memcpy(type, _type, _typeLength);
    String typeString = String(type);
    free(type);
    return typeString;
}

// this assumes the caller created type correctly
void NdefRecord::getType(uint8_t* type)
{
    memcpy(type, _type, _typeLength);
}

void NdefRecord::setType(const byte * type, const unsigned int numBytes)
{
    if(_typeLength)
    {
        free(_type);
    }

    _type = (uint8_t*)malloc(numBytes);
    memcpy(_type, type, numBytes);
    _typeLength = numBytes;
}

// assumes the caller sized payload properly
void NdefRecord::getPayload(byte *payload)
{
    memcpy(payload, _payload, _payloadLength);
}

void NdefRecord::setPayload(const byte * payload, const int numBytes)
{
    if (_payloadLength)
    {
        free(_payload);
    }

    _payload = (byte*)malloc(numBytes);
    memcpy(_payload, payload, numBytes);
    _payloadLength = numBytes;
}

String NdefRecord::getId()
{
    // TODO is there a simpler way to do this?
    char* id = (char*)malloc(_idLength);
    memset(id, 0, sizeof(id));
    memcpy(id, _id, _idLength);
    String idString = String(id);
    free(id);
    return idString;
}

void NdefRecord::getId(byte *id)
{
    memcpy(id, _id, _idLength);
}

void NdefRecord::setId(const byte * id, const unsigned int numBytes)
{
    if (_idLength)
    {
        free(_id);
    }

    _id = (byte*)malloc(numBytes);
    memcpy(_id, id, numBytes);
    _idLength = numBytes;
}

void NdefRecord::print()
{
    Serial.println(F("  NDEF Record"));
    Serial.print(F("    TNF 0x"));Serial.print(_tnf, HEX);Serial.print(" ");
    switch (_tnf) {
    case TNF_EMPTY:
        Serial.println(F("Empty"));
        break;
    case TNF_WELL_KNOWN:
        Serial.println(F("Well Known"));
        break;
    case TNF_MIME_MEDIA:
        Serial.println(F("Mime Media"));
        break;
    case TNF_ABSOLUTE_URI:
        Serial.println(F("Absolute URI"));
        break;
    case TNF_EXTERNAL_TYPE:
        Serial.println(F("External"));
        break;
    case TNF_UNKNOWN:
        Serial.println(F("Unknown"));
        break;
    case TNF_UNCHANGED:
        Serial.println(F("Unchanged"));
        break;
    case TNF_RESERVED:
        Serial.println(F("Reserved"));
        break;
    default:
        Serial.println();
    }
    Serial.print(F("    Type Length 0x"));Serial.print(_typeLength, HEX);Serial.print(" ");Serial.println(_typeLength);
    Serial.print(F("    Payload Length 0x"));Serial.print(_payloadLength, HEX);;Serial.print(" ");Serial.println(_payloadLength);
    if (_idLength)
    {
        Serial.print(F("    Id Length 0x"));Serial.println(_idLength, HEX);
    }
    Serial.print(F("    Type "));PrintHexChar(_type, _typeLength);
    // TODO chunk large payloads so this is readable
    Serial.print(F("    Payload "));PrintHexChar(_payload, _payloadLength);
    if (_idLength)
    {
        Serial.print(F("    Id "));PrintHexChar(_id, _idLength);
    }
    Serial.print(F("    Record is "));Serial.print(getEncodedSize());Serial.println(" bytes");

}<commit_msg>fix bug with getType()<commit_after>#include "NdefRecord.h"

NdefRecord::NdefRecord()
{
    //Serial.println("NdefRecord Constructor 1");
    _tnf = 0;
    _typeLength = 0;
    _payloadLength = 0;
    _idLength = 0;
    _type = (byte *)NULL;
    _payload = (byte *)NULL;
    _id = (byte *)NULL;
}

NdefRecord::NdefRecord(const NdefRecord& rhs)
{
    //Serial.println("NdefRecord Constructor 2 (copy)");

    _tnf = rhs._tnf;
    _typeLength = rhs._typeLength;
    _payloadLength = rhs._payloadLength;
    _idLength = rhs._idLength;
    _type = (byte *)NULL;
    _payload = (byte *)NULL;
    _id = (byte *)NULL;

    if (_typeLength)
    {
        _type = (byte*)malloc(_typeLength);
        memcpy(_type, rhs._type, _typeLength);
    }

    if (_payloadLength)
    {
        _payload = (byte*)malloc(_payloadLength);
        memcpy(_payload, rhs._payload, _payloadLength);
    }

    if (_idLength)
    {
        _id = (byte*)malloc(_idLength);
        memcpy(_id, rhs._id, _idLength);
    }

}

// TODO NdefRecord::NdefRecord(tnf, type, payload, id)

NdefRecord::~NdefRecord()
{
    //Serial.println("NdefRecord Destructor");
    if (_typeLength)
    {
        free(_type);
    }

    if (_payloadLength)
    {
        free(_payload);
    }

    if (_idLength)
    {
        free(_id);
    }
}

NdefRecord& NdefRecord::operator=(const NdefRecord& rhs)
{
    //Serial.println("NdefRecord ASSIGN");

    if (this != &rhs)
    {
        // free existing
        if (_typeLength)
        {
            free(_type);
        }

        if (_payloadLength)
        {
            free(_payload);
        }

        if (_idLength)
        {
            free(_id);
        }

        _tnf = rhs._tnf;
        _typeLength = rhs._typeLength;
        _payloadLength = rhs._payloadLength;
        _idLength = rhs._idLength;

        if (_typeLength)
        {
            _type = (byte*)malloc(_typeLength);
            memcpy(_type, rhs._type, _typeLength);
        }

        if (_payloadLength)
        {
            _payload = (byte*)malloc(_payloadLength);
            memcpy(_payload, rhs._payload, _payloadLength);
        }

        if (_idLength)
        {
            _id = (byte*)malloc(_idLength);
            memcpy(_id, rhs._id, _idLength);
        }
    }
    return *this;
}

// size of records in bytes
int NdefRecord::getEncodedSize()
{
    int size = 2; // tnf + typeLength
    if (_payloadLength > 0xFF)
    {
        size += 4;
    }
    else
    {
        size += 1;
    }

    if (_idLength)
    {
        size += 1;
    }

    size += (_typeLength + _payloadLength + _idLength);

    return size;
}

void NdefRecord::encode(byte *data, bool firstRecord, bool lastRecord)
{
    // assert data > getEncodedSize()

    uint8_t* data_ptr = &data[0];

    *data_ptr = getTnfByte(firstRecord, lastRecord);
    data_ptr += 1;

    *data_ptr = _typeLength;
    data_ptr += 1;

    if (_payloadLength <= 0xFF) {  // short record
        *data_ptr = _payloadLength;
        data_ptr += 1;
    } else { // long format
        // 4 bytes but we store length as an int
        data_ptr[0] = 0x0; // (_payloadLength >> 24) & 0xFF;
        data_ptr[1] = 0x0; // (_payloadLength >> 16) & 0xFF;
        data_ptr[2] = (_payloadLength >> 8) & 0xFF;
        data_ptr[3] = _payloadLength & 0xFF;
        data_ptr += 4;
    }

    if (_idLength)
    {
        *data_ptr = _idLength;
        data_ptr += 1;
    }

    //Serial.println(2);
    memcpy(data_ptr, _type, _typeLength);
    data_ptr += _typeLength;

    memcpy(data_ptr, _payload, _payloadLength);
    data_ptr += _payloadLength;

    if (_idLength)
    {
        memcpy(data_ptr, _id, _idLength);
        data_ptr += _idLength;
    }
}

byte NdefRecord::getTnfByte(bool firstRecord, bool lastRecord)
{
    int value = _tnf;

    if (firstRecord) { // mb
        value = value | 0x80;
    }

    if (lastRecord) { //
        value = value | 0x40;
    }

    // chunked flag is always false for now
    // if (cf) {
    //     value = value | 0x20;
    // }

    if (_payloadLength <= 0xFF) {
        value = value | 0x10;
    }

    if (_idLength) {
        value = value | 0x8;
    }

    return value;
}

byte NdefRecord::getTnf()
{
    return _tnf;
}

void NdefRecord::setTnf(byte tnf)
{
    _tnf = tnf;
}

unsigned int NdefRecord::getTypeLength()
{
    return _typeLength;
}

int NdefRecord::getPayloadLength()
{
    return _payloadLength;
}

unsigned int NdefRecord::getIdLength()
{
    return _idLength;
}

String NdefRecord::getType()
{
    String typeString = "";
    for (int c = 0; c < _typeLength; c++) {
        typeString += (char)_type[c];
    }
    return typeString;
}

// this assumes the caller created type correctly
void NdefRecord::getType(uint8_t* type)
{
    memcpy(type, _type, _typeLength);
}

void NdefRecord::setType(const byte * type, const unsigned int numBytes)
{
    if(_typeLength)
    {
        free(_type);
    }

    _type = (uint8_t*)malloc(numBytes);
    memcpy(_type, type, numBytes);
    _typeLength = numBytes;
}

// assumes the caller sized payload properly
void NdefRecord::getPayload(byte *payload)
{
    memcpy(payload, _payload, _payloadLength);
}

void NdefRecord::setPayload(const byte * payload, const int numBytes)
{
    if (_payloadLength)
    {
        free(_payload);
    }

    _payload = (byte*)malloc(numBytes);
    memcpy(_payload, payload, numBytes);
    _payloadLength = numBytes;
}

String NdefRecord::getId()
{
    String idString = "";
    for (int c = 0; c < _idLength; c++) {
        idString += (char)_id[c];
    }
    return idString;
}

void NdefRecord::getId(byte *id)
{
    memcpy(id, _id, _idLength);
}

void NdefRecord::setId(const byte * id, const unsigned int numBytes)
{
    if (_idLength)
    {
        free(_id);
    }

    _id = (byte*)malloc(numBytes);
    memcpy(_id, id, numBytes);
    _idLength = numBytes;
}

void NdefRecord::print()
{
    Serial.println(F("  NDEF Record"));
    Serial.print(F("    TNF 0x"));Serial.print(_tnf, HEX);Serial.print(" ");
    switch (_tnf) {
    case TNF_EMPTY:
        Serial.println(F("Empty"));
        break;
    case TNF_WELL_KNOWN:
        Serial.println(F("Well Known"));
        break;
    case TNF_MIME_MEDIA:
        Serial.println(F("Mime Media"));
        break;
    case TNF_ABSOLUTE_URI:
        Serial.println(F("Absolute URI"));
        break;
    case TNF_EXTERNAL_TYPE:
        Serial.println(F("External"));
        break;
    case TNF_UNKNOWN:
        Serial.println(F("Unknown"));
        break;
    case TNF_UNCHANGED:
        Serial.println(F("Unchanged"));
        break;
    case TNF_RESERVED:
        Serial.println(F("Reserved"));
        break;
    default:
        Serial.println();
    }
    Serial.print(F("    Type Length 0x"));Serial.print(_typeLength, HEX);Serial.print(" ");Serial.println(_typeLength);
    Serial.print(F("    Payload Length 0x"));Serial.print(_payloadLength, HEX);;Serial.print(" ");Serial.println(_payloadLength);
    if (_idLength)
    {
        Serial.print(F("    Id Length 0x"));Serial.println(_idLength, HEX);
    }
    Serial.print(F("    Type "));PrintHexChar(_type, _typeLength);
    // TODO chunk large payloads so this is readable
    Serial.print(F("    Payload "));PrintHexChar(_payload, _payloadLength);
    if (_idLength)
    {
        Serial.print(F("    Id "));PrintHexChar(_id, _idLength);
    }
    Serial.print(F("    Record is "));Serial.print(getEncodedSize());Serial.println(" bytes");

}<|endoftext|>