<commit_before>//
// MessagePack for C++ deserializing routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
#include "msgpack/unpack.hpp"
#include "msgpack/unpack_define.h"
#include <stdlib.h>

namespace msgpack {

#define msgpack_unpack_struct(name) \
	struct msgpack_unpacker_##name

#define msgpack_unpack_func(ret, name) \
	ret msgpack_unpacker_##name

#define msgpack_unpack_callback(name) \
	msgpack_unpack_##name

#define msgpack_unpack_object object

#define msgpack_unpack_user zone*

struct msgpack_unpacker_context;

static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);

static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);

static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
		const char* data, size_t len, size_t* off);

static inline object msgpack_unpack_init(zone** z)
{ return object(); }

static inline object msgpack_unpack_uint8(zone** z, uint8_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint16(zone** z, uint16_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint32(zone** z, uint32_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint64(zone** z, uint64_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_int8(zone** z, int8_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int16(zone** z, int16_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int32(zone** z, int32_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int64(zone** z, int64_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_float(zone** z, float d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }

static inline object msgpack_unpack_double(zone** z, double d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }

static inline object msgpack_unpack_nil(zone** z)
{ object o; o.type = type::NIL; return o; }

static inline object msgpack_unpack_true(zone** z)
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }

static inline object msgpack_unpack_false(zone** z)
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }

static inline object msgpack_unpack_array(zone** z, unsigned int n)
{
	object o;
	o.type = type::ARRAY;
	o.via.container.size = 0;
	o.via.container.ptr = (*z)->malloc_container(n);
	return o;
}

static inline void msgpack_unpack_array_item(zone** z, object* c, object o)
{ c->via.container.ptr[ c->via.container.size++ ] = o; }

static inline object msgpack_unpack_map(zone** z, unsigned int n)
{
	object o;
	o.type = type::MAP;
	o.via.container.size = 0;
	o.via.container.ptr = (*z)->malloc_container(n*2);
	return o;
}

static inline void msgpack_unpack_map_item(zone** z, object* c, object k, object v)
{
	c->via.container.ptr[ c->via.container.size   ] = k;
	c->via.container.ptr[ c->via.container.size+1 ] = v;
	++c->via.container.size;
}

static inline object msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l)
{ object o; o.type = type::RAW; o.via.ref.ptr = p; o.via.ref.size = l; return o; }

#include "msgpack/unpack_template.h"

struct unpacker::context {
	context(zone* z)
	{
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	~context() { }

	int execute(const char* data, size_t len, size_t* off)
	{
		return msgpack_unpacker_execute(&m_ctx, data, len, off);
	}

	object data()
	{
		return msgpack_unpacker_data(&m_ctx);
	}

	void reset()
	{
		zone* z = m_ctx.user;
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	void reset(zone* z)
	{
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	zone* user()
	{
		return m_ctx.user;
	}

	void user(zone* z)
	{
		m_ctx.user = z;
	}

private:
	msgpack_unpacker_context m_ctx;

private:
	context();
	context(const context&);
};

unpacker::unpacker() :
	m_buffer(NULL),
	m_used(0),
	m_free(0),
	m_off(0),
	m_zone(new zone()),
	m_ctx(new context(&*m_zone))
{ }

unpacker::~unpacker()
{
	delete m_ctx;
}

void unpacker::expand_buffer(size_t len)
{
	if(m_off == 0) {
		size_t next_size;
		if(m_free != 0) { next_size = m_free * 2; }
		else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
		while(next_size < len + m_used) { next_size *= 2; }

		m_buffer = m_zone->realloc(m_buffer, next_size);
		m_free = next_size - m_used;

	} else {
		size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
		while(next_size < len + m_used - m_off) { next_size *= 2; }

		char* tmp = m_zone->malloc(next_size);
		memcpy(tmp, m_buffer+m_off, m_used-m_off);

		m_buffer = tmp;
		m_used = m_used - m_off;
		m_free = next_size - m_used;
		m_off = 0;
	}
}

bool unpacker::execute()
{
	int ret = m_ctx->execute(m_buffer, m_used, &m_off);
	if(ret < 0) {
		throw unpack_error("parse error");
	} else if(ret == 0) {
		return false;
	} else {
		return true;
	}
}

zone* unpacker::release_zone()
{
	zone* n = new zone();
	std::auto_ptr<zone> old(m_zone.release());
	m_zone.reset(n);

	//std::auto_ptr<zone> old(new zone());
	//m_zone.swap(old);

	// move all bytes in m_buffer to new buffer from the new zone
	if(m_used <= m_off) {
		m_buffer = NULL;
		m_used = 0;
		m_free = 0;
		m_off = 0;
	} else {
		try {
			expand_buffer(0);
		} catch (...) {
			// m_zone.swap(old);
			zone* tmp = old.release();
			old.reset(m_zone.release());
			m_zone.reset(tmp);
			throw;
		}
	}
	m_ctx->user(m_zone.get());
	return old.release();
}

object unpacker::data()
{
	return m_ctx->data();
}

void unpacker::reset()
{
	if(m_off != 0) { delete release_zone(); }
	m_ctx->reset();
}

object unpacker::unpack(const char* data, size_t len, zone& z, size_t* off)
{
	context ctx(&z);
	if(off) {
		int ret = ctx.execute(data, len, off);
		if(ret < 0) {
			throw unpack_error("parse error");
		} else if(ret == 0) {
			throw unpack_error("insufficient bytes");
		}
	} else {
		size_t noff = 0;
		int ret = ctx.execute(data, len, &noff);
		if(ret < 0) {
			throw unpack_error("parse error");
		} else if(ret == 0) {
			throw unpack_error("insufficient bytes");
		} else if(noff < len) {
			throw unpack_error("extra bytes");
		}
	}
	return ctx.data();
}

}  // namespace msgpack

<commit_msg>lang/c/msgpack: msgpack::unpacker: fix buffer reallocation algorithm<commit_after>//
// MessagePack for C++ deserializing routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
#include "msgpack/unpack.hpp"
#include "msgpack/unpack_define.h"
#include <stdlib.h>

namespace msgpack {

#define msgpack_unpack_struct(name) \
	struct msgpack_unpacker_##name

#define msgpack_unpack_func(ret, name) \
	ret msgpack_unpacker_##name

#define msgpack_unpack_callback(name) \
	msgpack_unpack_##name

#define msgpack_unpack_object object

#define msgpack_unpack_user zone*

struct msgpack_unpacker_context;

static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);

static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);

static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
		const char* data, size_t len, size_t* off);

static inline object msgpack_unpack_init(zone** z)
{ return object(); }

static inline object msgpack_unpack_uint8(zone** z, uint8_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint16(zone** z, uint16_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint32(zone** z, uint32_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_uint64(zone** z, uint64_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }

static inline object msgpack_unpack_int8(zone** z, int8_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int16(zone** z, int16_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int32(zone** z, int32_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_int64(zone** z, int64_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
		else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }

static inline object msgpack_unpack_float(zone** z, float d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }

static inline object msgpack_unpack_double(zone** z, double d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }

static inline object msgpack_unpack_nil(zone** z)
{ object o; o.type = type::NIL; return o; }

static inline object msgpack_unpack_true(zone** z)
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }

static inline object msgpack_unpack_false(zone** z)
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }

static inline object msgpack_unpack_array(zone** z, unsigned int n)
{
	object o;
	o.type = type::ARRAY;
	o.via.container.size = 0;
	o.via.container.ptr = (*z)->malloc_container(n);
	return o;
}

static inline void msgpack_unpack_array_item(zone** z, object* c, object o)
{ c->via.container.ptr[ c->via.container.size++ ] = o; }

static inline object msgpack_unpack_map(zone** z, unsigned int n)
{
	object o;
	o.type = type::MAP;
	o.via.container.size = 0;
	o.via.container.ptr = (*z)->malloc_container(n*2);
	return o;
}

static inline void msgpack_unpack_map_item(zone** z, object* c, object k, object v)
{
	c->via.container.ptr[ c->via.container.size   ] = k;
	c->via.container.ptr[ c->via.container.size+1 ] = v;
	++c->via.container.size;
}

static inline object msgpack_unpack_raw(zone** z, const char* b, const char* p, unsigned int l)
{ object o; o.type = type::RAW; o.via.ref.ptr = p; o.via.ref.size = l; return o; }

#include "msgpack/unpack_template.h"

struct unpacker::context {
	context(zone* z)
	{
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	~context() { }

	int execute(const char* data, size_t len, size_t* off)
	{
		return msgpack_unpacker_execute(&m_ctx, data, len, off);
	}

	object data()
	{
		return msgpack_unpacker_data(&m_ctx);
	}

	void reset()
	{
		zone* z = m_ctx.user;
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	void reset(zone* z)
	{
		msgpack_unpacker_init(&m_ctx);
		m_ctx.user = z;
	}

	zone* user()
	{
		return m_ctx.user;
	}

	void user(zone* z)
	{
		m_ctx.user = z;
	}

private:
	msgpack_unpacker_context m_ctx;

private:
	context();
	context(const context&);
};

unpacker::unpacker() :
	m_buffer(NULL),
	m_used(0),
	m_free(0),
	m_off(0),
	m_zone(new zone()),
	m_ctx(new context(&*m_zone))
{ }

unpacker::~unpacker()
{
	delete m_ctx;
}

void unpacker::expand_buffer(size_t len)
{
	if(m_off == 0) {
		size_t next_size;
		if(m_used != 0) { next_size = (m_used + m_free) * 2; }
		else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
		while(next_size < len + m_used) { next_size *= 2; }

		m_buffer = m_zone->realloc(m_buffer, next_size);
		m_free = next_size - m_used;

	} else {
		size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
		while(next_size < len + m_used - m_off) { next_size *= 2; }

		char* tmp = m_zone->malloc(next_size);
		memcpy(tmp, m_buffer+m_off, m_used-m_off);

		m_buffer = tmp;
		m_used = m_used - m_off;
		m_free = next_size - m_used;
		m_off = 0;
	}
}

bool unpacker::execute()
{
	int ret = m_ctx->execute(m_buffer, m_used, &m_off);
	if(ret < 0) {
		throw unpack_error("parse error");
	} else if(ret == 0) {
		return false;
	} else {
		return true;
	}
}

zone* unpacker::release_zone()
{
	zone* n = new zone();
	std::auto_ptr<zone> old(m_zone.release());
	m_zone.reset(n);

	//std::auto_ptr<zone> old(new zone());
	//m_zone.swap(old);

	// move all bytes in m_buffer to new buffer from the new zone
	if(m_used <= m_off) {
		m_buffer = NULL;
		m_used = 0;
		m_free = 0;
		m_off = 0;
	} else {
		try {
			expand_buffer(0);
		} catch (...) {
			// m_zone.swap(old);
			zone* tmp = old.release();
			old.reset(m_zone.release());
			m_zone.reset(tmp);
			throw;
		}
	}
	m_ctx->user(m_zone.get());
	return old.release();
}

object unpacker::data()
{
	return m_ctx->data();
}

void unpacker::reset()
{
	if(m_off != 0) { delete release_zone(); }
	m_ctx->reset();
}

object unpacker::unpack(const char* data, size_t len, zone& z, size_t* off)
{
	context ctx(&z);
	if(off) {
		int ret = ctx.execute(data, len, off);
		if(ret < 0) {
			throw unpack_error("parse error");
		} else if(ret == 0) {
			throw unpack_error("insufficient bytes");
		}
	} else {
		size_t noff = 0;
		int ret = ctx.execute(data, len, &noff);
		if(ret < 0) {
			throw unpack_error("parse error");
		} else if(ret == 0) {
			throw unpack_error("insufficient bytes");
		} else if(noff < len) {
			throw unpack_error("extra bytes");
		}
	}
	return ctx.data();
}

}  // namespace msgpack

<|endoftext|>


<commit_before>#ifndef __CPREL_CPREL_HH__
#define __CPREL_CPREL_HH__

#include <iostream>
#include <sstream>
#include <climits>

#include <gecode/kernel.hh>
#include <gecode/set.hh> // for channel constraint
#include <cptuple/cptuple.hh> // for the dom constraint
#include <rel/grelation.hh>

using Gecode::Exception;
using Gecode::VarArgArray;
using Gecode::VarArray;

// exceptions
namespace MPG { namespace CPRel {

/// Exception indicating invalid limits
class OutOfLimits : public Exception {
public:
  OutOfLimits(const char* l)
    : Exception(l,"Number out of limits") {}
};
/// Exception indicating empty domain declaration
class VariableEmptyDomain : public Exception {
public:
  VariableEmptyDomain(const char* l)
    : Exception(l,"Attempt to create variable with empty domain") {}
};
/// Exception indicating invalid arity
class ArityMissmatch : public Exception {
public:
  ArityMissmatch(const char* l)
    : Exception(l,"Invalid arity for operation") {}
};
/// Exception indicating invalid permutation
class InvalidPermutation : public Exception {
public:
  InvalidPermutation(const char* l)
    : Exception(l,"Invalid permutation for operation") {}
};
}}

// Variable implementation definition
#include <cprel/varimp.hh>

// Variable definition
#include <cprel/var.hh>

// array traits
namespace MPG {
class CPRelVarArgs; class CPRelVarArray;
}

namespace Gecode {
template<>
class ArrayTraits<Gecode::VarArray<MPG::CPRelVar> > {
public:
  typedef MPG::CPRelVarArray  StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<MPG::CPRelVarArray> {
public:
  typedef MPG::CPRelVarArray  StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<Gecode::VarArgArray<MPG::CPRelVar> > {
public:
  typedef MPG::CPRelVarArgs   StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<MPG::CPRelVarArgs> {
public:
  typedef MPG::CPRelVarArgs  StorageType;
  typedef MPG::CPRelVar      ValueType;
  typedef MPG::CPRelVarArgs  ArgsType;
};

}
// variable arrays
namespace MPG {
class CPRelVarArgs : public VarArgArray<CPRelVar> {
public:
  CPRelVarArgs(void) {}
  explicit CPRelVarArgs(int n) : VarArgArray<CPRelVar>(n) {}
  CPRelVarArgs(const CPRelVarArgs& a) : VarArgArray<CPRelVar>(a) {}
  CPRelVarArgs(const VarArray<CPRelVar>& a) : VarArgArray<CPRelVar>(a) {}
  CPRelVarArgs(Space& home, int n,
               const GRelation& l, const GRelation& u)
    : VarArgArray<CPRelVar>(n) {
    for (int i=0; i<n; i++)
      (*this)[i] = CPRelVar(home,l,u);
  }
};
class CPRelVarArray : public VarArray<CPRelVar> {
public:
  CPRelVarArray(void) {}
  CPRelVarArray(const CPRelVarArray& a)
    : VarArray<CPRelVar>(a) {}
  CPRelVarArray(Space& home, int n, const GRelation& l, const GRelation& u)
    : VarArray<CPRelVar>(home,n) {
    for (int i=0; i<n; i++)
      (*this)[i] = CPRelVar(home,l,u);
  }
};

}

// View implementation
#include <cprel/view.hh>

// Descriptors
#include <bdddomain/perm-descriptor.hh>

/**
 * \defgroup SetProp Set propagators on relations
 *
 * A relation can be seen as a set of tuples. From this point of view different
 * constraints can be defined. These propagators are presented in this module.
 */

/**
 * \defgroup RelProp Basic relation propagators
 *
 * The propagators presented in this module extend common operations on relations
 * to constraints.  As opposed to databases, columns in the relation decission
 * variables are identified by their possition. This is, a relation of arity \a
 * n has columns \f$0,\ldots,n-1\f$ being the column identified with 0 the right
 * most one.
 *
 * As the notion of "colum names" is merely numeric, some of the constraints that
 * work with column information take numbers identifying the columns as parameters.
 * Moreover, constraints like \a join and \a projection rely on some conventions
 * regarding this imput.
 */

/**
 * \defgroup RelBranch Branchers (distribution strategies) on relations
 *
 * This module contains the branchers that can be used on relation domains.
 */

/**
 * \defgroup ChannelProp Channel propagators on relation variables.
 *
 * Constraints that provide interaction between relation
 * decision variables and variables from other constraint systems.
 */

namespace MPG {
/**
 * \brief Posts: \f$ A = B \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void equal(Gecode::Space& home, CPRelVar A, CPRelVar B);

/**
 * \brief Posts: \f$ A = \overline{B} \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void complement(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts: \f$ A \cap B = C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 */
void intersect(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts: \f$ A \cup B = C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 */
void Union(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts: \f$ A \subseteq B \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void subset(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts: \f$ disjoint(A,B)\f$.
 * \ingroup SetProp
 *
 * Enforces that \a A and \a B are two disjoint relations.
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void disjoint(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts the constraint: \f$ \forall t : t\in A \Rightarrow t\in B \iff t \in C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 */
void implies(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts the constraint: \f$ A = B \leftrightarrow_{\text{desc}}\f$.
 * \ingroup RelProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B  a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param desc an object describing the permutation. It represents a map from
 *        columns of \a A to columns of \a B.
 *
 * @see PermDescriptor
 */
void permutation(Gecode::Space& home, CPRelVar A, CPRelVar B,
                 const PermDescriptor& desc);
/**
 * \brief Posts the constraint: \f$ \Pi_{p} A = B \f$.
 * \ingroup RelProp
 *
 * @param p is the number of columns on the right of \a A to project on.
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n-p}\f$
 *
 * For more details see @see MPG::CPRel::Prop::Project::propagate
 */
void projection(Gecode::Space& home, int p, CPRelVar A, CPRelVar B);
/**
 * \brief Posts the constraint: \f$ A\;\bowtie_{j}\;B = C \f$
 * \ingroup RelProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param j is the number of columns on the right of \a A
 * and on the left of \a B to join on.
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{m}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n+m-j}\f$
 */
void join(Gecode::Space& home, CPRelVar A, int j, CPRelVar B, CPRelVar C);
/**
 * \brief Posts the constraint: \f$ R = S\f$
 * \ingroup ChannelProp
 *
 * @param R a unary relation decision variable: \f$A\subseteq\mathcal{U}_{1}\f$
 * @param S a set decision variable.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * is not 1.
 */
void channel(Gecode::Space& home, CPRelVar R, Gecode::SetVar S);
/**
 * \brief Posts the constraint: \f$ t \in R\f$
 * \ingroup ChannelProp
 *
 * @param t a tuple decision variable which domain is a subset of \f$\mathcal{U}_{n}\f$
 * @param R a relation decision variable: \f$R \subseteq \mathcal{U}_{n}\f$.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * and the arity of \a t is not the same.
 */
void included(Gecode::Space& home, CPTupleVar t, CPRelVar R);
/**
 * \brief Posts the constraint: \f$ t \notin R\f$
 * \ingroup ChannelProp
 *
 * @param t a tuple decision variable which domain is a subset of \f$\mathcal{U}_{n}\f$
 * @param R a relation decision variable: \f$R \subseteq \mathcal{U}_{n}\f$.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * and the arity of \a t is not the same.
 */
void excluded(Gecode::Space& home, CPTupleVar t, CPRelVar R);

/// \todo Document!
void follow(Gecode::Space& home, CPRelVar A, int f, CPRelVar B, CPRelVar C);
/**
 * \brief Simple branching on relations.
 * \ingroup RelBranch
 *
 * Branches on relation  \a R by selecting a tuple in it and creating a choice with
 * the tuple as part of the relation for the first alternative and the tuple as
 * excluded from the relation as the second alternative.
 *
 * @param R a relation decision variable.
 *
 */
void branch(Gecode::Home home, CPRelVar R);
}
#endif
<commit_msg>Added documentation for follow<commit_after>#ifndef __CPREL_CPREL_HH__
#define __CPREL_CPREL_HH__

#include <iostream>
#include <sstream>
#include <climits>

#include <gecode/kernel.hh>
#include <gecode/set.hh> // for channel constraint
#include <cptuple/cptuple.hh> // for the dom constraint
#include <rel/grelation.hh>

using Gecode::Exception;
using Gecode::VarArgArray;
using Gecode::VarArray;

// exceptions
namespace MPG { namespace CPRel {

/// Exception indicating invalid limits
class OutOfLimits : public Exception {
public:
  OutOfLimits(const char* l)
    : Exception(l,"Number out of limits") {}
};
/// Exception indicating empty domain declaration
class VariableEmptyDomain : public Exception {
public:
  VariableEmptyDomain(const char* l)
    : Exception(l,"Attempt to create variable with empty domain") {}
};
/// Exception indicating invalid arity
class ArityMissmatch : public Exception {
public:
  ArityMissmatch(const char* l)
    : Exception(l,"Invalid arity for operation") {}
};
/// Exception indicating invalid permutation
class InvalidPermutation : public Exception {
public:
  InvalidPermutation(const char* l)
    : Exception(l,"Invalid permutation for operation") {}
};
}}

// Variable implementation definition
#include <cprel/varimp.hh>

// Variable definition
#include <cprel/var.hh>

// array traits
namespace MPG {
class CPRelVarArgs; class CPRelVarArray;
}

namespace Gecode {
template<>
class ArrayTraits<Gecode::VarArray<MPG::CPRelVar> > {
public:
  typedef MPG::CPRelVarArray  StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<MPG::CPRelVarArray> {
public:
  typedef MPG::CPRelVarArray  StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<Gecode::VarArgArray<MPG::CPRelVar> > {
public:
  typedef MPG::CPRelVarArgs   StorageType;
  typedef MPG::CPRelVar       ValueType;
  typedef MPG::CPRelVarArgs   ArgsType;
};
template<>
class ArrayTraits<MPG::CPRelVarArgs> {
public:
  typedef MPG::CPRelVarArgs  StorageType;
  typedef MPG::CPRelVar      ValueType;
  typedef MPG::CPRelVarArgs  ArgsType;
};

}
// variable arrays
namespace MPG {
class CPRelVarArgs : public VarArgArray<CPRelVar> {
public:
  CPRelVarArgs(void) {}
  explicit CPRelVarArgs(int n) : VarArgArray<CPRelVar>(n) {}
  CPRelVarArgs(const CPRelVarArgs& a) : VarArgArray<CPRelVar>(a) {}
  CPRelVarArgs(const VarArray<CPRelVar>& a) : VarArgArray<CPRelVar>(a) {}
  CPRelVarArgs(Space& home, int n,
               const GRelation& l, const GRelation& u)
    : VarArgArray<CPRelVar>(n) {
    for (int i=0; i<n; i++)
      (*this)[i] = CPRelVar(home,l,u);
  }
};
class CPRelVarArray : public VarArray<CPRelVar> {
public:
  CPRelVarArray(void) {}
  CPRelVarArray(const CPRelVarArray& a)
    : VarArray<CPRelVar>(a) {}
  CPRelVarArray(Space& home, int n, const GRelation& l, const GRelation& u)
    : VarArray<CPRelVar>(home,n) {
    for (int i=0; i<n; i++)
      (*this)[i] = CPRelVar(home,l,u);
  }
};

}

// View implementation
#include <cprel/view.hh>

// Descriptors
#include <bdddomain/perm-descriptor.hh>

/**
 * \defgroup SetProp Set propagators on relations
 *
 * A relation can be seen as a set of tuples. From this point of view different
 * constraints can be defined. These propagators are presented in this module.
 */

/**
 * \defgroup RelProp Basic relation propagators
 *
 * The propagators presented in this module extend common operations on relations
 * to constraints.  As opposed to databases, columns in the relation decission
 * variables are identified by their possition. This is, a relation of arity \a
 * n has columns \f$0,\ldots,n-1\f$ being the column identified with 0 the right
 * most one.
 *
 * As the notion of "colum names" is merely numeric, some of the constraints that
 * work with column information take numbers identifying the columns as parameters.
 * Moreover, constraints like \a join and \a projection rely on some conventions
 * regarding this imput.
 */

/**
 * \defgroup RelBranch Branchers (distribution strategies) on relations
 *
 * This module contains the branchers that can be used on relation domains.
 */

/**
 * \defgroup ChannelProp Channel propagators on relation variables.
 *
 * Constraints that provide interaction between relation
 * decision variables and variables from other constraint systems.
 */

namespace MPG {
/**
 * \brief Posts: \f$ A = B \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 *
 * \see MPG::CPRel::Prop::Equal
 */
void equal(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts: \f$ A = \overline{B} \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void complement(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts: \f$ A \cap B = C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 *
 * \see MPG::CPRel::Prop::Intersect
 */
void intersect(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts: \f$ A \cup B = C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 */
void Union(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts: \f$ A \subseteq B \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void subset(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts: \f$ disjoint(A,B)\f$.
 * \ingroup SetProp
 *
 * Enforces that \a A and \a B are two disjoint relations.
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 */
void disjoint(Gecode::Space& home, CPRelVar A, CPRelVar B);
/**
 * \brief Posts the constraint: \f$ \forall t : t\in A \Rightarrow t\in B \iff t \in C \f$
 * \ingroup SetProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n}\f$
 */
void implies(Gecode::Space& home, CPRelVar A, CPRelVar B, CPRelVar C);
/**
 * \brief Posts the constraint: \f$ A = B \leftrightarrow_{\text{desc}}\f$.
 * \ingroup RelProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B  a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param desc an object describing the permutation. It represents a map from
 *        columns of \a A to columns of \a B.
 *
 * @see PermDescriptor
 */
void permutation(Gecode::Space& home, CPRelVar A, CPRelVar B,
                 const PermDescriptor& desc);
/**
 * \brief Posts the constraint: \f$ \Pi_{p} A = B \f$.
 * \ingroup RelProp
 *
 * @param p is the number of columns on the right of \a A to project on.
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{n-p}\f$
 *
 * @see MPG::CPRel::Prop::Project
 */
void projection(Gecode::Space& home, int p, CPRelVar A, CPRelVar B);
/**
 * \brief Posts the constraint: \f$ A\;\bowtie_{j}\;B = C \f$
 * \ingroup RelProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param j is the number of columns on the right of \a A
 * and on the left of \a B to join on.
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{m}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n+m-j}\f$
 *
 * @see MPG::CPRel::Prop::Join
 */
void join(Gecode::Space& home, CPRelVar A, int j, CPRelVar B, CPRelVar C);
/**
 * \brief Posts the constraint: \f$ A_{\smile_{f}}B = C \f$
 * \ingroup RelProp
 *
 * @param A a relation decision variable: \f$A\subseteq\mathcal{U}_{n}\f$
 * @param f is the number of columns on the right of \a A
 * and on the left of \a B that a match must contain to be consider as a follow.
 * @param B a relation decision variable: \f$B\subseteq\mathcal{U}_{m}\f$
 * @param C a relation decision variable: \f$C\subseteq\mathcal{U}_{n+m-2j}\f$
 *
 * @see MPG::CPRel::Prop::Follow
 */
void follow(Gecode::Space& home, CPRelVar A, int f, CPRelVar B, CPRelVar C);
/**
 * \brief Posts the constraint: \f$ R = S\f$
 * \ingroup ChannelProp
 *
 * @param R a unary relation decision variable: \f$A\subseteq\mathcal{U}_{1}\f$
 * @param S a set decision variable.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * is not 1.
 */
void channel(Gecode::Space& home, CPRelVar R, Gecode::SetVar S);
/**
 * \brief Posts the constraint: \f$ t \in R\f$
 * \ingroup ChannelProp
 *
 * @param t a tuple decision variable which domain is a subset of \f$\mathcal{U}_{n}\f$
 * @param R a relation decision variable: \f$R \subseteq \mathcal{U}_{n}\f$.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * and the arity of \a t is not the same.
 */
void included(Gecode::Space& home, CPTupleVar t, CPRelVar R);
/**
 * \brief Posts the constraint: \f$ t \notin R\f$
 * \ingroup ChannelProp
 *
 * @param t a tuple decision variable which domain is a subset of \f$\mathcal{U}_{n}\f$
 * @param R a relation decision variable: \f$R \subseteq \mathcal{U}_{n}\f$.
 *
 * \warning Throws an exception MPG::CPRel::ArityMissmatch if the arity of \a R
 * and the arity of \a t is not the same.
 */
void excluded(Gecode::Space& home, CPTupleVar t, CPRelVar R);
/**
 * \brief Simple branching on relations.
 * \ingroup RelBranch
 *
 * Branches on relation  \a R by selecting a tuple in it and creating a choice with
 * the tuple as part of the relation for the first alternative and the tuple as
 * excluded from the relation as the second alternative.
 *
 * @param R a relation decision variable.
 *
 */
void branch(Gecode::Home home, CPRelVar R);
}
#endif
<|endoftext|>


<commit_before>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#define SPACE_SCAN_CODE 0x0039

#include "keyboard-layout-manager.h"

#include <string>
#include <cctype>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutManager::Init(Handle<Object> exports, Handle<Object> module) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutManager::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutManager").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutManager::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutManager::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutManager::GetInstalledKeyboardLanguages);
  Nan::SetMethod(proto, "getCurrentKeymap", KeyboardLayoutManager::GetCurrentKeymap);

  module->Set(Nan::New("exports").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_manager, KeyboardLayoutManager::Init)

NAN_METHOD(KeyboardLayoutManager::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutManager *manager = new KeyboardLayoutManager(callback);
  manager->Wrap(info.This());
  return;
}

KeyboardLayoutManager::KeyboardLayoutManager(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutManager::~KeyboardLayoutManager() {
  delete callback;
};

void KeyboardLayoutManager::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName).ToLocalChecked());
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size()).ToLocalChecked());
}

NAN_METHOD(KeyboardLayoutManager::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size()).ToLocalChecked());
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}

struct KeycodeMapEntry {
  UINT scanCode;
  const char *dom3Code;
};

#define USB_KEYMAP_DECLARATION static const KeycodeMapEntry keyCodeMap[] =
#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {win, code}

#include "keycode_converter_data.inc"

Local<Value> CharacterForNativeCode(HKL keyboardLayout, UINT keyCode, UINT scanCode,
                                     BYTE *keyboardState, bool shift, bool altGraph) {
  memset(keyboardState, 0, 256);
  if (shift) {
    keyboardState[VK_SHIFT] = 0x80;
  }

  if (altGraph) {
    keyboardState[VK_MENU] = 0x80;
    keyboardState[VK_CONTROL] = 0x80;
  }

  wchar_t characters[5];
  int count = ToUnicodeEx(keyCode, scanCode, keyboardState, characters, 5, 0, keyboardLayout);

  if (count == -1) { // Dead key
    Local<String> result = Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
    // Clear dead key out of kernel-mode keyboard buffer so subsequent translations are not affected
    UINT spaceKeyCode = MapVirtualKeyEx(SPACE_SCAN_CODE, MAPVK_VSC_TO_VK, keyboardLayout);
    ToUnicodeEx(spaceKeyCode, SPACE_SCAN_CODE, keyboardState, characters, 5, 0, keyboardLayout);
    return result;
  }

  if (count > 0 && !std::iscntrl(characters[0])) {
    return Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
  } else {
    return Nan::Null();
  }
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeymap) {
  BYTE keyboardState[256];
  HKL keyboardLayout = GetKeyboardLayout(0);

  Handle<Object> result = Nan::New<Object>();
  Local<String> unmodifiedKey = Nan::New("unmodified").ToLocalChecked();
  Local<String> withShiftKey = Nan::New("withShift").ToLocalChecked();
  Local<String> withAltGraphKey = Nan::New("withAltGraph").ToLocalChecked();
  Local<String> withAltGraphShiftKey = Nan::New("withAltGraphShift").ToLocalChecked();

  size_t keyCodeMapSize = sizeof(keyCodeMap) / sizeof(keyCodeMap[0]);
  for (size_t i = 0; i < keyCodeMapSize; i++) {
    const char *dom3Code = keyCodeMap[i].dom3Code;
    UINT scanCode = keyCodeMap[i].scanCode;

    if (dom3Code && scanCode > 0x0000) {
      UINT keyCode = MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK, keyboardLayout);

      Local<String> dom3CodeKey = Nan::New(dom3Code).ToLocalChecked();
      Local<Value> unmodified = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, false);
      Local<Value> withShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, false);
      Local<Value> withAltGraph = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, true);
      Local<Value> withAltGraphShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, true);

      if (unmodified->IsString() || withShift->IsString() || withAltGraph->IsString() || withAltGraphShift->IsString()) {
        Local<Object> entry = Nan::New<Object>();
        entry->Set(unmodifiedKey, unmodified);
        entry->Set(withShiftKey, withShift);
        entry->Set(withAltGraphKey, withAltGraph);
        entry->Set(withAltGraphShiftKey, withAltGraphShift);

        result->Set(dom3CodeKey, entry);
      }
    }
  }

  info.GetReturnValue().Set(result);

}
<commit_msg>Don't map dead keys on Windows to avoid dropping dead key state<commit_after>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#define SPACE_SCAN_CODE 0x0039

#include "keyboard-layout-manager.h"

#include <string>
#include <cctype>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutManager::Init(Handle<Object> exports, Handle<Object> module) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutManager::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutManager").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutManager::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutManager::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutManager::GetInstalledKeyboardLanguages);
  Nan::SetMethod(proto, "getCurrentKeymap", KeyboardLayoutManager::GetCurrentKeymap);

  module->Set(Nan::New("exports").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_manager, KeyboardLayoutManager::Init)

NAN_METHOD(KeyboardLayoutManager::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutManager *manager = new KeyboardLayoutManager(callback);
  manager->Wrap(info.This());
  return;
}

KeyboardLayoutManager::KeyboardLayoutManager(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutManager::~KeyboardLayoutManager() {
  delete callback;
};

void KeyboardLayoutManager::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName).ToLocalChecked());
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size()).ToLocalChecked());
}

NAN_METHOD(KeyboardLayoutManager::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size()).ToLocalChecked());
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}

struct KeycodeMapEntry {
  UINT scanCode;
  const char *dom3Code;
};

#define USB_KEYMAP_DECLARATION static const KeycodeMapEntry keyCodeMap[] =
#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {win, code}

#include "keycode_converter_data.inc"

Local<Value> CharacterForNativeCode(HKL keyboardLayout, UINT keyCode, UINT scanCode,
                                     BYTE *keyboardState, bool shift, bool altGraph) {
  memset(keyboardState, 0, 256);
  if (shift) {
    keyboardState[VK_SHIFT] = 0x80;
  }

  if (altGraph) {
    keyboardState[VK_MENU] = 0x80;
    keyboardState[VK_CONTROL] = 0x80;
  }

  wchar_t characters[5];
  int count = ToUnicodeEx(keyCode, scanCode, keyboardState, characters, 5, 0, keyboardLayout);

  // Key code is a dead key on this layout.
  // We check the most significant bit of the key code to avoid calling this
  // method for dead keys, but I'm leaving this to be defensive in case there's
  // something we're not understanding.
  if (count == -1) {
    Local<String> result = Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
    // Clear dead key out of kernel-mode keyboard buffer so subsequent translations are not affected
    UINT spaceKeyCode = MapVirtualKeyEx(SPACE_SCAN_CODE, MAPVK_VSC_TO_VK, keyboardLayout);
    ToUnicodeEx(spaceKeyCode, SPACE_SCAN_CODE, keyboardState, characters, 5, 0, keyboardLayout);
    return result;
  }

  if (count > 0 && !std::iscntrl(characters[0])) {
    return Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
  } else {
    return Nan::Null();
  }
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeymap) {
  BYTE keyboardState[256];
  HKL keyboardLayout = GetKeyboardLayout(0);

  Handle<Object> result = Nan::New<Object>();
  Local<String> unmodifiedKey = Nan::New("unmodified").ToLocalChecked();
  Local<String> withShiftKey = Nan::New("withShift").ToLocalChecked();
  Local<String> withAltGraphKey = Nan::New("withAltGraph").ToLocalChecked();
  Local<String> withAltGraphShiftKey = Nan::New("withAltGraphShift").ToLocalChecked();

  size_t keyCodeMapSize = sizeof(keyCodeMap) / sizeof(keyCodeMap[0]);
  for (size_t i = 0; i < keyCodeMapSize; i++) {
    const char *dom3Code = keyCodeMap[i].dom3Code;
    UINT scanCode = keyCodeMap[i].scanCode;

    if (dom3Code && scanCode > 0x0000) {
      UINT keyCode = MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK, keyboardLayout);

      // If the most significant bit is 1, this is a dead key. Trying to translate it to
      // a character will cause the dead key state to be dropped if the most recently typed
      // key happens to be dead due to a stupid API design in Windows, so we're forced
      // to skip these keys to avoid this bug.
      if (keyCode & (1 << (sizeof(UINT) * 8 - 1))) continue;

      Local<String> dom3CodeKey = Nan::New(dom3Code).ToLocalChecked();
      Local<Value> unmodified = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, false);
      Local<Value> withShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, false);
      Local<Value> withAltGraph = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, true);
      Local<Value> withAltGraphShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, true);

      if (unmodified->IsString() || withShift->IsString() || withAltGraph->IsString() || withAltGraphShift->IsString()) {
        Local<Object> entry = Nan::New<Object>();
        entry->Set(unmodifiedKey, unmodified);
        entry->Set(withShiftKey, withShift);
        entry->Set(withAltGraphKey, withAltGraph);
        entry->Set(withAltGraphShiftKey, withAltGraphShift);

        result->Set(dom3CodeKey, entry);
      }
    }
  }

  info.GetReturnValue().Set(result);

}
<|endoftext|>


<commit_before>/*
 *          Copyright Andrey Semashev 2007 - 2013.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */

#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/format.hpp>
#include <boost/phoenix.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/utility/value_ref.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;

//[ example_extension_formatter_parser_point_definition
struct point
{
    float m_x, m_y;

    point() : m_x(0.0f), m_y(0.0f) {}
    point(float x, float y) : m_x(x), m_y(y) {}
};

template< typename CharT, typename TraitsT >
std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
{
    strm << "(" << p.m_x << ", " << p.m_y << ")";
    return strm;
}
//]

#if 0
//[ example_extension_simple_formatter_factory
void init_factories()
{
    logging::register_simple_formatter_factory< point, char >("Coordinates");
}
//]
#endif

//[ example_extension_custom_formatter_factory
// Custom point formatter
class point_formatter
{
public:
    typedef void result_type;

public:
    explicit point_formatter(std::string const& fmt) : m_format(fmt)
    {
    }

    void operator() (logging::formatting_ostream& strm, logging::value_ref< point > const& value)
    {
        if (value)
        {
            point const& p = value.get();
            m_format % p.m_x % p.m_y;
            strm << m_format;
            m_format.clear();
        }
    }

private:
    boost::format m_format;
};

// Custom point formatter factory
class point_formatter_factory :
    public logging::basic_formatter_factory< char, point >
{
public:
    formatter_type create_formatter(logging::attribute_name const& name, args_map const& args)
    {
        args_map::const_iterator it = args.find("format");
        if (it != args.end())
            return boost::phoenix::bind(point_formatter(it->second), expr::stream, expr::attr< point >(name));
        else
            return expr::stream << expr::attr< point >(name);
    }
};

void init_factories()
{
    logging::register_formatter_factory("Coordinates", boost::make_shared< point_formatter_factory >());
}
//]

void init_logging()
{
    init_factories();

    logging::add_console_log(std::clog, keywords::format = "%TimeStamp% %Coordinates(format=\"{%0.3f; %0.3f}\")% %Message%");

    logging::add_common_attributes();
}

int main(int, char*[])
{
    init_logging();

    src::logger lg;
    BOOST_LOG(lg) << logging::add_value("Coordinates", point(10.5f, 20.2f)) << "Hello, world with coordinates!";

    return 0;
}
<commit_msg>Added a workaround for #9362. Still doesn't compile because of #9363.<commit_after>/*
 *          Copyright Andrey Semashev 2007 - 2013.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */

#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/format.hpp>
#include <boost/phoenix.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/utility/value_ref.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;

//[ example_extension_formatter_parser_point_definition
struct point
{
    float m_x, m_y;

    point() : m_x(0.0f), m_y(0.0f) {}
    point(float x, float y) : m_x(x), m_y(y) {}
};

template< typename CharT, typename TraitsT >
std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
{
    strm << "(" << p.m_x << ", " << p.m_y << ")";
    return strm;
}
//]

#if 0
//[ example_extension_simple_formatter_factory
void init_factories()
{
    logging::register_simple_formatter_factory< point, char >("Coordinates");
}
//]
#endif

//[ example_extension_custom_formatter_factory
// Custom point formatter
class point_formatter
{
public:
    typedef void result_type;

public:
    explicit point_formatter(std::string const& fmt) : m_format(fmt)
    {
    }

    void operator() (logging::formatting_ostream& strm, logging::value_ref< point > const& value) const
    {
        if (value)
        {
            point const& p = value.get();
            m_format % p.m_x % p.m_y;
            strm << m_format;
            m_format.clear();
        }
    }

private:
    mutable boost::format m_format;
};

// Custom point formatter factory
class point_formatter_factory :
    public logging::basic_formatter_factory< char, point >
{
public:
    formatter_type create_formatter(logging::attribute_name const& name, args_map const& args)
    {
        args_map::const_iterator it = args.find("format");
        if (it != args.end())
            return boost::phoenix::bind(point_formatter(it->second), expr::stream, expr::attr< point >(name));
        else
            return expr::stream << expr::attr< point >(name);
    }
};

void init_factories()
{
    logging::register_formatter_factory("Coordinates", boost::make_shared< point_formatter_factory >());
}
//]

void init_logging()
{
    init_factories();

    logging::add_console_log(std::clog, keywords::format = "%TimeStamp% %Coordinates(format=\"{%0.3f; %0.3f}\")% %Message%");

    logging::add_common_attributes();
}

int main(int, char*[])
{
    init_logging();

    src::logger lg;
    BOOST_LOG(lg) << logging::add_value("Coordinates", point(10.5f, 20.2f)) << "Hello, world with coordinates!";

    return 0;
}
<|endoftext|>


<commit_before>/* The MIT License

   Copyright (c) 2013 Adrian Tan <atks@umich.edu>

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#include "normalize.h"

namespace
{

class Igor : Program
{
    public:

    ///////////
    //options//
    ///////////
    std::string input_vcf_file;
    std::string output_vcf_file;
    std::vector<GenomeInterval> intervals;
    std::string ref_fasta_file;
    int32_t window_size;
    bool print;

    ///////
    //i/o//
    ///////
    BCFOrderedReader *odr;
    BCFOrderedWriter *odw;
    bcf1_t *v;

    kstring_t s;
    kstring_t new_alleles;
    kstring_t old_alleles;

    /////////
    //stats//
    /////////
    uint32_t no_variants;

    uint32_t no_lt;    //# left trimmed
    uint32_t no_rt;    //# right trimmed
    uint32_t no_lt_rt; //# left trimmed and right trimmed
    uint32_t no_rt_la; //# right trimmed and left aligned
    uint32_t no_la;    //# left aligned

    uint32_t no_multi_lt;    //# left trimmed
    uint32_t no_multi_rt;    //# right trimmed
    uint32_t no_multi_lt_rt; //# left trimmed and right trimmed
    uint32_t no_multi_rt_la; //# right trimmed and left aligned
    uint32_t no_multi_la;    //# left aligned

    /////////
    //tools//
    /////////
    VariantManip *vm;

    Igor(int argc, char **argv)
    {
        version = "0.5";

        //////////////////////////
        //options initialization//
        //////////////////////////
        try
        {
            std::string desc = "normalizes variants in a VCF file";

            TCLAP::CmdLine cmd(desc, ' ', version);
            VTOutput my; cmd.setOutput(&my);
            TCLAP::ValueArg<std::string> arg_ref_fasta_file("r", "r", "reference sequence fasta file []", true, "", "str", cmd);
            TCLAP::ValueArg<std::string> arg_intervals("i", "i", "intervals []", false, "", "str", cmd);
            TCLAP::ValueArg<std::string> arg_interval_list("I", "I", "file containing list of intervals []", false, "", "file", cmd);
            TCLAP::ValueArg<int32_t> arg_window_size("w", "w", "window size for local sorting of variants [10000]", false, 10000, "integer", cmd);
            TCLAP::SwitchArg arg_quiet("q", "q", "do not print options and summary []", cmd, false);
            TCLAP::ValueArg<std::string> arg_output_vcf_file("o", "o", "output VCF file [-]", false, "-", "str", cmd);
            TCLAP::UnlabeledValueArg<std::string> arg_input_vcf_file("<in.vcf>", "input VCF file", true, "","file", cmd);

            cmd.parse(argc, argv);

            input_vcf_file = arg_input_vcf_file.getValue();
            output_vcf_file = arg_output_vcf_file.getValue();
            parse_intervals(intervals, arg_interval_list.getValue(), arg_intervals.getValue());
            print = !arg_quiet.getValue();
            window_size = arg_window_size.getValue();
            ref_fasta_file = arg_ref_fasta_file.getValue();
        }
        catch (TCLAP::ArgException &e)
        {
            std::cerr << "error: " << e.error() << " for arg " << e.argId() << "\n";
            abort();
        }
    };

    void initialize()
    {
        //////////////////////
        //i/o initialization//
        //////////////////////
        odr = new BCFOrderedReader(input_vcf_file, intervals);

        odw = new BCFOrderedWriter(output_vcf_file, window_size);
        odw->link_hdr(odr->hdr);
        bcf_hdr_append(odw->hdr, "##INFO=<ID=OLD_VARIANT,Number=1,Type=String,Description=\"Original chr:pos:ref:alt encoding\">\n");
        odw->write_hdr();

        s = {0,0,0};
        old_alleles = {0,0,0};
        new_alleles = {0,0,0};

        ////////////////////////
        //stats initialization//
        ////////////////////////
        no_variants = 0;

        no_lt = 0;
        no_rt = 0;
        no_lt_rt = 0;
        no_rt_la = 0;
        no_la = 0;

        no_multi_lt = 0;
        no_multi_rt = 0;
        no_multi_lt_rt = 0;
        no_multi_rt_la = 0;
        no_multi_la = 0;

        ////////////////////////
        //tools initialization//
        ////////////////////////
        vm = new VariantManip(ref_fasta_file);
    }

    void normalize()
    {
        uint32_t left_extended = 0;
        uint32_t left_trimmed = 0;
        uint32_t right_trimmed = 0;

        int32_t ambiguous_variant_types = (VT_MNP | VT_INDEL | VT_CLUMPED);

        v = odw->get_bcf1_from_pool();
        Variant variant;

        while (odr->read(v))
        {
            bcf_unpack(v, BCF_UN_INFO);

            bcf_print(odr->hdr, v);

            int32_t vtype = vm->classify_variant(odr->hdr, v, variant, false); //false argument to ensure no trimming

            if (vtype & ambiguous_variant_types)
            {
                const char* chrom = odr->get_seqname(v);
                uint32_t pos1 = bcf_get_pos1(v);

                std::vector<std::string> alleles;
                for (uint32_t i=0; i<bcf_get_n_allele(v); ++i)
                {
                    char *s = bcf_get_alt(v, i);
                    while (*s)
                    {
                        *s = toupper(*s);
                        ++s;
                    }
                    alleles.push_back(std::string(bcf_get_alt(v, i)));
                }
                left_extended = left_trimmed = right_trimmed = 0;

                vm->right_trim_or_left_extend(alleles, pos1, chrom, left_extended, right_trimmed);
                vm->left_trim(alleles, pos1, left_trimmed);

                if (left_trimmed || left_extended || right_trimmed)
                {
                    old_alleles.l = 0;
                    bcf_variant2string(odw->hdr, v, &old_alleles);
                    bcf_update_info_string(odw->hdr, v, "OLD_VARIANT", old_alleles.s);

                    bcf_set_pos1(v, pos1);
                    new_alleles.l=0;
                    for (size_t i=0; i<alleles.size(); ++i)
                    {
                        if (i) kputc(',', &new_alleles);
                        kputs(alleles[i].c_str(), &new_alleles);
                    }
                    bcf_update_alleles_str(odw->hdr, v, new_alleles.s);

                    if (bcf_get_n_allele(v)==2)
                    {
                        if (left_extended)
                        {
                            if (right_trimmed>left_extended)
                            {
                                ++no_rt_la;
                            }
                            else
                            {
                                ++no_la;
                            }
                        }
                        else
                        {
                            if (left_trimmed && right_trimmed>left_extended)
                            {
                                ++no_lt_rt;
                            }
                            else if (left_trimmed)
                            {
                                ++no_lt;
                            }
                            else if (right_trimmed>left_extended)
                            {
                                ++no_rt;
                            }
                        }
                    }
                    else
                    {
                        if (left_extended)
                        {
                            if (right_trimmed>left_extended)
                            {
                                ++no_multi_rt_la;
                            }
                            else
                            {
                                ++no_multi_la;
                            }
                        }
                        else
                        {
                            if (left_trimmed && right_trimmed>left_extended)
                            {
                                ++no_multi_lt_rt;
                            }
                            else if (left_trimmed)
                            {
                                ++no_multi_lt;
                            }
                            else if (right_trimmed>left_extended)
                            {
                                ++no_multi_rt;
                            }
                        }
                    }
                }
            }

            ++no_variants;

            odw->write(v);
            v = odw->get_bcf1_from_pool();
        }

        odw->close();
        odr->close();
    };

    void print_options()
    {
        if (!print) return;

        std::clog << "normalize v" << version << "\n";
        std::clog << "\n";
        std::clog << "options:     input VCF file        " << input_vcf_file << "\n";
        std::clog << "         [o] output VCF file       " << output_vcf_file << "\n";
        std::clog << "         [w] sorting window size   " << window_size << "\n";
        std::clog << "         [r] reference FASTA file  " << ref_fasta_file << "\n";
        print_int_op("         [i] intervals             ", intervals);
        std::clog << "\n";
    }

    void print_stats()
    {
        if (!print) return;

        int32_t no_biallelic_normalized = no_lt+no_rt+no_lt_rt+no_rt_la+no_la;
        int32_t no_multiallelic_normalized = no_multi_lt+no_multi_rt+no_multi_lt_rt+no_multi_rt_la+no_multi_la;
        int32_t no_normalized = no_biallelic_normalized + no_multiallelic_normalized;

        std::clog << "\n";
        std::clog << "stats: biallelic\n";
        std::clog << "          no. left trimmed                      : " << no_lt << "\n";
        std::clog << "          no. right trimmed                     : " << no_rt << "\n";
        std::clog << "          no. left and right trimmed            : " << no_lt_rt << "\n";
        std::clog << "          no. right trimmed and left aligned    : " << no_rt_la << "\n";
        std::clog << "          no. left aligned                      : " << no_la << "\n";
        std::clog << "\n";
        std::clog << "       total no. biallelic normalized           : " << no_biallelic_normalized << "\n";
        std::clog << "\n";
        std::clog << "       multiallelic\n";
        std::clog << "          no. left trimmed                      : " << no_multi_lt << "\n";
        std::clog << "          no. right trimmed                     : " << no_multi_rt << "\n";
        std::clog << "          no. left and right trimmed            : " << no_multi_lt_rt << "\n";
        std::clog << "          no. right trimmed and left aligned    : " << no_multi_rt_la << "\n";
        std::clog << "          no. left aligned                      : " << no_multi_la << "\n";
        std::clog << "\n";
        std::clog << "       total no. multiallelic normalized        : " << no_multiallelic_normalized << "\n";
        std::clog << "\n";
        std::clog << "       total no. variants normalized            : " << no_normalized << "\n";
        std::clog << "       total no. variants observed              : " << no_variants << "\n";
        std::clog << "\n";
    };

    ~Igor() {};

    private:
};

}

bool normalize(int argc, char ** argv)
{
    Igor igor(argc, argv);
    igor.print_options();
    igor.initialize();
    igor.normalize();
    igor.print_stats();

    return igor.print;
};
<commit_msg>removed debug statements<commit_after>/* The MIT License

   Copyright (c) 2013 Adrian Tan <atks@umich.edu>

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#include "normalize.h"

namespace
{

class Igor : Program
{
    public:

    ///////////
    //options//
    ///////////
    std::string input_vcf_file;
    std::string output_vcf_file;
    std::vector<GenomeInterval> intervals;
    std::string ref_fasta_file;
    int32_t window_size;
    bool print;

    ///////
    //i/o//
    ///////
    BCFOrderedReader *odr;
    BCFOrderedWriter *odw;
    bcf1_t *v;

    kstring_t s;
    kstring_t new_alleles;
    kstring_t old_alleles;

    /////////
    //stats//
    /////////
    uint32_t no_variants;

    uint32_t no_lt;    //# left trimmed
    uint32_t no_rt;    //# right trimmed
    uint32_t no_lt_rt; //# left trimmed and right trimmed
    uint32_t no_rt_la; //# right trimmed and left aligned
    uint32_t no_la;    //# left aligned

    uint32_t no_multi_lt;    //# left trimmed
    uint32_t no_multi_rt;    //# right trimmed
    uint32_t no_multi_lt_rt; //# left trimmed and right trimmed
    uint32_t no_multi_rt_la; //# right trimmed and left aligned
    uint32_t no_multi_la;    //# left aligned

    /////////
    //tools//
    /////////
    VariantManip *vm;

    Igor(int argc, char **argv)
    {
        version = "0.5";

        //////////////////////////
        //options initialization//
        //////////////////////////
        try
        {
            std::string desc = "normalizes variants in a VCF file";

            TCLAP::CmdLine cmd(desc, ' ', version);
            VTOutput my; cmd.setOutput(&my);
            TCLAP::ValueArg<std::string> arg_ref_fasta_file("r", "r", "reference sequence fasta file []", true, "", "str", cmd);
            TCLAP::ValueArg<std::string> arg_intervals("i", "i", "intervals []", false, "", "str", cmd);
            TCLAP::ValueArg<std::string> arg_interval_list("I", "I", "file containing list of intervals []", false, "", "file", cmd);
            TCLAP::ValueArg<int32_t> arg_window_size("w", "w", "window size for local sorting of variants [10000]", false, 10000, "integer", cmd);
            TCLAP::SwitchArg arg_quiet("q", "q", "do not print options and summary []", cmd, false);
            TCLAP::ValueArg<std::string> arg_output_vcf_file("o", "o", "output VCF file [-]", false, "-", "str", cmd);
            TCLAP::UnlabeledValueArg<std::string> arg_input_vcf_file("<in.vcf>", "input VCF file", true, "","file", cmd);

            cmd.parse(argc, argv);

            input_vcf_file = arg_input_vcf_file.getValue();
            output_vcf_file = arg_output_vcf_file.getValue();
            parse_intervals(intervals, arg_interval_list.getValue(), arg_intervals.getValue());
            print = !arg_quiet.getValue();
            window_size = arg_window_size.getValue();
            ref_fasta_file = arg_ref_fasta_file.getValue();
        }
        catch (TCLAP::ArgException &e)
        {
            std::cerr << "error: " << e.error() << " for arg " << e.argId() << "\n";
            abort();
        }
    };

    void initialize()
    {
        //////////////////////
        //i/o initialization//
        //////////////////////
        odr = new BCFOrderedReader(input_vcf_file, intervals);

        odw = new BCFOrderedWriter(output_vcf_file, window_size);
        odw->link_hdr(odr->hdr);
        bcf_hdr_append(odw->hdr, "##INFO=<ID=OLD_VARIANT,Number=1,Type=String,Description=\"Original chr:pos:ref:alt encoding\">\n");
        odw->write_hdr();

        s = {0,0,0};
        old_alleles = {0,0,0};
        new_alleles = {0,0,0};

        ////////////////////////
        //stats initialization//
        ////////////////////////
        no_variants = 0;

        no_lt = 0;
        no_rt = 0;
        no_lt_rt = 0;
        no_rt_la = 0;
        no_la = 0;

        no_multi_lt = 0;
        no_multi_rt = 0;
        no_multi_lt_rt = 0;
        no_multi_rt_la = 0;
        no_multi_la = 0;

        ////////////////////////
        //tools initialization//
        ////////////////////////
        vm = new VariantManip(ref_fasta_file);
    }

    void normalize()
    {
        uint32_t left_extended = 0;
        uint32_t left_trimmed = 0;
        uint32_t right_trimmed = 0;

        int32_t ambiguous_variant_types = (VT_MNP | VT_INDEL | VT_CLUMPED);

        v = odw->get_bcf1_from_pool();
        Variant variant;

        while (odr->read(v))
        {
            bcf_unpack(v, BCF_UN_INFO);
            int32_t vtype = vm->classify_variant(odr->hdr, v, variant, false); //false argument to ensure no trimming

            if (vtype & ambiguous_variant_types)
            {
                const char* chrom = odr->get_seqname(v);
                uint32_t pos1 = bcf_get_pos1(v);

                std::vector<std::string> alleles;
                for (uint32_t i=0; i<bcf_get_n_allele(v); ++i)
                {
                    char *s = bcf_get_alt(v, i);
                    while (*s)
                    {
                        *s = toupper(*s);
                        ++s;
                    }
                    alleles.push_back(std::string(bcf_get_alt(v, i)));
                }
                left_extended = left_trimmed = right_trimmed = 0;

                vm->right_trim_or_left_extend(alleles, pos1, chrom, left_extended, right_trimmed);
                vm->left_trim(alleles, pos1, left_trimmed);

                if (left_trimmed || left_extended || right_trimmed)
                {
                    old_alleles.l = 0;
                    bcf_variant2string(odw->hdr, v, &old_alleles);
                    bcf_update_info_string(odw->hdr, v, "OLD_VARIANT", old_alleles.s);

                    bcf_set_pos1(v, pos1);
                    new_alleles.l=0;
                    for (size_t i=0; i<alleles.size(); ++i)
                    {
                        if (i) kputc(',', &new_alleles);
                        kputs(alleles[i].c_str(), &new_alleles);
                    }
                    bcf_update_alleles_str(odw->hdr, v, new_alleles.s);

                    if (bcf_get_n_allele(v)==2)
                    {
                        if (left_extended)
                        {
                            if (right_trimmed>left_extended)
                            {
                                ++no_rt_la;
                            }
                            else
                            {
                                ++no_la;
                            }
                        }
                        else
                        {
                            if (left_trimmed && right_trimmed>left_extended)
                            {
                                ++no_lt_rt;
                            }
                            else if (left_trimmed)
                            {
                                ++no_lt;
                            }
                            else if (right_trimmed>left_extended)
                            {
                                ++no_rt;
                            }
                        }
                    }
                    else
                    {
                        if (left_extended)
                        {
                            if (right_trimmed>left_extended)
                            {
                                ++no_multi_rt_la;
                            }
                            else
                            {
                                ++no_multi_la;
                            }
                        }
                        else
                        {
                            if (left_trimmed && right_trimmed>left_extended)
                            {
                                ++no_multi_lt_rt;
                            }
                            else if (left_trimmed)
                            {
                                ++no_multi_lt;
                            }
                            else if (right_trimmed>left_extended)
                            {
                                ++no_multi_rt;
                            }
                        }
                    }
                }
            }

            ++no_variants;

            odw->write(v);
            v = odw->get_bcf1_from_pool();
        }

        odw->close();
        odr->close();
    };

    void print_options()
    {
        if (!print) return;

        std::clog << "normalize v" << version << "\n";
        std::clog << "\n";
        std::clog << "options:     input VCF file        " << input_vcf_file << "\n";
        std::clog << "         [o] output VCF file       " << output_vcf_file << "\n";
        std::clog << "         [w] sorting window size   " << window_size << "\n";
        std::clog << "         [r] reference FASTA file  " << ref_fasta_file << "\n";
        print_int_op("         [i] intervals             ", intervals);
        std::clog << "\n";
    }

    void print_stats()
    {
        if (!print) return;

        int32_t no_biallelic_normalized = no_lt+no_rt+no_lt_rt+no_rt_la+no_la;
        int32_t no_multiallelic_normalized = no_multi_lt+no_multi_rt+no_multi_lt_rt+no_multi_rt_la+no_multi_la;
        int32_t no_normalized = no_biallelic_normalized + no_multiallelic_normalized;

        std::clog << "\n";
        std::clog << "stats: biallelic\n";
        std::clog << "          no. left trimmed                      : " << no_lt << "\n";
        std::clog << "          no. right trimmed                     : " << no_rt << "\n";
        std::clog << "          no. left and right trimmed            : " << no_lt_rt << "\n";
        std::clog << "          no. right trimmed and left aligned    : " << no_rt_la << "\n";
        std::clog << "          no. left aligned                      : " << no_la << "\n";
        std::clog << "\n";
        std::clog << "       total no. biallelic normalized           : " << no_biallelic_normalized << "\n";
        std::clog << "\n";
        std::clog << "       multiallelic\n";
        std::clog << "          no. left trimmed                      : " << no_multi_lt << "\n";
        std::clog << "          no. right trimmed                     : " << no_multi_rt << "\n";
        std::clog << "          no. left and right trimmed            : " << no_multi_lt_rt << "\n";
        std::clog << "          no. right trimmed and left aligned    : " << no_multi_rt_la << "\n";
        std::clog << "          no. left aligned                      : " << no_multi_la << "\n";
        std::clog << "\n";
        std::clog << "       total no. multiallelic normalized        : " << no_multiallelic_normalized << "\n";
        std::clog << "\n";
        std::clog << "       total no. variants normalized            : " << no_normalized << "\n";
        std::clog << "       total no. variants observed              : " << no_variants << "\n";
        std::clog << "\n";
    };

    ~Igor() {};

    private:
};

}

bool normalize(int argc, char ** argv)
{
    Igor igor(argc, argv);
    igor.print_options();
    igor.initialize();
    igor.normalize();
    igor.print_stats();

    return igor.print;
};
<|endoftext|>


<commit_before>//===--- Tweak.cpp -----------------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Tweak.h"
#include "Logger.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
#include <functional>
#include <memory>

LLVM_INSTANTIATE_REGISTRY(llvm::Registry<clang::clangd::Tweak>);

namespace clang {
namespace clangd {

/// A handy typedef to save some typing.
typedef llvm::Registry<Tweak> TweakRegistry;

namespace {
/// Asserts invariants on TweakRegistry. No-op with assertion disabled.
void validateRegistry() {
#ifndef NDEBUG
  llvm::StringSet<> Seen;
  for (const auto &E : TweakRegistry::entries()) {
    // REGISTER_TWEAK ensures E.getName() is equal to the tweak class name.
    // We check that id() matches it.
    assert(E.instantiate()->id() == E.getName() &&
           "id should be equal to class name");
    assert(Seen.try_emplace(E.getName()).second && "duplicate check id");
  }
#endif
}
} // namespace

std::vector<std::unique_ptr<Tweak>> prepareTweaks(const Tweak::Selection &S) {
  validateRegistry();

  std::vector<std::unique_ptr<Tweak>> Available;
  for (const auto &E : TweakRegistry::entries()) {
    std::unique_ptr<Tweak> T = E.instantiate();
    if (!T->prepare(S))
      continue;
    Available.push_back(std::move(T));
  }
  // Ensure deterministic order of the results.
  llvm::sort(Available,
             [](const std::unique_ptr<Tweak> &L,
                const std::unique_ptr<Tweak> &R) { return L->id() < R->id(); });
  return Available;
}

llvm::Expected<std::unique_ptr<Tweak>> prepareTweak(TweakID ID,
                                                    const Tweak::Selection &S) {
  auto It = llvm::find_if(
      TweakRegistry::entries(),
      [ID](const TweakRegistry::entry &E) { return E.getName() == ID; });
  if (It == TweakRegistry::end())
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "id of the tweak is invalid");
  std::unique_ptr<Tweak> T = It->instantiate();
  if (!T->prepare(S))
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "failed to prepare() a check");
  return std::move(T);
}

} // namespace clangd
} // namespace clang
<commit_msg>[clangd] Remove extra ';' to fix -Wpedantic warning. NFC<commit_after>//===--- Tweak.cpp -----------------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Tweak.h"
#include "Logger.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
#include <functional>
#include <memory>

LLVM_INSTANTIATE_REGISTRY(llvm::Registry<clang::clangd::Tweak>)

namespace clang {
namespace clangd {

/// A handy typedef to save some typing.
typedef llvm::Registry<Tweak> TweakRegistry;

namespace {
/// Asserts invariants on TweakRegistry. No-op with assertion disabled.
void validateRegistry() {
#ifndef NDEBUG
  llvm::StringSet<> Seen;
  for (const auto &E : TweakRegistry::entries()) {
    // REGISTER_TWEAK ensures E.getName() is equal to the tweak class name.
    // We check that id() matches it.
    assert(E.instantiate()->id() == E.getName() &&
           "id should be equal to class name");
    assert(Seen.try_emplace(E.getName()).second && "duplicate check id");
  }
#endif
}
} // namespace

std::vector<std::unique_ptr<Tweak>> prepareTweaks(const Tweak::Selection &S) {
  validateRegistry();

  std::vector<std::unique_ptr<Tweak>> Available;
  for (const auto &E : TweakRegistry::entries()) {
    std::unique_ptr<Tweak> T = E.instantiate();
    if (!T->prepare(S))
      continue;
    Available.push_back(std::move(T));
  }
  // Ensure deterministic order of the results.
  llvm::sort(Available,
             [](const std::unique_ptr<Tweak> &L,
                const std::unique_ptr<Tweak> &R) { return L->id() < R->id(); });
  return Available;
}

llvm::Expected<std::unique_ptr<Tweak>> prepareTweak(TweakID ID,
                                                    const Tweak::Selection &S) {
  auto It = llvm::find_if(
      TweakRegistry::entries(),
      [ID](const TweakRegistry::entry &E) { return E.getName() == ID; });
  if (It == TweakRegistry::end())
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "id of the tweak is invalid");
  std::unique_ptr<Tweak> T = It->instantiate();
  if (!T->prepare(S))
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "failed to prepare() a check");
  return std::move(T);
}

} // namespace clangd
} // namespace clang
<|endoftext|>