<commit_before>//
//  Shader.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/02/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Shader.hpp"

#include <stdlib.h>
#include <stdio.h>

using namespace OpenGL;

namespace {
	Shader *bound_shader = nullptr;
}

GLuint Shader::compile_shader(const char *source, GLenum type)
{
	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);

#if defined(DEBUG)
	GLint isCompiled = 0;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
	if(isCompiled == GL_FALSE)
	{
		GLint logLength;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
		if(logLength > 0) {
			GLchar *log = (GLchar *)malloc((size_t)logLength);
			glGetShaderInfoLog(shader, logLength, &logLength, log);
			printf("Compile log:\n%s\n", log);
			free(log);
		}

		throw (type == GL_VERTEX_SHADER) ? VertexShaderCompilationError : FragmentShaderCompilationError;
	}
#endif

	return shader;
}

Shader::Shader(const char *vertex_shader, const char *fragment_shader, const AttributeBinding *attribute_bindings)
{
	_shader_program = glCreateProgram();
	GLuint vertex = compile_shader(vertex_shader, GL_VERTEX_SHADER);
	GLuint fragment = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);

	glAttachShader(_shader_program, vertex);
	glAttachShader(_shader_program, fragment);

	if(attribute_bindings)
	{
		while(attribute_bindings->name)
		{
			glBindAttribLocation(_shader_program, attribute_bindings->index, attribute_bindings->name);
			attribute_bindings++;
		}
	}

	glLinkProgram(_shader_program);

#if defined(DEBUG)
	GLint didLink = 0;
	glGetProgramiv(_shader_program, GL_LINK_STATUS, &didLink);
	if(didLink == GL_FALSE)
	{
		GLint logLength;
		glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &logLength);
		if(logLength > 0) {
			GLchar *log = (GLchar *)malloc((size_t)logLength);
			glGetProgramInfoLog(_shader_program, logLength, &logLength, log);
			printf("Link log:\n%s\n", log);
			free(log);
		}
		throw ProgramLinkageError;
	}
#endif
}

Shader::~Shader()
{
	if(bound_shader == this) Shader::unbind();
	glDeleteProgram(_shader_program);
}

void Shader::bind()
{
	if(bound_shader != this)
	{
		glUseProgram(_shader_program);
		bound_shader = this;
	}
	flush_functions();
}

void Shader::unbind()
{
	bound_shader = nullptr;
	glUseProgram(0);
}

GLint Shader::get_attrib_location(const GLchar *name)
{
	return glGetAttribLocation(_shader_program, name);
}

GLint Shader::get_uniform_location(const GLchar *name)
{
	return glGetUniformLocation(_shader_program, name);
}

void Shader::enable_vertex_attribute_with_pointer(const char *name, GLint size, GLenum type, GLboolean normalised, GLsizei stride, const GLvoid *pointer, GLuint divisor)
{
	GLint location = get_attrib_location(name);
	glEnableVertexAttribArray((GLuint)location);
	glVertexAttribPointer((GLuint)location, size, type, normalised, stride, pointer);
	glVertexAttribDivisor((GLuint)location, divisor);
}

// The various set_uniforms...
#define location() glGetUniformLocation(_shader_program, name.c_str())
void Shader::set_uniform(const std::string &name, GLint value)
{
	enqueue_function([name, value, this] {
		glUniform1i(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value)
{
	enqueue_function([name, value, this] {
		glUniform1ui(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value)
{
	enqueue_function([name, value, this] {
		glUniform1f(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2i(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2f(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2ui(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2, GLint value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3i(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2, GLfloat value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3f(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2, GLuint value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3ui(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2, GLint value3, GLint value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4i(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2, GLfloat value3, GLfloat value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4f(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2, GLuint value3, GLuint value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4ui(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLint *values)
{
	enqueue_function([name, size, count, values, this] {
		switch(size)
		{
			case 1: glUniform1iv(location(), count, values);	break;
			case 2: glUniform2iv(location(), count, values);	break;
			case 3: glUniform3iv(location(), count, values);	break;
			case 4: glUniform4iv(location(), count, values);	break;
		}
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLfloat *values)
{
	enqueue_function([name, size, count, values, this] {
		switch(size)
		{
			case 1: glUniform1fv(location(), count, values);	break;
			case 2: glUniform2fv(location(), count, values);	break;
			case 3: glUniform3fv(location(), count, values);	break;
			case 4: glUniform4fv(location(), count, values);	break;
		}
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLuint *values)
{
	enqueue_function([name, size, count, values, this] {
		switch(size)
		{
			case 1: glUniform1uiv(location(), count, values);	break;
			case 2: glUniform2uiv(location(), count, values);	break;
			case 3: glUniform3uiv(location(), count, values);	break;
			case 4: glUniform4uiv(location(), count, values);	break;
		}
	});
}

void Shader::set_uniform_matrix(const std::string &name, GLint size, bool transpose, const GLfloat *values)
{
	set_uniform_matrix(name, size, 1, transpose, values);
}

void Shader::set_uniform_matrix(const std::string &name, GLint size, GLsizei count, bool transpose, const GLfloat *values)
{
	enqueue_function([name, size, count, transpose, values, this] {
	GLboolean glTranspose = transpose ? GL_TRUE : GL_FALSE;
		switch(size)
		{
			case 2: glUniformMatrix2fv(location(), count, glTranspose, values);	break;
			case 3: glUniformMatrix3fv(location(), count, glTranspose, values);	break;
			case 4: glUniformMatrix4fv(location(), count, glTranspose, values);	break;
		}
	});
}

void Shader::enqueue_function(std::function<void(void)> function)
{
	_enqueued_functions.push_back(function);
}

void Shader::flush_functions()
{
	for(std::function<void(void)> function : _enqueued_functions)
	{
		function();
	}
	_enqueued_functions.clear();
}
<commit_msg>Ensured `values` aren't dangling pointers.<commit_after>//
//  Shader.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/02/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Shader.hpp"

#include <stdlib.h>
#include <stdio.h>

using namespace OpenGL;

namespace {
	Shader *bound_shader = nullptr;
}

GLuint Shader::compile_shader(const char *source, GLenum type)
{
	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);

#if defined(DEBUG)
	GLint isCompiled = 0;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
	if(isCompiled == GL_FALSE)
	{
		GLint logLength;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
		if(logLength > 0) {
			GLchar *log = (GLchar *)malloc((size_t)logLength);
			glGetShaderInfoLog(shader, logLength, &logLength, log);
			printf("Compile log:\n%s\n", log);
			free(log);
		}

		throw (type == GL_VERTEX_SHADER) ? VertexShaderCompilationError : FragmentShaderCompilationError;
	}
#endif

	return shader;
}

Shader::Shader(const char *vertex_shader, const char *fragment_shader, const AttributeBinding *attribute_bindings)
{
	_shader_program = glCreateProgram();
	GLuint vertex = compile_shader(vertex_shader, GL_VERTEX_SHADER);
	GLuint fragment = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);

	glAttachShader(_shader_program, vertex);
	glAttachShader(_shader_program, fragment);

	if(attribute_bindings)
	{
		while(attribute_bindings->name)
		{
			glBindAttribLocation(_shader_program, attribute_bindings->index, attribute_bindings->name);
			attribute_bindings++;
		}
	}

	glLinkProgram(_shader_program);

#if defined(DEBUG)
	GLint didLink = 0;
	glGetProgramiv(_shader_program, GL_LINK_STATUS, &didLink);
	if(didLink == GL_FALSE)
	{
		GLint logLength;
		glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &logLength);
		if(logLength > 0) {
			GLchar *log = (GLchar *)malloc((size_t)logLength);
			glGetProgramInfoLog(_shader_program, logLength, &logLength, log);
			printf("Link log:\n%s\n", log);
			free(log);
		}
		throw ProgramLinkageError;
	}
#endif
}

Shader::~Shader()
{
	if(bound_shader == this) Shader::unbind();
	glDeleteProgram(_shader_program);
}

void Shader::bind()
{
	if(bound_shader != this)
	{
		glUseProgram(_shader_program);
		bound_shader = this;
	}
	flush_functions();
}

void Shader::unbind()
{
	bound_shader = nullptr;
	glUseProgram(0);
}

GLint Shader::get_attrib_location(const GLchar *name)
{
	return glGetAttribLocation(_shader_program, name);
}

GLint Shader::get_uniform_location(const GLchar *name)
{
	return glGetUniformLocation(_shader_program, name);
}

void Shader::enable_vertex_attribute_with_pointer(const char *name, GLint size, GLenum type, GLboolean normalised, GLsizei stride, const GLvoid *pointer, GLuint divisor)
{
	GLint location = get_attrib_location(name);
	glEnableVertexAttribArray((GLuint)location);
	glVertexAttribPointer((GLuint)location, size, type, normalised, stride, pointer);
	glVertexAttribDivisor((GLuint)location, divisor);
}

// The various set_uniforms...
GLint fglGetUniformLocation(GLuint program, const GLchar *name)
{
	GLint result = glGetUniformLocation(program, name);
	printf("Resolved %s to %d\n", name, result);
	return result;
}
#define location() fglGetUniformLocation(_shader_program, name.c_str())
void Shader::set_uniform(const std::string &name, GLint value)
{
	enqueue_function([name, value, this] {
		glUniform1i(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value)
{
	enqueue_function([name, value, this] {
		glUniform1ui(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value)
{
	enqueue_function([name, value, this] {
		glUniform1f(location(), value);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2i(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2f(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2)
{
	enqueue_function([name, value1, value2, this] {
		glUniform2ui(location(), value1, value2);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2, GLint value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3i(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2, GLfloat value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3f(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2, GLuint value3)
{
	enqueue_function([name, value1, value2, value3, this] {
		glUniform3ui(location(), value1, value2, value3);
	});
}

void Shader::set_uniform(const std::string &name, GLint value1, GLint value2, GLint value3, GLint value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4i(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2, GLfloat value3, GLfloat value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4f(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLuint value1, GLuint value2, GLuint value3, GLuint value4)
{
	enqueue_function([name, value1, value2, value3, value4, this] {
		glUniform4ui(location(), value1, value2, value3, value4);
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLint *values)
{
	GLint *values_copy = new GLint[count];
	memcpy(values_copy, values, sizeof(GLint) * (size_t)count);
	enqueue_function([name, size, count, values_copy, this] {
		switch(size)
		{
			case 1: glUniform1iv(location(), count, values_copy);	break;
			case 2: glUniform2iv(location(), count, values_copy);	break;
			case 3: glUniform3iv(location(), count, values_copy);	break;
			case 4: glUniform4iv(location(), count, values_copy);	break;
		}
		delete[] values_copy;
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLfloat *values)
{
	GLfloat *values_copy = new GLfloat[count];
	memcpy(values_copy, values, sizeof(GLfloat) * (size_t)count);
	enqueue_function([name, size, count, values_copy, this] {
		switch(size)
		{
			case 1: glUniform1fv(location(), count, values_copy);	break;
			case 2: glUniform2fv(location(), count, values_copy);	break;
			case 3: glUniform3fv(location(), count, values_copy);	break;
			case 4: glUniform4fv(location(), count, values_copy);	break;
		}
		delete[] values_copy;
	});
}

void Shader::set_uniform(const std::string &name, GLint size, GLsizei count, const GLuint *values)
{
	GLuint *values_copy = new GLuint[count];
	memcpy(values_copy, values, sizeof(GLuint) * (size_t)count);
	enqueue_function([name, size, count, values_copy, this] {
		switch(size)
		{
			case 1: glUniform1uiv(location(), count, values_copy);	break;
			case 2: glUniform2uiv(location(), count, values_copy);	break;
			case 3: glUniform3uiv(location(), count, values_copy);	break;
			case 4: glUniform4uiv(location(), count, values_copy);	break;
		}
		delete[] values_copy;
	});
}

void Shader::set_uniform_matrix(const std::string &name, GLint size, bool transpose, const GLfloat *values)
{
	set_uniform_matrix(name, size, 1, transpose, values);
}

void Shader::set_uniform_matrix(const std::string &name, GLint size, GLsizei count, bool transpose, const GLfloat *values)
{
	GLfloat *values_copy = new GLfloat[count*size];
	memcpy(values_copy, values, sizeof(GLfloat) * (size_t)count * (size_t)size);
	enqueue_function([name, size, count, transpose, values_copy, this] {
		GLboolean glTranspose = transpose ? GL_TRUE : GL_FALSE;
		switch(size)
		{
			case 2: glUniformMatrix2fv(location(), count, glTranspose, values_copy);	break;
			case 3: glUniformMatrix3fv(location(), count, glTranspose, values_copy);	break;
			case 4: glUniformMatrix4fv(location(), count, glTranspose, values_copy);	break;
		}
		delete[] values_copy;
	});
}

void Shader::enqueue_function(std::function<void(void)> function)
{
	_enqueued_functions.push_back(function);
}

void Shader::flush_functions()
{
	for(std::function<void(void)> function : _enqueued_functions)
	{
		function();
	}
	_enqueued_functions.clear();
}
<|endoftext|>


<commit_before>//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Author: Edward Yunkai Cui
// Description: Those classes defined in this file are used by the
//              command manager in the world plugin
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifndef _GAZEBO_COMMAND_MANAGEMENT_HH_
#define _GAZEBO_COMMAND_MANAGEMENT_HH_

#include <boost/shared_ptr.hpp>

#include "command_message.pb.h"

using std::string;
using std::vector;
/// Smart pointer of CommandMessage object
typedef boost::shared_ptr<command_message::msgs::CommandMessage> CommandPtr;

namespace gazebo{
class SmoresModule;
/// Smart pointer of the SmoresModule object
typedef boost::shared_ptr<SmoresModule> SmoresModulePtr;
/// A data structure that stores special command message
//! Used by WorldPlugin, which basically specify connect or disconnect
class SpecialCommand
{
 public:
  /// Constructor
  /*!
    \param commandtype An integer which indicate what type of command this is
                       , see CommandType
    \param modelname1 Name of the first module
    \param modelname2 Name of the second module
    \param node1 An integer indicates the id of the node of the first module
    \param node2 An integer indicates the id of the node of the second module
  */
  SpecialCommand(int commandtype, string modelname1, string modelname2,
      int node1, int node2);
  /// Constructor
  /*!
    \param commandtype An integer which indicate what type of command this is
                       , see CommandType
  */
  SpecialCommand(int commandtype);
  /// Constructor
  SpecialCommand();
  /// Destructor
  ~SpecialCommand();
  /// CommandType: 0 no special command; 1 connect; 2 disconnect
  int CommandType;
  /// Name of the first module
  string Module1;
  /// Name of the second module
  string Module2;
  /// Node id of the first module
  int Node1;
  /// Node id of the second module
  int Node2;
}; // class SpecialCommand
/// A data structure that stores normal command message
class CommandPro  // abbr for Command protocol
{
 public:
  /// Constructor
  CommandPro();
  /// Constructor
  //! \param command A smart pointer of the CommandMessage object
  CommandPro(CommandPtr command);
  /// Constructor
  /*!
    \param command A smart pointer of the CommandMessage object
    \param timer Timer of the time-based command, unit: msec
  */
  CommandPro(CommandPtr command, unsigned int timer);
  /// Destructor
  ~CommandPro();
  /// Set a timer for the current command
  //! \param timer A timer, unit: msec
  void SetTimer(unsigned int timer);
  /// Set condition string of the current command
  //! \param condition Condition string
  void SetCondition(string condition);
  /// Set dependency string of the current command
  //! \param dependency Dependency string
  void SetDependency(string dependency);
  /// Make current command a special command
  //! \param specialcommand A specialcommand object
  void SetSpecialCommand(SpecialCommand specialcommand);
  /// A pointer of the CommandMessage object
  CommandPtr ActualCommandMessage;
  /// Flag indicates whether the current command is a time based command
  bool TimeBased;
  /// Timer of the current command, unit: msec
  unsigned int TimeInterval;  // Millisecond
  /// Flag indicates whether this command has a condition
  bool ConditionCommand;
  /// The condition string
  string ConditionID;
  /// Flag indicates whether this command has a dependency
  bool ConditionOnOtherCommand;
  /// The dependency string
  string Dependency;
  /// Flag indicates whether this command is a special command
  bool SpecialCommandFlag;
  /// Special command object
  SpecialCommand Command;
}; // class CommandPro
/// A class that used to manage the commands for each module
//! Used in the command execution
class ModuleCommands
{
 public:
  /// Constructor
  //! \param which_module Pointer of the parent SmoresModule object
  ModuleCommands(SmoresModulePtr which_module);
  /// Destructor
  ~ModuleCommands();
  /// Pointer of the parent SmoresModule object
  SmoresModulePtr WhichModule;
  /// The vector of command array
  vector<CommandPro> CommandSquence;
  /// The indicator of whether a command has been finished
  bool FinishedFlag;
  /// The indicator of whether a command has been received by model
  bool ReceivedFlag;
  /// The indicator of whether a command has been executing
  bool ExecutionFlag;
}; // class ModuleCommands
}
#endif<commit_msg>Updated the documentations<commit_after>//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Author: Edward Yunkai Cui
// Description: Those classes defined in this file are used by the
//              command manager in the world plugin
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifndef _GAZEBO_COMMAND_MANAGEMENT_HH_
#define _GAZEBO_COMMAND_MANAGEMENT_HH_

#include <boost/shared_ptr.hpp>

#include "command_message.pb.h"

using std::string;
using std::vector;
/// Smart pointer of CommandMessage object
typedef boost::shared_ptr<command_message::msgs::CommandMessage> CommandPtr;

namespace gazebo{
class SmoresModule;
/// Smart pointer of the SmoresModule object
typedef boost::shared_ptr<SmoresModule> SmoresModulePtr;
/// A data structure that stores special command message
//! Used by WorldPlugin, which basically specify connect or disconnect
class SpecialCommand
{
 public:
  /// Constructor
  /*!
    \param commandtype An integer which indicate what type of command this is
                       , see CommandType
    \param modelname1 Name of the first module
    \param modelname2 Name of the second module
    \param node1 An integer indicates the id of the node of the first module
    \param node2 An integer indicates the id of the node of the second module
  */
  SpecialCommand(int commandtype, string modelname1, string modelname2,
      int node1, int node2);
  /// Constructor
  /*!
    \param commandtype An integer which indicate what type of command this is
                       , see CommandType
  */
  SpecialCommand(int commandtype);
  /// Constructor
  SpecialCommand();
  /// Destructor
  ~SpecialCommand();
  /// CommandType: 0 no special command; 1 connect; 2 disconnect
  int CommandType;
  /// Name of the first module
  string Module1;
  /// Name of the second module
  string Module2;
  /// Node id of the first module
  int Node1;
  /// Node id of the second module
  int Node2;
}; // class SpecialCommand
/// A data structure that stores normal command message
class CommandPro  // abbr for Command protocol
{
 public:
  /// Constructor
  CommandPro();
  /// Constructor
  /*! \param command A smart pointer of the CommandMessage object */
  CommandPro(CommandPtr command);
  /// Constructor
  /*!
    \param command A smart pointer of the CommandMessage object
    \param timer Timer of the time-based command, unit: msec
  */
  CommandPro(CommandPtr command, unsigned int timer);
  /// Destructor
  ~CommandPro();
  /// Set a timer for the current command
  /*! \param timer A timer, unit: msec */
  void SetTimer(unsigned int timer);
  /// Set condition string of the current command
  /*! \param condition Condition string */
  void SetCondition(string condition);
  /// Set dependency string of the current command
  /*! \param dependency Dependency string */
  void SetDependency(string dependency);
  /// Make current command a special command
  /*! \param specialcommand A specialcommand object */
  void SetSpecialCommand(SpecialCommand specialcommand);
  /// A pointer of the CommandMessage object
  CommandPtr ActualCommandMessage;
  /// Flag indicates whether the current command is a time based command
  bool TimeBased;
  /// Timer of the current command, unit: msec
  unsigned int TimeInterval;  // Millisecond
  /// Flag indicates whether this command has a condition
  bool ConditionCommand;
  /// The condition string
  string ConditionID;
  /// Flag indicates whether this command has a dependency
  bool ConditionOnOtherCommand;
  /// The dependency string
  string Dependency;
  /// Flag indicates whether this command is a special command
  bool SpecialCommandFlag;
  /// Special command object
  SpecialCommand Command;
}; // class CommandPro
/// A class that used to manage the commands for each module
//! Used in the command execution
class ModuleCommands
{
 public:
  /// Constructor
  /*! \param which_module Pointer of the parent SmoresModule object */
  ModuleCommands(SmoresModulePtr which_module);
  /// Destructor
  ~ModuleCommands();
  /// Pointer of the parent SmoresModule object
  SmoresModulePtr WhichModule;
  /// The vector of command array
  vector<CommandPro> CommandSquence;
  /// The indicator of whether a command has been finished
  bool FinishedFlag;
  /// The indicator of whether a command has been received by model
  bool ReceivedFlag;
  /// The indicator of whether a command has been executing
  bool ExecutionFlag;
}; // class ModuleCommands
}
#endif<|endoftext|>


<commit_before>/**
 *  @author Koen Wolters <koen.wolters@cern.ch>
 *  @author Daniel Hynds <daniel.hynds@cern.ch>
 */

#ifndef ALLPIX_MODULE_MANAGER_H
#define ALLPIX_MODULE_MANAGER_H

#include <list>
#include <map>
#include <memory>
#include <queue>

#include "../config/Configuration.hpp"
#include "Module.hpp"
#include "core/config/Configuration.hpp"

namespace allpix {

    class ConfigManager;
    class Messenger;
    class GeometryManager;

    class ModuleManager {
    public:
        // Constructor and destructors
        ModuleManager();
        virtual ~ModuleManager();

        // Disallow copy
        ModuleManager(const ModuleManager&) = delete;
        ModuleManager& operator=(const ModuleManager&) = delete;

        // Load modules
        virtual void load(Messenger* messenger, ConfigManager* conf_manager, GeometryManager* geo_manager);

        // Initialize modules (pre-run)
        virtual void init();

        // Run modules
        virtual void run();

        // Finalize modules (post-run)
        virtual void finalize();

    protected:
        using ModuleList = std::list<std::unique_ptr<Module>>;
        using IdentifierToModuleMap = std::map<ModuleIdentifier, ModuleList::iterator>;
        using ModuleToIdentifierMap = std::map<Module*, ModuleIdentifier>;

        // Add module to run queue
        void add_to_run_queue(Module*);

        // get module identifier
        ModuleIdentifier get_identifier_from_module(Module*);

        // Create modules from the loaded library
        std::vector<std::pair<ModuleIdentifier, Module*>> createModules(Configuration, void*);
        std::vector<std::pair<ModuleIdentifier, Module*>> createModulesPerDetector(Configuration, void*);
        void check_module_detector(const std::string&, Module*, const Detector*);

        // Modules and identifiers converters
        ModuleList modules_;
        IdentifierToModuleMap id_to_module_;
        ModuleToIdentifierMap module_to_id_;
        Messenger* messenger_;
        ConfigManager* conf_manager_;
        GeometryManager* geo_manager_;

        // global allpix configuration
        Configuration global_config_;

        // list of loaded libraries
        std::map<std::string, void*> loadedLibraries_;
    };
} // namespace allpix

#endif /* ALLPIX_MODULE_MANAGER_H */
<commit_msg>made module creation private<commit_after>/**
 *  @author Koen Wolters <koen.wolters@cern.ch>
 *  @author Daniel Hynds <daniel.hynds@cern.ch>
 */

#ifndef ALLPIX_MODULE_MANAGER_H
#define ALLPIX_MODULE_MANAGER_H

#include <list>
#include <map>
#include <memory>
#include <queue>

#include "../config/Configuration.hpp"
#include "Module.hpp"
#include "core/config/Configuration.hpp"

namespace allpix {

    class ConfigManager;
    class Messenger;
    class GeometryManager;

    class ModuleManager {
    public:
        // Constructor and destructors
        ModuleManager();
        virtual ~ModuleManager();

        // Disallow copy
        ModuleManager(const ModuleManager&) = delete;
        ModuleManager& operator=(const ModuleManager&) = delete;

        // Load modules
        virtual void load(Messenger* messenger, ConfigManager* conf_manager, GeometryManager* geo_manager);

        // Initialize modules (pre-run)
        virtual void init();

        // Run modules
        virtual void run();

        // Finalize modules (post-run)
        virtual void finalize();

    protected:
        using ModuleList = std::list<std::unique_ptr<Module>>;
        using IdentifierToModuleMap = std::map<ModuleIdentifier, ModuleList::iterator>;
        using ModuleToIdentifierMap = std::map<Module*, ModuleIdentifier>;

        // get module identifier
        ModuleIdentifier get_identifier_from_module(Module*);

        // Modules and identifiers converters
        ModuleList modules_;
        IdentifierToModuleMap id_to_module_;
        ModuleToIdentifierMap module_to_id_;
        Messenger* messenger_;
        ConfigManager* conf_manager_;
        GeometryManager* geo_manager_;

        // global allpix configuration
        Configuration global_config_;

        // list of loaded libraries
        std::map<std::string, void*> loadedLibraries_;

    private:
        // Create modules from the loaded library
        std::vector<std::pair<ModuleIdentifier, Module*>> createModules(Configuration, void*);
        std::vector<std::pair<ModuleIdentifier, Module*>> createModulesPerDetector(Configuration, void*);
        void check_module_detector(const std::string&, Module*, const Detector*);

    };
} // namespace allpix

#endif /* ALLPIX_MODULE_MANAGER_H */
<|endoftext|>


<commit_before>/***************************************************************************
    copyright            : (C) 2002, 2003 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it  under the terms of the GNU Lesser General Public License version  *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
 *   USA                                                                   *
 ***************************************************************************/

#include <iostream>
#include <bitset>

#include <tstring.h>
#include <tdebug.h>

#include "id3v2header.h"
#include "id3v2footer.h"
#include "id3v2synchdata.h"

using namespace TagLib;
using namespace ID3v2;

class Header::HeaderPrivate
{
public:
  HeaderPrivate() : majorVersion(0),
                    revisionNumber(0),
                    unsynchronisation(false),
                    extendedHeader(false),
                    experimentalIndicator(false),
                    footerPresent(false),
                    tagSize(0) {}

  ~HeaderPrivate() {}

  uint majorVersion;
  uint revisionNumber;

  bool unsynchronisation;
  bool extendedHeader;
  bool experimentalIndicator;
  bool footerPresent;

  uint tagSize;

  static const uint size = 10;
};

////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////

TagLib::uint Header::size()
{
  return HeaderPrivate::size;
}

ByteVector Header::fileIdentifier()
{
  return ByteVector::fromCString("ID3");
}

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Header::Header()
{
  d = new HeaderPrivate;
}

Header::Header(const ByteVector &data)
{
  d = new HeaderPrivate;
  parse(data);
}

Header::~Header()
{
  delete d;
}

TagLib::uint Header::majorVersion() const
{
  return d->majorVersion;
}

TagLib::uint Header::revisionNumber() const
{
  return d->revisionNumber;
}

bool Header::unsynchronisation() const
{
  return d->unsynchronisation;
}

bool Header::extendedHeader() const
{
  return d->extendedHeader;
}

bool Header::experimentalIndicator() const
{
  return d->experimentalIndicator;
}

bool Header::footerPresent() const
{
  return d->footerPresent;
}

TagLib::uint Header::tagSize() const
{
  return d->tagSize;
}

TagLib::uint Header::completeTagSize() const
{
  if(d->footerPresent)
    return d->tagSize + d->size + Footer::size();
  else
    return d->tagSize + d->size;
}

void Header::setTagSize(uint s)
{
  d->tagSize = s;
}

void Header::setData(const ByteVector &data)
{
  parse(data);
}

ByteVector Header::render() const
{
  ByteVector v;

  // add the file identifier -- "ID3"
  v.append(fileIdentifier());

  // add the version number -- we always render a 2.4.0 tag regardless of what
  // the tag originally was.

  v.append(char(4));
  v.append(char(0));

  // render and add the flags
  std::bitset<8> flags;

  flags[7] = d->unsynchronisation;
  flags[6] = d->extendedHeader;
  flags[5] = d->experimentalIndicator;
  flags[4] = d->footerPresent;

  v.append(char(flags.to_ulong()));

  // add the size
  v.append(SynchData::fromUInt(d->tagSize));

  return v;
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void Header::parse(const ByteVector &data)
{
  if(data.size() < size())
    return;

  // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
  // synch-safe integer, so all bytes must be less than 128.  If this is not
  // true then this is an invalid tag.

  // note that we're doing things a little out of order here -- the size is
  // later in the bytestream than the version

  ByteVector sizeData = data.mid(6, 4);

  if(sizeData.size() != 4) {
    d->tagSize = 0;
    debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!");
    return;
  }

  for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) {
    if(uchar(*it) >= 128) {
      d->tagSize = 0;
      debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128.");
      return;
    }
  }

  // The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")

  // Read the version number from the fourth and fifth bytes.
  d->majorVersion = data[3];   // (structure 3.1 "major version")
  d->revisionNumber = data[4]; // (structure 3.1 "revision number")

  // Read the flags, the first four bits of the sixth byte.
  std::bitset<8> flags(data[5]);

  d->unsynchronisation     = flags[7]; // (structure 3.1.a)
  d->extendedHeader        = flags[6]; // (structure 3.1.b)
  d->experimentalIndicator = flags[5]; // (structure 3.1.c)
  d->footerPresent         = flags[4]; // (structure 3.1.d)

  // Get the size from the remaining four bytes (read above)

  d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
}
<commit_msg>Default to ID3v2.4 in the header (fixes the bug just reported on the list)<commit_after>/***************************************************************************
    copyright            : (C) 2002, 2003 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it  under the terms of the GNU Lesser General Public License version  *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
 *   USA                                                                   *
 ***************************************************************************/

#include <iostream>
#include <bitset>

#include <tstring.h>
#include <tdebug.h>

#include "id3v2header.h"
#include "id3v2footer.h"
#include "id3v2synchdata.h"

using namespace TagLib;
using namespace ID3v2;

class Header::HeaderPrivate
{
public:
  HeaderPrivate() : majorVersion(4),
                    revisionNumber(0),
                    unsynchronisation(false),
                    extendedHeader(false),
                    experimentalIndicator(false),
                    footerPresent(false),
                    tagSize(0) {}

  ~HeaderPrivate() {}

  uint majorVersion;
  uint revisionNumber;

  bool unsynchronisation;
  bool extendedHeader;
  bool experimentalIndicator;
  bool footerPresent;

  uint tagSize;

  static const uint size = 10;
};

////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////

TagLib::uint Header::size()
{
  return HeaderPrivate::size;
}

ByteVector Header::fileIdentifier()
{
  return ByteVector::fromCString("ID3");
}

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Header::Header()
{
  d = new HeaderPrivate;
}

Header::Header(const ByteVector &data)
{
  d = new HeaderPrivate;
  parse(data);
}

Header::~Header()
{
  delete d;
}

TagLib::uint Header::majorVersion() const
{
  return d->majorVersion;
}

TagLib::uint Header::revisionNumber() const
{
  return d->revisionNumber;
}

bool Header::unsynchronisation() const
{
  return d->unsynchronisation;
}

bool Header::extendedHeader() const
{
  return d->extendedHeader;
}

bool Header::experimentalIndicator() const
{
  return d->experimentalIndicator;
}

bool Header::footerPresent() const
{
  return d->footerPresent;
}

TagLib::uint Header::tagSize() const
{
  return d->tagSize;
}

TagLib::uint Header::completeTagSize() const
{
  if(d->footerPresent)
    return d->tagSize + d->size + Footer::size();
  else
    return d->tagSize + d->size;
}

void Header::setTagSize(uint s)
{
  d->tagSize = s;
}

void Header::setData(const ByteVector &data)
{
  parse(data);
}

ByteVector Header::render() const
{
  ByteVector v;

  // add the file identifier -- "ID3"
  v.append(fileIdentifier());

  // add the version number -- we always render a 2.4.0 tag regardless of what
  // the tag originally was.

  v.append(char(4));
  v.append(char(0));

  // render and add the flags
  std::bitset<8> flags;

  flags[7] = d->unsynchronisation;
  flags[6] = d->extendedHeader;
  flags[5] = d->experimentalIndicator;
  flags[4] = d->footerPresent;

  v.append(char(flags.to_ulong()));

  // add the size
  v.append(SynchData::fromUInt(d->tagSize));

  return v;
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void Header::parse(const ByteVector &data)
{
  if(data.size() < size())
    return;

  // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
  // synch-safe integer, so all bytes must be less than 128.  If this is not
  // true then this is an invalid tag.

  // note that we're doing things a little out of order here -- the size is
  // later in the bytestream than the version

  ByteVector sizeData = data.mid(6, 4);

  if(sizeData.size() != 4) {
    d->tagSize = 0;
    debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!");
    return;
  }

  for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) {
    if(uchar(*it) >= 128) {
      d->tagSize = 0;
      debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128.");
      return;
    }
  }

  // The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")

  // Read the version number from the fourth and fifth bytes.
  d->majorVersion = data[3];   // (structure 3.1 "major version")
  d->revisionNumber = data[4]; // (structure 3.1 "revision number")

  // Read the flags, the first four bits of the sixth byte.
  std::bitset<8> flags(data[5]);

  d->unsynchronisation     = flags[7]; // (structure 3.1.a)
  d->extendedHeader        = flags[6]; // (structure 3.1.b)
  d->experimentalIndicator = flags[5]; // (structure 3.1.c)
  d->footerPresent         = flags[4]; // (structure 3.1.d)

  // Get the size from the remaining four bytes (read above)

  d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
}
<|endoftext|>


<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <cmath>
// StdAir
#include <stdair/basic/BasConst_Inventory.hpp>
#include <stdair/bom/BomRetriever.hpp>
#include <stdair/bom/BomManager.hpp>
#include <stdair/bom/SegmentDate.hpp>
#include <stdair/bom/SegmentCabin.hpp>
#include <stdair/bom/FareFamily.hpp>
#include <stdair/bom/BookingClass.hpp>
#include <stdair/bom/SegmentSnapshotTable.hpp>
#include <stdair/service/Logger.hpp>
// AirInv
#include <airinv/basic/BasConst_Curves.hpp>
#include <airinv/bom/SegmentSnapshotTableHelper.hpp>
#include <airinv/bom/FlightDateHelper.hpp>
#include <airinv/bom/SegmentCabinHelper.hpp>

namespace AIRINV {

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::
  takeSnapshots (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable,
                 const stdair::DateTime_T& iSnapshotTime) {
    // Retrieve the segment-cabin index and take the snapshots for
    // each segment-cabin.
    const stdair::SegmentCabinIndexMap_T& lSegmentCabinIndexMap =
      ioSegmentSnapshotTable.getSegmentCabinIndexMap();
    for (stdair::SegmentCabinIndexMap_T::const_iterator itSCIdx =
           lSegmentCabinIndexMap.begin();
         itSCIdx != lSegmentCabinIndexMap.end(); ++itSCIdx) {
      const stdair::SegmentCabin* lSC_ptr = itSCIdx->first;
      assert (lSC_ptr != NULL);
      const stdair::SegmentDataID_T& lSCIdx = itSCIdx->second;

      const stdair::Date_T& lSnapshotDate = iSnapshotTime.date();

      // Compare the date of the snapshot time and the departure date of
      // the segment-cabin in order to verify the necescity of taking snapshots.
      const stdair::SegmentDate& lSegmentDate =
        stdair::BomManager::getParent<stdair::SegmentDate> (*lSC_ptr);
      const stdair::Date_T& lDepartureDate = lSegmentDate.getBoardingDate();
      const stdair::DateOffset_T lDateOffset = lDepartureDate - lSnapshotDate;
      const stdair::DTD_T lDTD = lDateOffset.days() + 1;

      if (lDTD >= 0 && lDTD <= stdair::DEFAULT_MAX_DTD) {
        SegmentCabinHelper::updateAvailabilities (*lSC_ptr);
        takeSnapshots (ioSegmentSnapshotTable, lDTD, *lSC_ptr, lSCIdx);
        registerProductAndPriceOrientedBookings (ioSegmentSnapshotTable,
                                                 lDTD, *lSC_ptr, lSCIdx);
      }
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::
  takeSnapshots (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable,
                 const stdair::DTD_T& iDTD,
                 const stdair::SegmentCabin& iSegmentCabin,
                 const stdair::SegmentDataID_T iSegmentCabinIdx) {

    // Extract the views for the corresponding DTD and segment-cabin.
    stdair::SegmentCabinDTDSnapshotView_T lBookingView = ioSegmentSnapshotTable.
      getSegmentCabinDTDBookingSnapshotView (iSegmentCabinIdx,
                                             iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lCancellationView = ioSegmentSnapshotTable.
      getSegmentCabinDTDCancellationSnapshotView (iSegmentCabinIdx,
                                                  iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lAvailabilityView = ioSegmentSnapshotTable.
      getSegmentCabinDTDAvailabilitySnapshotView (iSegmentCabinIdx,
                                                  iSegmentCabinIdx, iDTD);

    // Retrieve the block index of the segment-cabin.
    std::ostringstream lSCMapKey;
    lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
              << iSegmentCabin.describeKey();
    const stdair::ClassIndex_T& lCabinIdx =
      ioSegmentSnapshotTable.getClassIndex (lSCMapKey.str());
    lAvailabilityView[lCabinIdx] = iSegmentCabin.getAvailabilityPool();
    lBookingView[lCabinIdx] = iSegmentCabin.getCommittedSpace();

    // Browse the booking class list
    const stdair::BookingClassList_T& lBCList =
      stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
    for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
         itBC != lBCList.end(); ++itBC) {
      const stdair::BookingClass* lBookingClass_ptr = *itBC;
      assert (lBookingClass_ptr != NULL);

      // Retrieve the block index of the booking class.
      const stdair::ClassIndex_T& lIdx =
        ioSegmentSnapshotTable.getClassIndex (lBookingClass_ptr->describeKey());

      // DEBUG
      // STDAIR_LOG_DEBUG ("Taking snapshot for "
      //                   << iSegmentCabin.describeKey() << ", "
      //                   << lBookingClass_ptr->describeKey()
      //                   << ", DTD: " << iDTD << ", nb of bookings: "
      //                   << lBookingClass_ptr->getNbOfBookings());

      // Write the snapshot.
      lBookingView[lIdx]=lBookingClass_ptr->getNbOfBookings();
      lCancellationView[lIdx] =
        lBookingClass_ptr->getNbOfCancellations();
      lAvailabilityView[lIdx] =
        lBookingClass_ptr->getSegmentAvailability();
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::registerProductAndPriceOrientedBookings
  (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable, const stdair::DTD_T& iDTD,
   const stdair::SegmentCabin& iSegmentCabin,
   const stdair::SegmentDataID_T iSegmentCabinIdx) {

    // Extract the views for the corresponding DTD and segment-cabin.
    stdair::SegmentCabinDTDRangeSnapshotView_T lRangeBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDRangeBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
    stdair::SegmentCabinDTDRangeSnapshotView_T lRangeCancellationView =
      ioSegmentSnapshotTable.getSegmentCabinDTDRangeCancellationSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
    stdair::SegmentCabinDTDSnapshotView_T lProductOrientedGrossBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDProductOrientedGrossBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lPriceOrientedGrossBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDPriceOrientedGrossBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lProductOrientedNetBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDProductOrientedNetBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lPriceOrientedNetBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDPriceOrientedNetBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);

    // Retrieve the lowest class and treat the number of gross
    // bookings of this class the price oriented bookings.
    const stdair::BookingClassList_T& lBCList =
      stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
    stdair::BookingClassList_T::const_reverse_iterator itBC = lBCList.rbegin();
    assert (itBC != lBCList.rend());
    stdair::BookingClass* lLowestClass_ptr = *itBC; ++itBC;
    assert (lLowestClass_ptr != NULL);

    // Retrieve the block index of the booking class.
    const stdair::ClassIndex_T& lClassIdx =
      ioSegmentSnapshotTable.getClassIndex (lLowestClass_ptr->describeKey());

    // Compute the number of gross bookings for this class.
    const stdair::NbOfBookings_T lNbOfNetBkgs =
      lRangeBookingView[lClassIdx][0] - lRangeBookingView[lClassIdx][1];
    const stdair::NbOfCancellations_T lNbOfCx =
      lRangeCancellationView[lClassIdx][0]-lRangeCancellationView[lClassIdx][1];
    const stdair::NbOfBookings_T lNbOfGrossBkgs = lNbOfNetBkgs + lNbOfCx;

    // Write these numbern of bookings to the price-oriented value.
    lPriceOrientedGrossBookingView[lClassIdx] = lNbOfGrossBkgs;
    lPriceOrientedNetBookingView[lClassIdx] = lNbOfNetBkgs;

    // Retrieve the lowest yield.
    const stdair::Yield_T& lLowestYield = lLowestClass_ptr->getYield();

    // Boolean for "no lower class available" verification.
    bool noLowerClassAvl = true;
    if (lLowestClass_ptr->getSegmentAvailability() >= 1.0) {
      noLowerClassAvl = false;
    }

    // Browse the booking class list
    for (; itBC != lBCList.rend(); ++itBC) {
      const stdair::BookingClass* lBookingClass_ptr = *itBC;
      assert (lBookingClass_ptr != NULL);

      // Retrieve the yield of the this class.
      const stdair::Yield_T& lYield = lBookingClass_ptr->getYield();
      assert (lYield > lLowestYield);

      // Retrieve the block index of the booking class.
      const stdair::ClassIndex_T& lIdx =
        ioSegmentSnapshotTable.getClassIndex (lBookingClass_ptr->describeKey());

      // Compute the number of gross bookings for this class.
      const stdair::NbOfBookings_T lNetBkgs =
        lRangeBookingView[lIdx][0] - lRangeBookingView[lIdx][1];
      const stdair::NbOfCancellations_T lCx =
        lRangeCancellationView[lIdx][0] - lRangeCancellationView[lIdx][1];
      const stdair::NbOfBookings_T lGrossBkgs = lNetBkgs + lCx;

      // If there is a lower class available, these gross bookings
      // will be considered product-oriented. Otherwise, they will be
      // considered price-oriented
      if (noLowerClassAvl == false) {
        lProductOrientedGrossBookingView[lIdx] = lGrossBkgs;
        lProductOrientedNetBookingView[lIdx] = lNetBkgs;
      } else {
        lPriceOrientedGrossBookingView[lIdx] = lGrossBkgs;
        lPriceOrientedNetBookingView[lIdx] = lNetBkgs;

        if (lBookingClass_ptr->getSegmentAvailability() >= 1.0) {
          noLowerClassAvl = false;
        }
      }
    }
  }

}
<commit_msg>[Dev] Improved the retrieve of the lowest yield and the lowest class available: no necessary the last one, especially when dealing with fare families.<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <cmath>
// StdAir
#include <stdair/basic/BasConst_Inventory.hpp>
#include <stdair/bom/BomRetriever.hpp>
#include <stdair/bom/BomManager.hpp>
#include <stdair/bom/SegmentDate.hpp>
#include <stdair/bom/SegmentCabin.hpp>
#include <stdair/bom/FareFamily.hpp>
#include <stdair/bom/BookingClass.hpp>
#include <stdair/bom/SegmentSnapshotTable.hpp>
#include <stdair/service/Logger.hpp>
// AirInv
#include <airinv/basic/BasConst_Curves.hpp>
#include <airinv/bom/SegmentSnapshotTableHelper.hpp>
#include <airinv/bom/FlightDateHelper.hpp>
#include <airinv/bom/SegmentCabinHelper.hpp>

namespace AIRINV {

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::
  takeSnapshots (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable,
                 const stdair::DateTime_T& iSnapshotTime) {
    // Retrieve the segment-cabin index and take the snapshots for
    // each segment-cabin.
    const stdair::SegmentCabinIndexMap_T& lSegmentCabinIndexMap =
      ioSegmentSnapshotTable.getSegmentCabinIndexMap();
    for (stdair::SegmentCabinIndexMap_T::const_iterator itSCIdx =
           lSegmentCabinIndexMap.begin();
         itSCIdx != lSegmentCabinIndexMap.end(); ++itSCIdx) {
      const stdair::SegmentCabin* lSC_ptr = itSCIdx->first;
      assert (lSC_ptr != NULL);
      const stdair::SegmentDataID_T& lSCIdx = itSCIdx->second;

      const stdair::Date_T& lSnapshotDate = iSnapshotTime.date();

      // Compare the date of the snapshot time and the departure date of
      // the segment-cabin in order to verify the necescity of taking snapshots.
      const stdair::SegmentDate& lSegmentDate =
        stdair::BomManager::getParent<stdair::SegmentDate> (*lSC_ptr);
      const stdair::Date_T& lDepartureDate = lSegmentDate.getBoardingDate();
      const stdair::DateOffset_T lDateOffset = lDepartureDate - lSnapshotDate;
      const stdair::DTD_T lDTD = lDateOffset.days() + 1;

      if (lDTD >= 0 && lDTD <= stdair::DEFAULT_MAX_DTD) {
        SegmentCabinHelper::updateAvailabilities (*lSC_ptr);
        takeSnapshots (ioSegmentSnapshotTable, lDTD, *lSC_ptr, lSCIdx);
        registerProductAndPriceOrientedBookings (ioSegmentSnapshotTable,
                                                 lDTD, *lSC_ptr, lSCIdx);
      }
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::
  takeSnapshots (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable,
                 const stdair::DTD_T& iDTD,
                 const stdair::SegmentCabin& iSegmentCabin,
                 const stdair::SegmentDataID_T iSegmentCabinIdx) {

    // Extract the views for the corresponding DTD and segment-cabin.
    stdair::SegmentCabinDTDSnapshotView_T lBookingView = ioSegmentSnapshotTable.
      getSegmentCabinDTDBookingSnapshotView (iSegmentCabinIdx,
                                             iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lCancellationView = ioSegmentSnapshotTable.
      getSegmentCabinDTDCancellationSnapshotView (iSegmentCabinIdx,
                                                  iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lAvailabilityView = ioSegmentSnapshotTable.
      getSegmentCabinDTDAvailabilitySnapshotView (iSegmentCabinIdx,
                                                  iSegmentCabinIdx, iDTD);

    // Retrieve the block index of the segment-cabin.
    std::ostringstream lSCMapKey;
    lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
              << iSegmentCabin.describeKey();
    const stdair::ClassIndex_T& lCabinIdx =
      ioSegmentSnapshotTable.getClassIndex (lSCMapKey.str());
    lAvailabilityView[lCabinIdx] = iSegmentCabin.getAvailabilityPool();
    lBookingView[lCabinIdx] = iSegmentCabin.getCommittedSpace();

    // Browse the booking class list
    const stdair::BookingClassList_T& lBCList =
      stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
    for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
         itBC != lBCList.end(); ++itBC) {
      const stdair::BookingClass* lBookingClass_ptr = *itBC;
      assert (lBookingClass_ptr != NULL);

      // Retrieve the block index of the booking class.
      const stdair::ClassIndex_T& lIdx =
        ioSegmentSnapshotTable.getClassIndex (lBookingClass_ptr->describeKey());

      // DEBUG
      // STDAIR_LOG_DEBUG ("Taking snapshot for "
      //                   << iSegmentCabin.describeKey() << ", "
      //                   << lBookingClass_ptr->describeKey()
      //                   << ", DTD: " << iDTD << ", nb of bookings: "
      //                   << lBookingClass_ptr->getNbOfBookings());

      // Write the snapshot.
      lBookingView[lIdx]=lBookingClass_ptr->getNbOfBookings();
      lCancellationView[lIdx] =
        lBookingClass_ptr->getNbOfCancellations();
      lAvailabilityView[lIdx] =
        lBookingClass_ptr->getSegmentAvailability();
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void SegmentSnapshotTableHelper::registerProductAndPriceOrientedBookings
  (stdair::SegmentSnapshotTable& ioSegmentSnapshotTable, const stdair::DTD_T& iDTD,
   const stdair::SegmentCabin& iSegmentCabin,
   const stdair::SegmentDataID_T iSegmentCabinIdx) {

    // Extract the views for the corresponding DTD and segment-cabin.
    stdair::SegmentCabinDTDRangeSnapshotView_T lRangeBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDRangeBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
    stdair::SegmentCabinDTDRangeSnapshotView_T lRangeCancellationView =
      ioSegmentSnapshotTable.getSegmentCabinDTDRangeCancellationSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
    stdair::SegmentCabinDTDSnapshotView_T lProductOrientedGrossBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDProductOrientedGrossBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lPriceOrientedGrossBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDPriceOrientedGrossBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lProductOrientedNetBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDProductOrientedNetBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
    stdair::SegmentCabinDTDSnapshotView_T lPriceOrientedNetBookingView =
      ioSegmentSnapshotTable.getSegmentCabinDTDPriceOrientedNetBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);

    // Retrieve the lowest yield and the lowest class and treat the number of gross
    // bookings of this class the price oriented bookings.
    const stdair::BookingClassList_T& lBCList =
      stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
    stdair::BookingClassList_T::const_iterator iterBC = lBCList.begin();
    assert (iterBC != lBCList.end());
    stdair::BookingClass* lLowestClass_ptr = *iterBC;
    assert (lLowestClass_ptr  != NULL);
    stdair::Yield_T lLowestYield = lLowestClass_ptr->getYield();
    for (; iterBC != lBCList.end(); iterBC++) {
      const stdair::BookingClass* lBookingClass_ptr = *iterBC;
      assert (lBookingClass_ptr != NULL);
      const stdair::Yield_T& lYield = lBookingClass_ptr->getYield();
      if (lYield < lLowestYield) {
        lLowestYield = lYield;
        lLowestClass_ptr = *iterBC;
      }
    }
    assert (lLowestClass_ptr != NULL);

    // Retrieve the block index of the booking class.
    const stdair::ClassIndex_T& lClassIdx =
      ioSegmentSnapshotTable.getClassIndex (lLowestClass_ptr->describeKey());

    // Compute the number of gross bookings for this class.
    const stdair::NbOfBookings_T lNbOfNetBkgs =
      lRangeBookingView[lClassIdx][0] - lRangeBookingView[lClassIdx][1];
    const stdair::NbOfCancellations_T lNbOfCx =
      lRangeCancellationView[lClassIdx][0]-lRangeCancellationView[lClassIdx][1];
    const stdair::NbOfBookings_T lNbOfGrossBkgs = lNbOfNetBkgs + lNbOfCx;

    // Write these numbern of bookings to the price-oriented value.
    lPriceOrientedGrossBookingView[lClassIdx] = lNbOfGrossBkgs;
    lPriceOrientedNetBookingView[lClassIdx] = lNbOfNetBkgs;

    // Boolean for "no lower class available" verification.
    bool noLowerClassAvl = true;
    if (lLowestClass_ptr->getSegmentAvailability() >= 1.0) {
      noLowerClassAvl = false;
    }

    // Browse the booking class list
    stdair::BookingClassList_T::const_reverse_iterator itBC = lBCList.rbegin();
    for (; itBC != lBCList.rend(); itBC++) {
      const stdair::BookingClass* lBookingClass_ptr = *itBC;
      assert (lBookingClass_ptr != NULL);

      // Retrieve the yield of the this class.
      const stdair::Yield_T& lYield = lBookingClass_ptr->getYield();
      assert (lYield >= lLowestYield);
      if (lYield > lLowestYield) {

        // Retrieve the block index of the booking class.
        const stdair::ClassIndex_T& lIdx =
          ioSegmentSnapshotTable.getClassIndex (lBookingClass_ptr->describeKey());

        // Compute the number of gross bookings for this class.
        const stdair::NbOfBookings_T lNetBkgs =
          lRangeBookingView[lIdx][0] - lRangeBookingView[lIdx][1];
        const stdair::NbOfCancellations_T lCx =
          lRangeCancellationView[lIdx][0] - lRangeCancellationView[lIdx][1];
        const stdair::NbOfBookings_T lGrossBkgs = lNetBkgs + lCx;

        // If there is a lower class available, these gross bookings
        // will be considered product-oriented. Otherwise, they will be
        // considered price-oriented
        if (noLowerClassAvl == false) {
          lProductOrientedGrossBookingView[lIdx] = lGrossBkgs;
          lProductOrientedNetBookingView[lIdx] = lNetBkgs;
        } else {
          lPriceOrientedGrossBookingView[lIdx] = lGrossBkgs;
          lPriceOrientedNetBookingView[lIdx] = lNetBkgs;

          if (lBookingClass_ptr->getSegmentAvailability() >= 1.0) {
            noLowerClassAvl = false;
          }
        }
      }
    }
  }

}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file ms5611_i2c.cpp
 *
 * I2C interface for MS5611
 */

/* XXX trim includes */
#include <px4_config.h>
#include <px4_defines.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>

#include <arch/board/board.h>

#include <drivers/device/i2c.h>

#include "ms5611.h"

#include "board_config.h"

#define MS5611_ADDRESS_1		0x76	/* address select pins pulled high (PX4FMU series v1.6+) */
#define MS5611_ADDRESS_2		0x77    /* address select pins pulled low (PX4FMU prototypes) */

device::Device *MS5611_i2c_interface(ms5611::prom_u &prom_buf);

class MS5611_I2C : public device::I2C
{
public:
	MS5611_I2C(uint8_t bus, ms5611::prom_u &prom_buf);
	virtual ~MS5611_I2C();

	virtual int	init();
	virtual int	read(unsigned offset, void *data, unsigned count);
	virtual int	ioctl(unsigned operation, unsigned &arg);

protected:
	virtual int	probe();

private:
	ms5611::prom_u	&_prom;

	int		_probe_address(uint8_t address);

	/**
	 * Send a reset command to the MS5611.
	 *
	 * This is required after any bus reset.
	 */
	int		_reset();

	/**
	 * Send a measure command to the MS5611.
	 *
	 * @param addr		Which address to use for the measure operation.
	 */
	int		_measure(unsigned addr);

	/**
	 * Read the MS5611 PROM
	 *
	 * @return		PX4_OK if the PROM reads successfully.
	 */
	int		_read_prom();

};

device::Device *
MS5611_i2c_interface(ms5611::prom_u &prom_buf, uint8_t busnum)
{
	return new MS5611_I2C(busnum, prom_buf);
}

MS5611_I2C::MS5611_I2C(uint8_t bus, ms5611::prom_u &prom) :
	I2C("MS5611_I2C", nullptr, bus, 0, 400000),
	_prom(prom)
{
}

MS5611_I2C::~MS5611_I2C()
{
}

int
MS5611_I2C::init()
{
	/* this will call probe(), and thereby _probe_address */
	return I2C::init();
}

int
MS5611_I2C::read(unsigned offset, void *data, unsigned count)
{
	union _cvt {
		uint8_t	b[4];
		uint32_t w;
	} *cvt = (_cvt *)data;
	uint8_t buf[3];

	/* read the most recent measurement */
	uint8_t cmd = 0;
	int ret = transfer(&cmd, 1, &buf[0], 3);

	if (ret == PX4_OK) {
		/* fetch the raw value */
		cvt->b[0] = buf[2];
		cvt->b[1] = buf[1];
		cvt->b[2] = buf[0];
		cvt->b[3] = 0;
	}

	return ret;
}

int
MS5611_I2C::ioctl(unsigned operation, unsigned &arg)
{
	int ret;

	switch (operation) {
	case IOCTL_RESET:
		ret = _reset();
		break;

	case IOCTL_MEASURE:
		ret = _measure(arg);
		break;

	default:
		ret = EINVAL;
	}

	return ret;
}

int
MS5611_I2C::probe()
{
	_retries = 10;

	if ((PX4_OK == _probe_address(MS5611_ADDRESS_1)) ||
	    (PX4_OK == _probe_address(MS5611_ADDRESS_2))) {
		/*
		 * Disable retries; we may enable them selectively in some cases,
		 * but the device gets confused if we retry some of the commands.
		 */
		_retries = 0;
		return PX4_OK;
	}

	return -EIO;
}

int
MS5611_I2C::_probe_address(uint8_t address)
{
	/* select the address we are going to try */
	set_address(address);

	/* send reset command */
	if (PX4_OK != _reset()) {
		return -EIO;
	}

	/* read PROM */
	if (PX4_OK != _read_prom()) {
		return -EIO;
	}

	return PX4_OK;
}

int
MS5611_I2C::_reset()
{
	unsigned	old_retrycount = _retries;
	uint8_t		cmd = ADDR_RESET_CMD;
	int		result;

	/* bump the retry count */
	_retries = 10;
	result = transfer(&cmd, 1, nullptr, 0);
	_retries = old_retrycount;

	return result;
}

int
MS5611_I2C::_measure(unsigned addr)
{
	/*
	 * Disable retries on this command; we can't know whether failure
	 * means the device did or did not see the command.
	 */
	_retries = 0;

	uint8_t cmd = addr;
	return transfer(&cmd, 1, nullptr, 0);
}

int
MS5611_I2C::_read_prom()
{
	uint8_t		prom_buf[2];
	union {
		uint8_t		b[2];
		uint16_t	w;
	} cvt;

	/*
	 * Wait for PROM contents to be in the device (2.8 ms) in the case we are
	 * called immediately after reset.
	 */
	usleep(3000);

	uint8_t last_val = 0;
	bool bits_stuck = true;

	/* read and convert PROM words */
	for (int i = 0; i < 8; i++) {
		uint8_t cmd = ADDR_PROM_SETUP + (i * 2);

		if (PX4_OK != transfer(&cmd, 1, &prom_buf[0], 2)) {
			break;
		}

		/* check if all bytes are zero */
		if (i == 0) {
			/* initalize to first byte read */
			last_val = prom_buf[0];
		}

		if (prom_buf[0] != last_val || prom_buf[1] != last_val) {
			bits_stuck = false;
		}

		/* assemble 16 bit value and convert from big endian (sensor) to little endian (MCU) */
		cvt.b[0] = prom_buf[1];
		cvt.b[1] = prom_buf[0];
		_prom.c[i] = cvt.w;
	}

	/* calculate CRC and return success/failure accordingly */
	return (ms5611::crc4(&_prom.c[0]) && !bits_stuck) ? PX4_OK : -EIO;
}
<commit_msg>Update ms5611_i2c.cpp<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file ms5611_i2c.cpp
 *
 * I2C interface for MS5611
 */

/* XXX trim includes */
#include <px4_config.h>
#include <px4_defines.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>

#include <arch/board/board.h>

#include <drivers/device/i2c.h>

#include "ms5611.h"

#include "board_config.h"

#define MS5611_ADDRESS_1		0x76	/* address select pins pulled high (PX4FMU series v1.6+) */
#define MS5611_ADDRESS_2		0x77    /* address select pins pulled low (PX4FMU prototypes) */

device::Device *MS5611_i2c_interface(ms5611::prom_u &prom_buf);

class MS5611_I2C : public device::I2C
{
public:
	MS5611_I2C(uint8_t bus, ms5611::prom_u &prom_buf);
	virtual ~MS5611_I2C();

	virtual int	init();
	virtual int	read(unsigned offset, void *data, unsigned count);
	virtual int	ioctl(unsigned operation, unsigned &arg);

protected:
	virtual int	probe();

private:
	ms5611::prom_u	&_prom;

	int		_probe_address(uint8_t address);

	/**
	 * Send a reset command to the MS5611.
	 *
	 * This is required after any bus reset.
	 */
	int		_reset();

	/**
	 * Send a measure command to the MS5611.
	 *
	 * @param addr		Which address to use for the measure operation.
	 */
	int		_measure(unsigned addr);

	/**
	 * Read the MS5611 PROM
	 *
	 * @return		PX4_OK if the PROM reads successfully.
	 */
	int		_read_prom();

};

device::Device *
MS5611_i2c_interface(ms5611::prom_u &prom_buf, uint8_t busnum)
{
	return new MS5611_I2C(busnum, prom_buf);
}

MS5611_I2C::MS5611_I2C(uint8_t bus, ms5611::prom_u &prom) :
	I2C("MS5611_I2C", nullptr, bus, 0, 400000),
	_prom(prom)
{
}

MS5611_I2C::~MS5611_I2C()
{
}

int
MS5611_I2C::init()
{
	/* this will call probe(), and thereby _probe_address */
	return I2C::init();
}

int
MS5611_I2C::read(unsigned offset, void *data, unsigned count)
{
	union _cvt {
		uint8_t	b[4];
		uint32_t w;
	} *cvt = (_cvt *)data;
	uint8_t buf[3];

	/* read the most recent measurement */
	uint8_t cmd = 0;
	int ret = transfer(&cmd, 1, &buf[0], 3);

	if (ret == PX4_OK) {
		/* fetch the raw value */
		cvt->b[0] = buf[2];
		cvt->b[1] = buf[1];
		cvt->b[2] = buf[0];
		cvt->b[3] = 0;
	}

	return ret;
}

int
MS5611_I2C::ioctl(unsigned operation, unsigned &arg)
{
	int ret;

	switch (operation) {
	case IOCTL_RESET:
		ret = _reset();
		break;

	case IOCTL_MEASURE:
		ret = _measure(arg);
		break;

	default:
		ret = EINVAL;
	}

	return ret;
}

int
MS5611_I2C::probe()
{
	_retries = 10;

	if ((PX4_OK == _probe_address(MS5611_ADDRESS_1)) ||
	    (PX4_OK == _probe_address(MS5611_ADDRESS_2))) {
		/*
		 * Disable retries; we may enable them selectively in some cases,
		 * but the device gets confused if we retry some of the commands.
		 */
		_retries = 0;
		return PX4_OK;
	}

	return -EIO;
}

int
MS5611_I2C::_probe_address(uint8_t address)
{
	/* select the address we are going to try */
	set_address(address);

	/* send reset command */
	if (PX4_OK != _reset()) {
		return -EIO;
	}

	/* read PROM */
	if (PX4_OK != _read_prom()) {
		return -EIO;
	}

	return PX4_OK;
}

int
MS5611_I2C::_reset()
{
	unsigned	old_retrycount = _retries;
	uint8_t		cmd = ADDR_RESET_CMD;
	int		result;

	/* bump the retry count */
	_retries = 10;
	result = transfer(&cmd, 1, nullptr, 0);
	_retries = old_retrycount;

	return result;
}

int
MS5611_I2C::_measure(unsigned addr)
{
	/*
	 * Disable retries on this command; we can't know whether failure
	 * means the device did or did not see the command.
	 */
	_retries = 0;

	uint8_t cmd = addr;
	return transfer(&cmd, 1, nullptr, 0);
}

int
MS5611_I2C::_read_prom()
{
	uint8_t		prom_buf[2];
	union {
		uint8_t		b[2];
		uint16_t	w;
	} cvt;

	/*
	 * Wait for PROM contents to be in the device (2.8 ms) in the case we are
	 * called immediately after reset.
	 */
	usleep(3000);

	uint8_t last_val = 0;
	bool bits_stuck = true;

	/* read and convert PROM words */
	for (int i = 0; i < 8; i++) {
		uint8_t cmd = ADDR_PROM_SETUP + (i * 2);

		if (PX4_OK != transfer(&cmd, 1, &prom_buf[0], 2)) {
			break;
		}

		/* check if all bytes are zero */
		if (i == 0) {
			/* initialize to first byte read */
			last_val = prom_buf[0];
		}

		if (prom_buf[0] != last_val || prom_buf[1] != last_val) {
			bits_stuck = false;
		}

		/* assemble 16 bit value and convert from big endian (sensor) to little endian (MCU) */
		cvt.b[0] = prom_buf[1];
		cvt.b[1] = prom_buf[0];
		_prom.c[i] = cvt.w;
	}

	/* calculate CRC and return success/failure accordingly */
	return (ms5611::crc4(&_prom.c[0]) && !bits_stuck) ? PX4_OK : -EIO;
}
<|endoftext|>


<commit_before>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/
#include <Rocket/Core.h>
#include "client.h"
#include "rocket.h"
#include "../qcommon/q_unicode.h"

using namespace Rocket::Core::Input;

static std::map< int, int > keyMap;
static bool init = false;

void Rocket_InitKeys( void )
{
	keyMap[ K_TAB ] = KI_TAB;
	keyMap[ K_ENTER ] = KI_RETURN;
	keyMap[ K_ESCAPE ] = KI_ESCAPE;
	keyMap[ K_SPACE ] = KI_SPACE;

	keyMap[ K_BACKSPACE ] = KI_BACK;

	keyMap[ K_COMMAND ] = KI_LWIN;
	keyMap[ K_CAPSLOCK ] = KI_CAPITAL;
	keyMap[ K_POWER ] = KI_POWER;
	keyMap[ K_PAUSE ] = KI_PAUSE;

	keyMap[ K_UPARROW ] = KI_UP;
	keyMap[ K_DOWNARROW ] = KI_DOWN;
	keyMap[ K_LEFTARROW ] = KI_LEFT;
	keyMap[ K_RIGHTARROW ] = KI_RIGHT;

	keyMap[ K_ALT ] = KI_LMETA;
	keyMap[ K_CTRL ] = KI_LCONTROL;
	keyMap[ K_SHIFT ] = KI_LSHIFT;
	keyMap[ K_INS ] = KI_INSERT;
	keyMap[ K_DEL ] = KI_DELETE;
	keyMap[ K_PGDN ] = KI_NEXT;
	keyMap[ K_PGUP ] = KI_PRIOR;
	keyMap[ K_HOME ] = KI_HOME;
	keyMap[ K_END ] = KI_END;

	keyMap[ K_F1 ] = KI_F1;
	keyMap[ K_F2 ] = KI_F2;
	keyMap[ K_F3 ] = KI_F3;
	keyMap[ K_F4 ] = KI_F4;
	keyMap[ K_F5 ] = KI_F5;
	keyMap[ K_F6 ] = KI_F6;
	keyMap[ K_F7 ] = KI_F7;
	keyMap[ K_F8 ] = KI_F8;
	keyMap[ K_F9 ] = KI_F9;
	keyMap[ K_F10 ] = KI_F10;
	keyMap[ K_F11 ] = KI_F11;
	keyMap[ K_F12 ] = KI_F12;
	keyMap[ K_F13 ] = KI_F13;
	keyMap[ K_F14 ] = KI_F14;
	keyMap[ K_F15 ] = KI_F15;

	keyMap[ K_KP_HOME ] = KI_NUMPAD7;
	keyMap[ K_KP_UPARROW ] = KI_NUMPAD8;
	keyMap[ K_KP_PGUP ] = KI_NUMPAD9;
	keyMap[ K_KP_LEFTARROW ] = KI_NUMPAD4;
	keyMap[ K_KP_5 ] = KI_NUMPAD5;
	keyMap[ K_KP_RIGHTARROW ] = KI_NUMPAD6;
	keyMap[ K_KP_END ] = KI_NUMPAD1;
	keyMap[ K_KP_DOWNARROW ] = KI_NUMPAD2;
	keyMap[ K_KP_PGDN ] = KI_NUMPAD3;
	keyMap[ K_KP_ENTER ] = KI_NUMPADENTER;
	keyMap[ K_KP_INS ] = KI_NUMPAD0;
	keyMap[ K_KP_DEL ] = KI_DECIMAL;
	keyMap[ K_KP_SLASH ] = KI_DIVIDE;
	keyMap[ K_KP_MINUS ] = KI_SUBTRACT;
	keyMap[ K_KP_PLUS ] = KI_ADD;
	keyMap[ K_KP_NUMLOCK ] = KI_NUMLOCK;
	keyMap[ K_KP_STAR ] = KI_MULTIPLY;
// 	keyMap[ K_KP_EQUALS ] = KI_KP_EQUALS;

	keyMap[ K_SUPER ] = KI_LWIN;
// 	keyMap[ K_COMPOSE ] = KI_COMPOSE;
// 	keyMap[ K_MODE ] = KI_MODE;
	keyMap[ K_HELP ] = KI_HELP;
	keyMap[ K_PRINT ] = KI_PRINT;
// 	keyMap[ K_SYSREQ ] = KI_SYSREQ;
	keyMap[ K_SCROLLOCK ] = KI_SCROLL;
// 	keyMap[ K_BREAK ] = KI_BREAK;
	keyMap[ K_MENU ] = KI_APPS;
// 	keyMap[ K_EURO ] = KI_EURO;
// 	keyMap[ K_UNDO ] = KI_UNDO;

	// Corresponds to 0 - 9
	for ( int i = '0'; i < '9' + 1; ++i )
	{
		keyMap[ i ] = KI_0 + ( i - '0' );
	}

	// Corresponds to a - z
	for ( int i = 'a'; i < 'z' + 1; ++i )
	{
		keyMap[ i ] = KI_A + ( i - 'a' );
	}

	// Other keyMap that out of ascii order and are handled separately
	keyMap[ ';' ] = KI_OEM_1;      // US standard keyboard; the ';:' key.
	keyMap[ '=' ] = KI_OEM_PLUS;   // Any region; the '=+' key.
	keyMap[ ',' ] = KI_OEM_COMMA;  // Any region; the ',<' key.
	keyMap[ '-' ] = KI_OEM_MINUS;  // Any region; the '-_' key.
	keyMap[ '.' ] = KI_OEM_PERIOD; // Any region; the '.>' key.
	keyMap[ '/' ] = KI_OEM_2;      // Any region; the '/?' key.
	keyMap[ '`' ] = KI_OEM_3;      // Any region; the '`~' key.
	keyMap[ K_CONSOLE ] = KI_OEM_3;

	keyMap[ '[' ] = KI_OEM_4;      // US standard keyboard; the '[{' key.
	keyMap[ '\\' ] = KI_OEM_5;     // US standard keyboard; the '\|' key.
	keyMap[ ']' ] = KI_OEM_6;      // US standard keyboard; the ']}' key.
	keyMap[ '\'' ] = KI_OEM_7;     // US standard keyboard; the ''"' key.

	init = true;
}

KeyIdentifier Rocket_FromQuake( int key )
{
	if ( !init )
	{
		Com_Log( LOG_WARN, "Tried to convert keyMap before key array initialized." );
		return KI_UNKNOWN;
	}
	std::map< int, int >::iterator it;
	it = keyMap.find( key );
	if ( it != keyMap.end() )
	{
		return static_cast< KeyIdentifier >( it->second );
	}

	Com_Logf( LOG_WARN, "Rocket_FromQuake: Could not find keynum %d", key );
	return KI_UNKNOWN;
}

keyNum_t Rocket_ToQuake( int key )
{
	if ( !init )
	{
		Com_Log( LOG_WARN, "Tried to convert keyMap before key array initialized." );
		return K_NONE;
	}
	std::map< int, int >::iterator it;
	for ( it = keyMap.begin(); it != keyMap.end(); ++it )
	{
		if ( it->second == key )
		{
			return static_cast< keyNum_t>( it->first );
		}
	}

	Com_Logf( LOG_WARN, "Rocket_ToQuake: Could not find keynum %d", key );
	return K_NONE;
}

KeyModifier Rocket_GetKeyModifiers( void )
{
	int mod = 0;

	if ( Key_IsDown( K_CTRL ) )
	{
		mod |= KM_CTRL;
	}
	if ( Key_IsDown( K_SHIFT ) )
	{
		mod |= KM_SHIFT;
	}
	if ( Key_IsDown( K_ALT ) )
	{
		mod |= KM_ALT;
	}
	if ( Key_IsDown( K_SUPER ) )
	{
		mod |= KM_META;
	}
	if ( Key_IsDown( K_CAPSLOCK ) )
	{
		mod |= KM_CAPSLOCK;
	}
	if ( Sys_IsNumLockDown() )
	{
		mod |= KM_NUMLOCK;
	}

	return static_cast< KeyModifier >( mod );
}

void Rocket_ProcessMouseClick( int button, qboolean down )
{
	int idx = 0;
	if ( button <= K_MOUSE5 )
	{
		idx = button - K_MOUSE1;
	}
	else
	{
		idx = button - K_AUX1 + 5; // Start at 5 because of K_MOUSE5
	}

	if ( down )
	{
		menuContext->ProcessMouseButtonDown( idx, Rocket_GetKeyModifiers() );
	}
	else
	{
		menuContext->ProcessMouseButtonUp( idx, Rocket_GetKeyModifiers() );
	}
}

#define MOUSEWHEEL_DELTA 5
void Rocket_ProcessKeyInput( int key, qboolean down )
{
	if ( !menuContext )
	{
		return;
	}

	// Our input system sends mouse events as key presses.
	if ( ( key >= K_MOUSE1 && key <= K_MOUSE5 ) || ( key >= K_AUX1 && key <= K_AUX16 ) )
	{
		Rocket_ProcessMouseClick( key, down );
		return;
	}

	if ( ( key == K_MWHEELDOWN || key == K_MWHEELUP ) )
	{
		// Our input system sends an up event right after a down event
		// We only want to catch one of these.
		if ( !down )
		{
			return;
		}

		menuContext->ProcessMouseWheel( key == K_MWHEELDOWN ? MOUSEWHEEL_DELTA : -MOUSEWHEEL_DELTA, Rocket_GetKeyModifiers() );
		return;
	}
	if ( down )
	{
		menuContext->ProcessKeyDown( Rocket_FromQuake( key ), Rocket_GetKeyModifiers() );
	}
	else
	{
		menuContext->ProcessKeyUp( Rocket_FromQuake( key ), Rocket_GetKeyModifiers() );
	}
}

int utf8_to_ucs2( const unsigned char *input )
{
	if ( input[0] == 0 )
		return -1;

	if ( input[0] < 0x80 )
	{
		return input[0];
	}

	if ( ( input[0] & 0xE0 ) == 0xE0 )
	{
		if ( input[1] == 0 || input[2] == 0 )
			return -1;

		return
		    ( input[0] & 0x0F ) << 12 |
		    ( input[1] & 0x3F ) << 6  |
		    ( input[2] & 0x3F );
	}

	if ( ( input[0] & 0xC0 ) == 0xC0 )
	{
		if ( input[1] == 0 )
			return -1;

		return
		    ( input[0] & 0x1F ) << 6  |
		    ( input[1] & 0x3F );
	}

	return -1;
}

void Rocket_ProcessTextInput( int key )
{
	if ( !menuContext )
	{
		return;
	}

	//
	// ignore any non printable chars
	//
	const char *s =  Q_UTF8_Unstore( key );
	if ( ( unsigned char )*s < 32 || ( unsigned char )*s == 0x7f )
	{
		return;
	}

	menuContext->ProcessTextInput( utf8_to_ucs2( ( unsigned char* )s ) );
}

void Rocket_MouseMove( int x, int y )
{
	if ( !menuContext )
	{
		return;
	}

	menuContext->ProcessMouseMove( x, y, Rocket_GetKeyModifiers() );
}
<commit_msg>Don't inject input to rocket if console is down<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/
#include <Rocket/Core.h>
#include "client.h"
#include "rocket.h"
#include "../qcommon/q_unicode.h"

using namespace Rocket::Core::Input;

static std::map< int, int > keyMap;
static bool init = false;

void Rocket_InitKeys( void )
{
	keyMap[ K_TAB ] = KI_TAB;
	keyMap[ K_ENTER ] = KI_RETURN;
	keyMap[ K_ESCAPE ] = KI_ESCAPE;
	keyMap[ K_SPACE ] = KI_SPACE;

	keyMap[ K_BACKSPACE ] = KI_BACK;

	keyMap[ K_COMMAND ] = KI_LWIN;
	keyMap[ K_CAPSLOCK ] = KI_CAPITAL;
	keyMap[ K_POWER ] = KI_POWER;
	keyMap[ K_PAUSE ] = KI_PAUSE;

	keyMap[ K_UPARROW ] = KI_UP;
	keyMap[ K_DOWNARROW ] = KI_DOWN;
	keyMap[ K_LEFTARROW ] = KI_LEFT;
	keyMap[ K_RIGHTARROW ] = KI_RIGHT;

	keyMap[ K_ALT ] = KI_LMETA;
	keyMap[ K_CTRL ] = KI_LCONTROL;
	keyMap[ K_SHIFT ] = KI_LSHIFT;
	keyMap[ K_INS ] = KI_INSERT;
	keyMap[ K_DEL ] = KI_DELETE;
	keyMap[ K_PGDN ] = KI_NEXT;
	keyMap[ K_PGUP ] = KI_PRIOR;
	keyMap[ K_HOME ] = KI_HOME;
	keyMap[ K_END ] = KI_END;

	keyMap[ K_F1 ] = KI_F1;
	keyMap[ K_F2 ] = KI_F2;
	keyMap[ K_F3 ] = KI_F3;
	keyMap[ K_F4 ] = KI_F4;
	keyMap[ K_F5 ] = KI_F5;
	keyMap[ K_F6 ] = KI_F6;
	keyMap[ K_F7 ] = KI_F7;
	keyMap[ K_F8 ] = KI_F8;
	keyMap[ K_F9 ] = KI_F9;
	keyMap[ K_F10 ] = KI_F10;
	keyMap[ K_F11 ] = KI_F11;
	keyMap[ K_F12 ] = KI_F12;
	keyMap[ K_F13 ] = KI_F13;
	keyMap[ K_F14 ] = KI_F14;
	keyMap[ K_F15 ] = KI_F15;

	keyMap[ K_KP_HOME ] = KI_NUMPAD7;
	keyMap[ K_KP_UPARROW ] = KI_NUMPAD8;
	keyMap[ K_KP_PGUP ] = KI_NUMPAD9;
	keyMap[ K_KP_LEFTARROW ] = KI_NUMPAD4;
	keyMap[ K_KP_5 ] = KI_NUMPAD5;
	keyMap[ K_KP_RIGHTARROW ] = KI_NUMPAD6;
	keyMap[ K_KP_END ] = KI_NUMPAD1;
	keyMap[ K_KP_DOWNARROW ] = KI_NUMPAD2;
	keyMap[ K_KP_PGDN ] = KI_NUMPAD3;
	keyMap[ K_KP_ENTER ] = KI_NUMPADENTER;
	keyMap[ K_KP_INS ] = KI_NUMPAD0;
	keyMap[ K_KP_DEL ] = KI_DECIMAL;
	keyMap[ K_KP_SLASH ] = KI_DIVIDE;
	keyMap[ K_KP_MINUS ] = KI_SUBTRACT;
	keyMap[ K_KP_PLUS ] = KI_ADD;
	keyMap[ K_KP_NUMLOCK ] = KI_NUMLOCK;
	keyMap[ K_KP_STAR ] = KI_MULTIPLY;
// 	keyMap[ K_KP_EQUALS ] = KI_KP_EQUALS;

	keyMap[ K_SUPER ] = KI_LWIN;
// 	keyMap[ K_COMPOSE ] = KI_COMPOSE;
// 	keyMap[ K_MODE ] = KI_MODE;
	keyMap[ K_HELP ] = KI_HELP;
	keyMap[ K_PRINT ] = KI_PRINT;
// 	keyMap[ K_SYSREQ ] = KI_SYSREQ;
	keyMap[ K_SCROLLOCK ] = KI_SCROLL;
// 	keyMap[ K_BREAK ] = KI_BREAK;
	keyMap[ K_MENU ] = KI_APPS;
// 	keyMap[ K_EURO ] = KI_EURO;
// 	keyMap[ K_UNDO ] = KI_UNDO;

	// Corresponds to 0 - 9
	for ( int i = '0'; i < '9' + 1; ++i )
	{
		keyMap[ i ] = KI_0 + ( i - '0' );
	}

	// Corresponds to a - z
	for ( int i = 'a'; i < 'z' + 1; ++i )
	{
		keyMap[ i ] = KI_A + ( i - 'a' );
	}

	// Other keyMap that out of ascii order and are handled separately
	keyMap[ ';' ] = KI_OEM_1;      // US standard keyboard; the ';:' key.
	keyMap[ '=' ] = KI_OEM_PLUS;   // Any region; the '=+' key.
	keyMap[ ',' ] = KI_OEM_COMMA;  // Any region; the ',<' key.
	keyMap[ '-' ] = KI_OEM_MINUS;  // Any region; the '-_' key.
	keyMap[ '.' ] = KI_OEM_PERIOD; // Any region; the '.>' key.
	keyMap[ '/' ] = KI_OEM_2;      // Any region; the '/?' key.
	keyMap[ '`' ] = KI_OEM_3;      // Any region; the '`~' key.
	keyMap[ K_CONSOLE ] = KI_OEM_3;

	keyMap[ '[' ] = KI_OEM_4;      // US standard keyboard; the '[{' key.
	keyMap[ '\\' ] = KI_OEM_5;     // US standard keyboard; the '\|' key.
	keyMap[ ']' ] = KI_OEM_6;      // US standard keyboard; the ']}' key.
	keyMap[ '\'' ] = KI_OEM_7;     // US standard keyboard; the ''"' key.

	init = true;
}

KeyIdentifier Rocket_FromQuake( int key )
{
	if ( !init )
	{
		Com_Log( LOG_WARN, "Tried to convert keyMap before key array initialized." );
		return KI_UNKNOWN;
	}
	std::map< int, int >::iterator it;
	it = keyMap.find( key );
	if ( it != keyMap.end() )
	{
		return static_cast< KeyIdentifier >( it->second );
	}

	Com_Logf( LOG_WARN, "Rocket_FromQuake: Could not find keynum %d", key );
	return KI_UNKNOWN;
}

keyNum_t Rocket_ToQuake( int key )
{
	if ( !init )
	{
		Com_Log( LOG_WARN, "Tried to convert keyMap before key array initialized." );
		return K_NONE;
	}
	std::map< int, int >::iterator it;
	for ( it = keyMap.begin(); it != keyMap.end(); ++it )
	{
		if ( it->second == key )
		{
			return static_cast< keyNum_t>( it->first );
		}
	}

	Com_Logf( LOG_WARN, "Rocket_ToQuake: Could not find keynum %d", key );
	return K_NONE;
}

KeyModifier Rocket_GetKeyModifiers( void )
{
	int mod = 0;

	if ( Key_IsDown( K_CTRL ) )
	{
		mod |= KM_CTRL;
	}
	if ( Key_IsDown( K_SHIFT ) )
	{
		mod |= KM_SHIFT;
	}
	if ( Key_IsDown( K_ALT ) )
	{
		mod |= KM_ALT;
	}
	if ( Key_IsDown( K_SUPER ) )
	{
		mod |= KM_META;
	}
	if ( Key_IsDown( K_CAPSLOCK ) )
	{
		mod |= KM_CAPSLOCK;
	}
	if ( Sys_IsNumLockDown() )
	{
		mod |= KM_NUMLOCK;
	}

	return static_cast< KeyModifier >( mod );
}

void Rocket_ProcessMouseClick( int button, qboolean down )
{
	if ( !menuContext || cls.keyCatchers & KEYCATCH_CONSOLE )
	{
		return;
	}

	int idx = 0;
	if ( button <= K_MOUSE5 )
	{
		idx = button - K_MOUSE1;
	}
	else
	{
		idx = button - K_AUX1 + 5; // Start at 5 because of K_MOUSE5
	}

	if ( down )
	{
		menuContext->ProcessMouseButtonDown( idx, Rocket_GetKeyModifiers() );
	}
	else
	{
		menuContext->ProcessMouseButtonUp( idx, Rocket_GetKeyModifiers() );
	}
}

#define MOUSEWHEEL_DELTA 5
void Rocket_ProcessKeyInput( int key, qboolean down )
{
	if ( !menuContext || cls.keyCatchers & KEYCATCH_CONSOLE )
	{
		return;
	}

	// Our input system sends mouse events as key presses.
	if ( ( key >= K_MOUSE1 && key <= K_MOUSE5 ) || ( key >= K_AUX1 && key <= K_AUX16 ) )
	{
		Rocket_ProcessMouseClick( key, down );
		return;
	}

	if ( ( key == K_MWHEELDOWN || key == K_MWHEELUP ) )
	{
		// Our input system sends an up event right after a down event
		// We only want to catch one of these.
		if ( !down )
		{
			return;
		}

		menuContext->ProcessMouseWheel( key == K_MWHEELDOWN ? MOUSEWHEEL_DELTA : -MOUSEWHEEL_DELTA, Rocket_GetKeyModifiers() );
		return;
	}
	if ( down )
	{
		menuContext->ProcessKeyDown( Rocket_FromQuake( key ), Rocket_GetKeyModifiers() );
	}
	else
	{
		menuContext->ProcessKeyUp( Rocket_FromQuake( key ), Rocket_GetKeyModifiers() );
	}
}

int utf8_to_ucs2( const unsigned char *input )
{
	if ( input[0] == 0 )
		return -1;

	if ( input[0] < 0x80 )
	{
		return input[0];
	}

	if ( ( input[0] & 0xE0 ) == 0xE0 )
	{
		if ( input[1] == 0 || input[2] == 0 )
			return -1;

		return
		    ( input[0] & 0x0F ) << 12 |
		    ( input[1] & 0x3F ) << 6  |
		    ( input[2] & 0x3F );
	}

	if ( ( input[0] & 0xC0 ) == 0xC0 )
	{
		if ( input[1] == 0 )
			return -1;

		return
		    ( input[0] & 0x1F ) << 6  |
		    ( input[1] & 0x3F );
	}

	return -1;
}

void Rocket_ProcessTextInput( int key )
{
	if ( !menuContext )
	{
		return;
	}

	//
	// ignore any non printable chars
	//
	const char *s =  Q_UTF8_Unstore( key );
	if ( ( unsigned char )*s < 32 || ( unsigned char )*s == 0x7f )
	{
		return;
	}

	menuContext->ProcessTextInput( utf8_to_ucs2( ( unsigned char* )s ) );
}

void Rocket_MouseMove( int x, int y )
{
	if ( !menuContext )
	{
		return;
	}

	menuContext->ProcessMouseMove( x, y, Rocket_GetKeyModifiers() );
}
<|endoftext|>