<commit_before>#ifndef NEU_ANY_LAYER_VECTOR_HPP
#define NEU_ANY_LAYER_VECTOR_HPP
//20150914
#include <vector>
#include <neu/basic_type.hpp>
#include <neu/range/algorithm.hpp>
#include <neu/range/gpu_buffer_range.hpp>
#include <neu/layer/traits.hpp>
#include <neu/layer/any_layer.hpp>
#include <neu/layer/deserialize_fwd.hpp>
namespace neu {
	namespace layer {
		namespace traits {
			template<>
			class input_rank<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::input_rank(alv.front());
				}
			};
			template<>
			class output_rank<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::output_rank(alv.back());
				}
			};
			template<>
			class input_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv, rank_id ri) {
					return ::neu::layer::input_size(alv.front(), ri);
				}
			};
			template<>
			class output_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv, rank_id ri) {
					return ::neu::layer::output_size(alv.back(), ri);
				}
			};
			template<>
			class batch_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::batch_size(alv.front());
				}
			};
			template<>
			class test_forward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(
						std::vector<neu::layer::any_layer>& layers,
						std::size_t batch_size,
						InputRange const& initial_input, OutputRange& result_output,
						boost::compute::command_queue& queue) {
					gpu_vector input(initial_input.begin(), initial_input.end(), queue);
					gpu_vector output(queue.get_context());
					auto output_range = range::to_range(output);
					for(auto& l : layers) {
						output.resize(::neu::layer::whole_output_size(l), queue);
						l.test_forward(batch_size,
							range::to_range(input), output_range, queue);
						input.swap(output);
					}
					range::copy(input, result_output, queue);
				}
			};
			template<>
			class forward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_input, OutputRange& result_output,
						boost::compute::command_queue& queue) {
					gpu_vector input(initial_input.begin(), initial_input.end(), queue);
					gpu_vector output(queue.get_context());
					auto output_range = range::to_range(output);
					for(auto& l : layers) {
						output.resize(::neu::layer::whole_output_size(l), queue);
						l.forward(range::to_range(input), output_range, queue);
						input.swap(output);
					}
					range::copy(input, result_output, queue);
				}
			};
			template<>
			class backward_top<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_delta,
						boost::compute::command_queue& queue) {
					gpu_vector delta(initial_delta.begin(), initial_delta.end(), queue);
					gpu_vector prev_delta(queue.get_context());
					auto prev_delta_range = range::to_range(prev_delta);

					// call backward except the top layer
					for(int i = layers.size()-1; i >= 1; --i) {
						auto& l = layers.at(i);
						prev_delta.resize(::neu::layer::whole_input_size(l), queue);
						l.backward(
							range::to_range(delta), prev_delta_range,
							queue);
						delta.swap(prev_delta);
					}

					// call backward_top on the top layer
					layers.front().backward_top(range::to_range(delta), queue);
				}
			};
			template<>
			class backward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_delta,
						OutputRange& result_prev_delta,
						boost::compute::command_queue& queue) {
					gpu_vector delta(initial_delta.begin(), initial_delta.end(), queue);
					gpu_vector prev_delta(queue.get_context());
					auto prev_delta_range = range::to_range(prev_delta);

					for(int i = layers.size()-1; i >= 0; --i) {
						auto& l = layers.at(i);
						prev_delta.resize(::neu::layer::whole_input_size(l), queue);
						l.backward(
							range::to_range(delta), prev_delta_range,
							queue);
						delta.swap(prev_delta);
					}
					range::copy(delta, result_prev_delta, queue);
				}
			};
			template<>
			class update<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						boost::compute::command_queue& queue) {
					for(auto& l : layers) {
						l.update(queue);
					}
				}
			};
			template<>
			class serialize<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& layers,
						YAML::Emitter& emitter, boost::compute::command_queue& queue) {
					emitter << YAML::BeginMap
						<< YAML::Key << "layer_type"
							<< YAML::Value << "any_layer_vector"
						<< YAML::Key << "input_dim"
							<< YAML::Value << ::neu::layer::input_dim(layers)
						<< YAML::Key << "output_dim"
							<< YAML::Value << ::neu::layer::output_dim(layers)
						<< YAML::Key << "batch_size"
							<< YAML::Value << ::neu::layer::batch_size(layers)
						<< YAML::Key << "layers" << YAML::Value
							<< YAML::BeginSeq;
					for(auto const& l : layers) {
						::neu::layer::serialize(l, emitter, queue);
					}
					emitter << YAML::EndSeq << YAML::EndMap;
				}
			};
		}
		decltype(auto) deserialize_any_layer_vector(YAML::Node const& node,
				boost::compute::command_queue& queue) {
			NEU_ASSERT(node["layer_type"].as<std::string>() == "any_layer_vector");
			auto layers_node = node["layers"];
			std::vector<neu::layer::any_layer> layers;
			for(auto const& ln : layers_node) {
				layers.push_back(::neu::layer::deserialize(ln, queue));
			}
			return layers;
		}
	}
}// namespace neu

#endif //NEU_ANY_LAYER_VECTOR_HPP
<commit_msg>fix range resize<commit_after>#ifndef NEU_ANY_LAYER_VECTOR_HPP
#define NEU_ANY_LAYER_VECTOR_HPP
//20150914
#include <vector>
#include <neu/basic_type.hpp>
#include <neu/range/algorithm.hpp>
#include <neu/range/gpu_buffer_range.hpp>
#include <neu/layer/traits.hpp>
#include <neu/layer/any_layer.hpp>
#include <neu/layer/deserialize_fwd.hpp>
namespace neu {
	namespace layer {
		namespace traits {
			template<>
			class input_rank<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::input_rank(alv.front());
				}
			};
			template<>
			class output_rank<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::output_rank(alv.back());
				}
			};
			template<>
			class input_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv, rank_id ri) {
					return ::neu::layer::input_size(alv.front(), ri);
				}
			};
			template<>
			class output_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv, rank_id ri) {
					return ::neu::layer::output_size(alv.back(), ri);
				}
			};
			template<>
			class batch_size<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& alv) {
					return ::neu::layer::batch_size(alv.front());
				}
			};
			template<>
			class test_forward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(
						std::vector<neu::layer::any_layer>& layers,
						std::size_t batch_size,
						InputRange const& initial_input, OutputRange& result_output,
						boost::compute::command_queue& queue) {
					gpu_vector input(initial_input.begin(), initial_input.end(), queue);
					gpu_vector output(queue.get_context());
					for(auto& l : layers) {
						output.resize(::neu::layer::whole_output_size(l), queue);
						auto output_range = range::to_range(output);
						l.test_forward(batch_size,
							range::to_range(input), output_range, queue);
						input.swap(output);
					}
					range::copy(input, result_output, queue);
				}
			};
			template<>
			class forward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_input, OutputRange& result_output,
						boost::compute::command_queue& queue) {
					gpu_vector input(initial_input.begin(), initial_input.end(), queue);
					gpu_vector output(queue.get_context());
					for(auto& l : layers) {
						output.resize(::neu::layer::whole_output_size(l), queue);
						auto output_range = range::to_range(output);
						l.forward(range::to_range(input), output_range, queue);
						input.swap(output);
					}
					range::copy(input, result_output, queue);
				}
			};
			template<>
			class backward_top<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_delta,
						boost::compute::command_queue& queue) {
					gpu_vector delta(initial_delta.begin(), initial_delta.end(), queue);
					gpu_vector prev_delta(queue.get_context());

					// call backward except the top layer
					for(int i = layers.size()-1; i >= 1; --i) {
						auto& l = layers.at(i);
						prev_delta.resize(::neu::layer::whole_input_size(l), queue);
						auto prev_delta_range = range::to_range(prev_delta);
						l.backward(
							range::to_range(delta), prev_delta_range,
							queue);
						delta.swap(prev_delta);
					}

					// call backward_top on the top layer
					layers.front().backward_top(range::to_range(delta), queue);
				}
			};
			template<>
			class backward<std::vector<neu::layer::any_layer>> {
			public:
				template<typename InputRange, typename OutputRange>
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						InputRange const& initial_delta,
						OutputRange& result_prev_delta,
						boost::compute::command_queue& queue) {
					gpu_vector delta(initial_delta.begin(), initial_delta.end(), queue);
					gpu_vector prev_delta(queue.get_context());

					for(int i = layers.size()-1; i >= 0; --i) {
						auto& l = layers.at(i);
						prev_delta.resize(::neu::layer::whole_input_size(l), queue);
						auto prev_delta_range = range::to_range(prev_delta);
						l.backward(
							range::to_range(delta), prev_delta_range,
							queue);
						delta.swap(prev_delta);
					}
					range::copy(delta, result_prev_delta, queue);
				}
			};
			template<>
			class update<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(std::vector<neu::layer::any_layer>& layers,
						boost::compute::command_queue& queue) {
					for(auto& l : layers) {
						l.update(queue);
					}
				}
			};
			template<>
			class serialize<std::vector<neu::layer::any_layer>> {
			public:
				static decltype(auto) call(
						std::vector<neu::layer::any_layer> const& layers,
						YAML::Emitter& emitter, boost::compute::command_queue& queue) {
					emitter << YAML::BeginMap
						<< YAML::Key << "layer_type"
							<< YAML::Value << "any_layer_vector"
						<< YAML::Key << "input_dim"
							<< YAML::Value << ::neu::layer::input_dim(layers)
						<< YAML::Key << "output_dim"
							<< YAML::Value << ::neu::layer::output_dim(layers)
						<< YAML::Key << "batch_size"
							<< YAML::Value << ::neu::layer::batch_size(layers)
						<< YAML::Key << "layers" << YAML::Value
							<< YAML::BeginSeq;
					for(auto const& l : layers) {
						::neu::layer::serialize(l, emitter, queue);
					}
					emitter << YAML::EndSeq << YAML::EndMap;
				}
			};
		}
		decltype(auto) deserialize_any_layer_vector(YAML::Node const& node,
				boost::compute::command_queue& queue) {
			NEU_ASSERT(node["layer_type"].as<std::string>() == "any_layer_vector");
			auto layers_node = node["layers"];
			std::vector<neu::layer::any_layer> layers;
			for(auto const& ln : layers_node) {
				layers.push_back(::neu::layer::deserialize(ln, queue));
			}
			return layers;
		}
	}
}// namespace neu

#endif //NEU_ANY_LAYER_VECTOR_HPP
<|endoftext|>


<commit_before>/* Copyright (C) 2004 MySQL AB

   This program 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; version 2 of the License.

   This program 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 this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "parse_output.h"

#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>

#include <stdio.h>

#include "parse.h"
#include "portability.h"

/**************************************************************************
  Private module implementation.
**************************************************************************/

namespace { /* no-indent */

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

void trim_space(const char **text, uint *word_len)
{
  const char *start= *text;
  while (*start != 0 && *start == ' ')
    start++;
  *text= start;

  int len= strlen(start);
  const char *end= start + len - 1;
  while (end > start && my_isspace(&my_charset_latin1, *end))
    end--;
  *word_len= (end - start)+1;
}

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

/**
  @brief A facade to the internal workings of optaining the output from an
  executed system process.
*/

class Mysqld_output_parser
{
public:
  Mysqld_output_parser()
  { }

  virtual ~Mysqld_output_parser()
  { }

public:
  bool parse(const char *command,
             const char *option_name_str,
             uint option_name_length,
             char *option_value_buf,
             size_t option_value_buf_size,
             enum_option_type option_type);

protected:
  /**
    @brief Run a process and attach stdout- and stdin-pipes to it.

    @param command The path to the process to be executed

    @return Error status.
      @retval TRUE An error occurred
      @retval FALSE Operation was a success
  */

  virtual bool run_command(const char *command)= 0;

  /**
    @brief Read a sequence of bytes from the executed process' stdout pipe.

    The sequence is terminated by either '\0', LF or CRLF tokens. The
    terminating token is excluded from the result.

    @param line_buffer A pointer to a character buffer
    @param line_buffer_size The size of the buffer in bytes

    @return Error status.
      @retval TRUE An error occured
      @retval FALSE Operation was a success
  */

  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size)= 0;

  /**
    @brief Release any resources needed after a execution and parsing.
  */

  virtual bool cleanup()= 0;
};

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

bool Mysqld_output_parser::parse(const char *command,
                                 const char *option_name_str,
                                 uint option_name_length,
                                 char *option_value_buf,
                                 size_t option_value_buf_size,
                                 enum_option_type option_type)
{
  /* should be enough to store the string from the output */
  const int LINE_BUFFER_SIZE= 512;
  char line_buffer[LINE_BUFFER_SIZE];

  if (run_command(command))
    return TRUE;

  while (true)
  {
    if (read_line(line_buffer, LINE_BUFFER_SIZE))
    {
      cleanup();
      return TRUE;
    }

    uint found_word_len= 0;
    char *linep= line_buffer;

    line_buffer[sizeof(line_buffer) - 1]= '\0';        /* safety */

    /* Find the word(s) we are looking for in the line. */

    linep= strstr(linep, option_name_str);

    if (!linep)
      continue;

    linep+= option_name_length;

    switch (option_type)
    {
    case GET_VALUE:
      trim_space((const char**) &linep, &found_word_len);

      if (option_value_buf_size <= found_word_len)
      {
        cleanup();
        return TRUE;
      }

      strmake(option_value_buf, linep, found_word_len);

      break;

    case GET_LINE:
      strmake(option_value_buf, linep, option_value_buf_size - 1);

      break;
    }

    cleanup();

    return FALSE;
  }
}

/**************************************************************************
  Platform-specific implementation: UNIX.
**************************************************************************/

#ifndef __WIN__

class Mysqld_output_parser_unix : public Mysqld_output_parser
{
public:
  Mysqld_output_parser_unix() :
    m_stdout(NULL)
  { }

protected:
  virtual bool run_command(const char *command);

  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size);

  virtual bool cleanup();

private:
  FILE *m_stdout;
};

bool Mysqld_output_parser_unix::run_command(const char *command)
{
  if (!(m_stdout= popen(command, "r")))
    return TRUE;

  /*
    We want fully buffered stream. We also want system to allocate
    appropriate buffer.
  */

  setvbuf(m_stdout, NULL, _IOFBF, 0);

  return FALSE;
}

bool Mysqld_output_parser_unix::read_line(char *line_buffer,
                                          uint line_buffer_size)
{
  char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout);
  /* Remove any tailing new line charaters */
  if (line_buffer[line_buffer_size-1] == LF)
   line_buffer[line_buffer_size-1]= '\0';
  return (retbuff == NULL);
}

bool Mysqld_output_parser_unix::cleanup()
{
  if (m_stdout)
    pclose(m_stdout);

  return FALSE;
}

#else /* Windows */

/**************************************************************************
  Platform-specific implementation: Windows.
**************************************************************************/

class Mysqld_output_parser_win : public Mysqld_output_parser
{
public:
  Mysqld_output_parser_win() :
      m_internal_buffer(NULL),
      m_internal_buffer_offset(0),
      m_internal_buffer_size(0)
  { }

protected:
  virtual bool run_command(const char *command);
  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size);
  virtual bool cleanup();

private:
  HANDLE m_h_child_stdout_wr;
  HANDLE m_h_child_stdout_rd;
  uint m_internal_buffer_offset;
  uint m_internal_buffer_size;
  char *m_internal_buffer;
};

bool Mysqld_output_parser_win::run_command(const char *command)
{
  BOOL op_status;

  SECURITY_ATTRIBUTES sa_attr;
  sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES);
  sa_attr.bInheritHandle= TRUE;
  sa_attr.lpSecurityDescriptor= NULL;

  op_status= CreatePipe(&m_h_child_stdout_rd,
                        &m_h_child_stdout_wr,
                        &sa_attr,
                        0 /* Use system-default buffer size. */);

  if (!op_status)
    return TRUE;

  SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0);

  STARTUPINFO si_start_info;
  ZeroMemory(&si_start_info, sizeof(STARTUPINFO));
  si_start_info.cb= sizeof(STARTUPINFO);
  si_start_info.hStdError= m_h_child_stdout_wr;
  si_start_info.hStdOutput= m_h_child_stdout_wr;
  si_start_info.dwFlags|= STARTF_USESTDHANDLES;

  PROCESS_INFORMATION pi_proc_info;

  op_status= CreateProcess(NULL,           /* Application name. */
                           (char*)command, /* Command line. */
                           NULL,           /* Process security attributes. */
                           NULL,           /* Primary thread security attr.*/
                           TRUE,           /* Handles are inherited. */
                           0,              /* Creation flags. */
                           NULL,           /* Use parent's environment. */
                           NULL,           /* Use parent's curr. directory. */
                           &si_start_info, /* STARTUPINFO pointer. */
                           &pi_proc_info); /* Rec. PROCESS_INFORMATION. */

  if (!retval)
  {
    CloseHandle(m_h_child_stdout_rd);
    CloseHandle(m_h_child_stdout_wr);

    return TRUE;
  }

  /* Close unnessary handles. */

  CloseHandle(pi_proc_info.hProcess);
  CloseHandle(pi_proc_info.hThread);

  return FALSE;
}

bool Mysqld_output_parser_win::read_line(char *line_buffer,
                                         uint line_buffer_size)
{
  DWORD dw_read_count= m_internal_buffer_size;
  bzero(line_buffer,line_buffer_size);
  char *buff_ptr= line_buffer;
  char ch;

  while (buff_ptr - line_buffer < line_buffer_size)
  {
    do
    {
      ReadFile(m_h_child_stdout_rd, &ch,
               1, &dw_read_count, NULL);
    } while ((ch == CR || ch == LF) && buff_ptr == line_buffer);

    if (dw_read_count == 0)
      return TRUE;

    if (ch == CR || ch == LF)
      break;

    *buff_ptr++ = ch;
  }

  return FALSE;
}

bool Mysqld_output_parser_win::cleanup()
{
  /* Close all handles. */

  CloseHandle(m_h_child_stdout_wr);
  CloseHandle(m_h_child_stdout_rd);

  return FALSE;
}
#endif

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

} /* End of private module implementation. */

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

/**
  @brief Parse output of the given command

  @param      command               The command to execute.
  @param      option_name_str       Option name.
  @param      option_name_length    Length of the option name.
  @param[out] option_value_buf      The buffer to store option value.
  @param      option_value_buf_size Size of the option value buffer.
  @param      option_type           Type of the option:
                                      - GET_LINE if we want to get all the
                                        line after the option name;
                                      - GET_VALUE otherwise.

  Execute the process by running "command". Find the "option name" and
  return the next word if "option_type" is GET_VALUE. Return the rest of
  the parsed string otherwise.

  @note This function has a separate windows implementation.

  @return The error status.
    @retval FALSE Ok, the option name has been found.
    @retval TRUE Error occured or the option name is not found.
*/

bool parse_output_and_get_value(const char *command,
                                const char *option_name_str,
                                uint option_name_length,
                                char *option_value_buf,
                                size_t option_value_buf_size,
                                enum_option_type option_type)
{
#ifndef __WIN__
  Mysqld_output_parser_unix parser;
#else /* __WIN__ */
  Mysqld_output_parser_win parser;
#endif

  return parser.parse(command,
                      option_name_str,
                      option_name_length,
                      option_value_buf,
                      option_value_buf_size,
                      option_type);
}
<commit_msg>Fix of build errors for windows.<commit_after>/* Copyright (C) 2004 MySQL AB

   This program 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; version 2 of the License.

   This program 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 this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "parse_output.h"

#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>

#include <stdio.h>

#include "parse.h"
#include "portability.h"

/**************************************************************************
  Private module implementation.
**************************************************************************/

namespace { /* no-indent */

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

void trim_space(const char **text, uint *word_len)
{
  const char *start= *text;
  while (*start != 0 && *start == ' ')
    start++;
  *text= start;

  int len= strlen(start);
  const char *end= start + len - 1;
  while (end > start && my_isspace(&my_charset_latin1, *end))
    end--;
  *word_len= (end - start)+1;
}

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

/**
  @brief A facade to the internal workings of optaining the output from an
  executed system process.
*/

class Mysqld_output_parser
{
public:
  Mysqld_output_parser()
  { }

  virtual ~Mysqld_output_parser()
  { }

public:
  bool parse(const char *command,
             const char *option_name_str,
             uint option_name_length,
             char *option_value_buf,
             size_t option_value_buf_size,
             enum_option_type option_type);

protected:
  /**
    @brief Run a process and attach stdout- and stdin-pipes to it.

    @param command The path to the process to be executed

    @return Error status.
      @retval TRUE An error occurred
      @retval FALSE Operation was a success
  */

  virtual bool run_command(const char *command)= 0;

  /**
    @brief Read a sequence of bytes from the executed process' stdout pipe.

    The sequence is terminated by either '\0', LF or CRLF tokens. The
    terminating token is excluded from the result.

    @param line_buffer A pointer to a character buffer
    @param line_buffer_size The size of the buffer in bytes

    @return Error status.
      @retval TRUE An error occured
      @retval FALSE Operation was a success
  */

  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size)= 0;

  /**
    @brief Release any resources needed after a execution and parsing.
  */

  virtual bool cleanup()= 0;
};

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

bool Mysqld_output_parser::parse(const char *command,
                                 const char *option_name_str,
                                 uint option_name_length,
                                 char *option_value_buf,
                                 size_t option_value_buf_size,
                                 enum_option_type option_type)
{
  /* should be enough to store the string from the output */
  const int LINE_BUFFER_SIZE= 512;
  char line_buffer[LINE_BUFFER_SIZE];

  if (run_command(command))
    return TRUE;

  while (true)
  {
    if (read_line(line_buffer, LINE_BUFFER_SIZE))
    {
      cleanup();
      return TRUE;
    }

    uint found_word_len= 0;
    char *linep= line_buffer;

    line_buffer[sizeof(line_buffer) - 1]= '\0';        /* safety */

    /* Find the word(s) we are looking for in the line. */

    linep= strstr(linep, option_name_str);

    if (!linep)
      continue;

    linep+= option_name_length;

    switch (option_type)
    {
    case GET_VALUE:
      trim_space((const char**) &linep, &found_word_len);

      if (option_value_buf_size <= found_word_len)
      {
        cleanup();
        return TRUE;
      }

      strmake(option_value_buf, linep, found_word_len);

      break;

    case GET_LINE:
      strmake(option_value_buf, linep, option_value_buf_size - 1);

      break;
    }

    cleanup();

    return FALSE;
  }
}

/**************************************************************************
  Platform-specific implementation: UNIX.
**************************************************************************/

#ifndef __WIN__

class Mysqld_output_parser_unix : public Mysqld_output_parser
{
public:
  Mysqld_output_parser_unix() :
    m_stdout(NULL)
  { }

protected:
  virtual bool run_command(const char *command);

  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size);

  virtual bool cleanup();

private:
  FILE *m_stdout;
};

bool Mysqld_output_parser_unix::run_command(const char *command)
{
  if (!(m_stdout= popen(command, "r")))
    return TRUE;

  /*
    We want fully buffered stream. We also want system to allocate
    appropriate buffer.
  */

  setvbuf(m_stdout, NULL, _IOFBF, 0);

  return FALSE;
}

bool Mysqld_output_parser_unix::read_line(char *line_buffer,
                                          uint line_buffer_size)
{
  char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout);
  /* Remove any tailing new line charaters */
  if (line_buffer[line_buffer_size-1] == LF)
   line_buffer[line_buffer_size-1]= '\0';
  return (retbuff == NULL);
}

bool Mysqld_output_parser_unix::cleanup()
{
  if (m_stdout)
    pclose(m_stdout);

  return FALSE;
}

#else /* Windows */

/**************************************************************************
  Platform-specific implementation: Windows.
**************************************************************************/

class Mysqld_output_parser_win : public Mysqld_output_parser
{
public:
  Mysqld_output_parser_win() :
      m_internal_buffer(NULL),
      m_internal_buffer_offset(0),
      m_internal_buffer_size(0)
  { }

protected:
  virtual bool run_command(const char *command);
  virtual bool read_line(char *line_buffer,
                         uint line_buffer_size);
  virtual bool cleanup();

private:
  HANDLE m_h_child_stdout_wr;
  HANDLE m_h_child_stdout_rd;
  uint m_internal_buffer_offset;
  uint m_internal_buffer_size;
  char *m_internal_buffer;
};

bool Mysqld_output_parser_win::run_command(const char *command)
{
  BOOL op_status;

  SECURITY_ATTRIBUTES sa_attr;
  sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES);
  sa_attr.bInheritHandle= TRUE;
  sa_attr.lpSecurityDescriptor= NULL;

  op_status= CreatePipe(&m_h_child_stdout_rd,
                        &m_h_child_stdout_wr,
                        &sa_attr,
                        0 /* Use system-default buffer size. */);

  if (!op_status)
    return TRUE;

  SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0);

  STARTUPINFO si_start_info;
  ZeroMemory(&si_start_info, sizeof(STARTUPINFO));
  si_start_info.cb= sizeof(STARTUPINFO);
  si_start_info.hStdError= m_h_child_stdout_wr;
  si_start_info.hStdOutput= m_h_child_stdout_wr;
  si_start_info.dwFlags|= STARTF_USESTDHANDLES;

  PROCESS_INFORMATION pi_proc_info;

  op_status= CreateProcess(NULL,           /* Application name. */
                           (char*)command, /* Command line. */
                           NULL,           /* Process security attributes. */
                           NULL,           /* Primary thread security attr.*/
                           TRUE,           /* Handles are inherited. */
                           0,              /* Creation flags. */
                           NULL,           /* Use parent's environment. */
                           NULL,           /* Use parent's curr. directory. */
                           &si_start_info, /* STARTUPINFO pointer. */
                           &pi_proc_info); /* Rec. PROCESS_INFORMATION. */

  if (!op_status)
  {
    CloseHandle(m_h_child_stdout_rd);
    CloseHandle(m_h_child_stdout_wr);

    return TRUE;
  }

  /* Close unnessary handles. */

  CloseHandle(pi_proc_info.hProcess);
  CloseHandle(pi_proc_info.hThread);

  return FALSE;
}

bool Mysqld_output_parser_win::read_line(char *line_buffer,
                                         uint line_buffer_size)
{
  DWORD dw_read_count= m_internal_buffer_size;
  bzero(line_buffer,line_buffer_size);
  char *buff_ptr= line_buffer;
  char ch;

  while ((unsigned)(buff_ptr - line_buffer) < line_buffer_size)
  {
    do
    {
      ReadFile(m_h_child_stdout_rd, &ch,
               1, &dw_read_count, NULL);
    } while ((ch == CR || ch == LF) && buff_ptr == line_buffer);

    if (dw_read_count == 0)
      return TRUE;

    if (ch == CR || ch == LF)
      break;

    *buff_ptr++ = ch;
  }

  return FALSE;
}

bool Mysqld_output_parser_win::cleanup()
{
  /* Close all handles. */

  CloseHandle(m_h_child_stdout_wr);
  CloseHandle(m_h_child_stdout_rd);

  return FALSE;
}
#endif

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

} /* End of private module implementation. */

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

/**
  @brief Parse output of the given command

  @param      command               The command to execute.
  @param      option_name_str       Option name.
  @param      option_name_length    Length of the option name.
  @param[out] option_value_buf      The buffer to store option value.
  @param      option_value_buf_size Size of the option value buffer.
  @param      option_type           Type of the option:
                                      - GET_LINE if we want to get all the
                                        line after the option name;
                                      - GET_VALUE otherwise.

  Execute the process by running "command". Find the "option name" and
  return the next word if "option_type" is GET_VALUE. Return the rest of
  the parsed string otherwise.

  @note This function has a separate windows implementation.

  @return The error status.
    @retval FALSE Ok, the option name has been found.
    @retval TRUE Error occured or the option name is not found.
*/

bool parse_output_and_get_value(const char *command,
                                const char *option_name_str,
                                uint option_name_length,
                                char *option_value_buf,
                                size_t option_value_buf_size,
                                enum_option_type option_type)
{
#ifndef __WIN__
  Mysqld_output_parser_unix parser;
#else /* __WIN__ */
  Mysqld_output_parser_win parser;
#endif

  return parser.parse(command,
                      option_name_str,
                      option_name_length,
                      option_value_buf,
                      option_value_buf_size,
                      option_type);
}
<|endoftext|>


<commit_before>#include <Windows.h>
#include <cstdio>
#include <cstring>

using namespace std;

enum DisplaySelection {
	DS_MONITOR = 1,
	DS_HDMI = 2,
	DS_TOGGLE = 3,
};

/* This array must match the above enum */
char *DisplaySelectionString[] = {
	"Monitor",
	"HDMI",
	"Toggle",
};

#define MAX_PATH_ELEMENTS 128
#define MAX_MODE_ELEMENTS 8

int main(int argc, char *argv[])
{
	LONG retval;
	DISPLAYCONFIG_PATH_INFO pathArray[MAX_PATH_ELEMENTS];
	DISPLAYCONFIG_MODE_INFO modeArray[MAX_MODE_ELEMENTS];
	UINT32 numPathElements = sizeof(pathArray)/sizeof(pathArray[0]);
	UINT32 numModeElements = sizeof(modeArray)/sizeof(modeArray[0]);
	UINT32 hdmi_idx = MAX_PATH_ELEMENTS;
	UINT32 dvi_idx = MAX_PATH_ELEMENTS;
	DisplaySelection current_selection = DS_TOGGLE;

	retval = QueryDisplayConfig(QDC_ALL_PATHS, &numPathElements, pathArray, &numModeElements, modeArray, NULL);

	if (ERROR_SUCCESS != retval) {
		printf("Query failure - unable to set new path!!\n");
		if (ERROR_INSUFFICIENT_BUFFER == retval)
			printf("Insufficient buffer failure; increase MAX_PATH_ELEMENTS or MAX_MODE_ELEMENTS and re-compile.");
		return 2;
	}

	/* Find the target paths we care about */
	for (unsigned int path = 0; path < numPathElements; path++) {
		if (pathArray[path].sourceInfo.modeInfoIdx >= 0
			&& pathArray[path].sourceInfo.modeInfoIdx < numModeElements) {

			if ((pathArray[path].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI)
				&& (pathArray[path].targetInfo.targetAvailable == TRUE)) {
				hdmi_idx = path;
				if (DISPLAYCONFIG_PATH_ACTIVE & pathArray[path].flags)
					current_selection = DS_HDMI;
			}
			else if ((pathArray[path].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI)
				&& (pathArray[path].targetInfo.targetAvailable == TRUE)) {
				dvi_idx = path;
				if (DISPLAYCONFIG_PATH_ACTIVE & pathArray[path].flags)
					current_selection = DS_MONITOR;
			}
		}
	}
	if (current_selection == DS_TOGGLE) {
		printf("Unable to determine current video output -- exiting\n");
		return 3;
	}

	/* No argument means toggle output */
	unsigned int input = DS_TOGGLE;
	DISPLAYCONFIG_PATH_INFO desiredSettings;

	/* Try to get the desired output setting */
	if (argc > 1) {
		input = atoi(argv[1]);
	}

	/* input should match the enum above. indexed into the string array as (input - 1) */
	if ((input - 1) < (sizeof(DisplaySelectionString) / sizeof(DisplaySelectionString[0]))) {
		printf("Device to be selected is the %s selection.\n", DisplaySelectionString[input - 1]);
		if ((DS_MONITOR == input && current_selection == DS_HDMI) || (DS_TOGGLE == input && DS_HDMI == current_selection)) {
			if (dvi_idx < MAX_PATH_ELEMENTS)
				desiredSettings = pathArray[dvi_idx];
			else {
				printf("Attempting to switch to DVI, but unable to find config element -- exiting\n");
				return 4;
			}
		}
		else if ((DS_HDMI == input && current_selection == DS_MONITOR) || (DS_TOGGLE == input && DS_MONITOR == current_selection))
		{
			if (hdmi_idx < MAX_PATH_ELEMENTS)
				desiredSettings = pathArray[hdmi_idx];
			else {
				printf("Attempting to switch to HDMI, but unable to find config element -- exiting\n");
				return 5;
			}
		}
		else
		{
			printf("Output already set to the desired selection.\n");
			return 0;
		}
	}
	else
	{
		printf("Unknown display selection: %d\n\n", input);
		printf("Usage:\n");
		printf("\tDisplayController_Config.exe [new_output]\n");
		for (int i = 0; i < sizeof(DisplaySelectionString) / sizeof(DisplaySelectionString[0]); i++) {
			printf("\t\t%d: %s\n", i + 1, DisplaySelectionString[i]);
		}
		printf("\n\tNo parameter means Toggle\n");
		return 1;
	}

	/* If we get here we will attempt to set the path -- let SetDisplayConfig pick the mode info */
	desiredSettings.flags = DISPLAYCONFIG_PATH_ACTIVE;
	desiredSettings.targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
	desiredSettings.sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
	retval = SetDisplayConfig(1, &desiredSettings, 0, NULL, SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES);

	if (ERROR_SUCCESS != retval) {
		printf("Unable to set -- trying again with SetDisplayConfig creating mode info\n");
		retval = SetDisplayConfig(1, &desiredSettings, 0, NULL, SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_CHANGES |
													SDC_ALLOW_PATH_ORDER_CHANGES |SDC_USE_SUPPLIED_DISPLAY_CONFIG);
		if (ERROR_SUCCESS != retval) {
			printf("Unable to set the new display config!!\n");
			return 3;
		}
	}

	return 0;
}<commit_msg>Add "Both" option<commit_after>#include <Windows.h>
#include <cstdio>
#include <cstring>

using namespace std;

enum DisplaySelection {
	DS_MONITOR = 1,
	DS_HDMI = 2,
	DS_BOTH = 3,
	DS_CYCLE = 4,
};

/* This array must match the above enum */
const char *DisplaySelectionStrings[] = {
	"Monitor",
	"HDMI",
	"Both",
	"Cycle",
};
static const unsigned int MaxSelectionStrings = sizeof(DisplaySelectionStrings) / sizeof(DisplaySelectionStrings[0]);

#define DS_SELECT_NONE_FLAG 0
#define DS_SELECT_MONITOR_FLAG 1
#define DS_SELECT_HDMI_FLAG 2
typedef unsigned int DisplaySelectionFlags;

/* This array is used to list the order of output combos for the Cycle option.
   It is also contains the flags for each selection at (DS_* - 1) */
const DisplaySelectionFlags OptionFlags[] = {
	DS_SELECT_MONITOR_FLAG,                       /* DVI */
	DS_SELECT_HDMI_FLAG,                          /* HDMI */
	DS_SELECT_MONITOR_FLAG | DS_SELECT_HDMI_FLAG, /* Both */
};
static const unsigned int MaxOptions = sizeof(OptionFlags) / sizeof(OptionFlags[0]);

static DisplaySelectionFlags GetNextOption(DisplaySelectionFlags current_selection)
{
	unsigned int curr_idx = 0;
	for (curr_idx = 0; curr_idx < MaxOptions; curr_idx++) {
		if (OptionFlags[curr_idx] == current_selection)
			break;
	}
	if (curr_idx == MaxOptions) {
		return OptionFlags[0];
	}
	return OptionFlags[(curr_idx + 1) % MaxOptions];
}

#define MAX_PATH_ELEMENTS 128
#define MAX_MODE_ELEMENTS 8

int main(int argc, char *argv[])
{
	LONG retval;
	DISPLAYCONFIG_PATH_INFO pathArray[MAX_PATH_ELEMENTS];
	DISPLAYCONFIG_MODE_INFO modeArray[MAX_MODE_ELEMENTS];
	UINT32 numPathElements = sizeof(pathArray)/sizeof(pathArray[0]);
	UINT32 numModeElements = sizeof(modeArray)/sizeof(modeArray[0]);
	UINT32 hdmi_idx = MAX_PATH_ELEMENTS;
	UINT32 dvi_idx = MAX_PATH_ELEMENTS;
	DisplaySelectionFlags current_selection = DS_SELECT_NONE_FLAG;

	retval = QueryDisplayConfig(QDC_ALL_PATHS, &numPathElements, pathArray, &numModeElements, modeArray, NULL);

	if (ERROR_SUCCESS != retval) {
		printf("Query failure - unable to set new path!!\n");
		if (ERROR_INSUFFICIENT_BUFFER == retval)
			printf("Insufficient buffer failure; increase MAX_PATH_ELEMENTS or MAX_MODE_ELEMENTS and re-compile.");
		return 2;
	}

	/* Find the target paths we care about */
	for (unsigned int path = 0; path < numPathElements; path++) {
		if (pathArray[path].sourceInfo.modeInfoIdx >= 0
			&& pathArray[path].sourceInfo.modeInfoIdx < numModeElements) {

			if ((pathArray[path].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI)
				&& (pathArray[path].targetInfo.targetAvailable == TRUE)) {
				hdmi_idx = path;
				if (DISPLAYCONFIG_PATH_ACTIVE & pathArray[path].flags)
					current_selection |= DS_SELECT_HDMI_FLAG;
			}
			else if ((pathArray[path].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI)
				&& (pathArray[path].targetInfo.targetAvailable == TRUE)) {
				dvi_idx = path;
				if (DISPLAYCONFIG_PATH_ACTIVE & pathArray[path].flags)
					current_selection |= DS_SELECT_MONITOR_FLAG;
			}
		}
	}
	if (current_selection == DS_SELECT_NONE_FLAG) {
		printf("Unable to determine current video output -- exiting\n");
		return 3;
	}

	/* No argument means cycle output */
	unsigned int input = DS_CYCLE;
	DISPLAYCONFIG_PATH_INFO desiredSettings[2];
	unsigned int num_desired_settings = 0;

	/* Try to get the desired output setting */
	if (argc > 1) {
		input = atoi(argv[1]);
	}

	/* input should match the enum above. indexed into the string array as (input - 1) */
	if ((input - 1) < MaxSelectionStrings) {
		printf("Device to be selected is the %s selection.\n", DisplaySelectionStrings[input - 1]);
		DisplaySelectionFlags desired_selection;
		if (DS_CYCLE == input)
			desired_selection = GetNextOption(current_selection);
		else
			desired_selection = OptionFlags[input - 1];

		if (desired_selection != current_selection)
		{
			/* HDMI will get priority if multiple outputs being attempted */
			if (desired_selection & DS_SELECT_HDMI_FLAG)
			{
				if (hdmi_idx < MAX_PATH_ELEMENTS)
					desiredSettings[num_desired_settings++] = pathArray[hdmi_idx];
				else {
					printf("Attempting to enable HDMI, but unable to find config element -- exiting\n");
					return 4;
				}

			}
			if (desired_selection & DS_SELECT_MONITOR_FLAG)
			{
				if (dvi_idx < MAX_PATH_ELEMENTS)
					desiredSettings[num_desired_settings++] = pathArray[dvi_idx];
				else {
					printf("Attempting to enable DVI, but unable to find config element -- exiting\n");
					return 5;
				}
			}
		}
		else
		{
			printf("Output already set to the desired selection.\n");
			return 0;
		}
	}
	else
	{
		printf("Unknown display selection: %d\n\n", input);
		printf("Usage:\n");
		printf("\tDisplayController_Config.exe [new_output]\n");
		for (int i = 0; i < MaxSelectionStrings; i++) {
			printf("\t\t%d: %s\n", i + 1, DisplaySelectionStrings[i]);
		}
		printf("\n\tNo parameter means Cycle\n");
		return 1;
	}

	/* If we get here we will attempt to set the path -- let SetDisplayConfig pick the mode info */
	unsigned int setting = 0;
	for (setting = 0; setting < num_desired_settings; setting++) {
		desiredSettings[setting].flags = DISPLAYCONFIG_PATH_ACTIVE;
		desiredSettings[setting].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
		desiredSettings[setting].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
	}
	retval = SetDisplayConfig(num_desired_settings, desiredSettings, 0, NULL,
							SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES);

	if (ERROR_SUCCESS != retval) {
		printf("Unable to set -- trying again with SetDisplayConfig creating mode info\n");
		retval = SetDisplayConfig(num_desired_settings, desiredSettings, 0, NULL, SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_CHANGES |
															SDC_ALLOW_PATH_ORDER_CHANGES |SDC_USE_SUPPLIED_DISPLAY_CONFIG);
		if (ERROR_SUCCESS != retval) {
			printf("Unable to set the new display config!!\n");
			return 3;
		}
	}

	return 0;
}<|endoftext|>


<commit_before>// Copyright 2020, Intel Corporation

#include "mlir/Conversion/GPUToVulkan/ConvertGPUToVulkanPass.h"
#include "mlir/Conversion/SCFToGPU/SCFToGPU.h"
#include "mlir/Conversion/SCFToGPU/SCFToGPUPass.h"
#include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
#include "mlir/Conversion/StandardToSPIRV/ConvertStandardToSPIRVPass.h"
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/GPU/Passes.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/SPIRV/Passes.h"
#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/SPIRVOps.h"
#include "mlir/Dialect/StandardOps/Transforms/Passes.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Transforms/Passes.h"

#include "pmlc/compiler/registry.h"
#include "pmlc/conversion/gpu/lowering.h"
#include "pmlc/conversion/gpu_to_spirv/passes.h"
#include "pmlc/conversion/pxa_to_affine/passes.h"
#include "pmlc/conversion/stdx_to_llvm/passes.h"
#include "pmlc/conversion/tile_to_pxa/passes.h"
#include "pmlc/dialect/pxa/transforms/passes.h"
#include "pmlc/dialect/stdx/ir/ops.h"
#include "pmlc/dialect/stdx/transforms/passes.h"
#include "pmlc/dialect/tile/transforms/passes.h"
#include "pmlc/target/intel_gen/pass_detail.h"
#include "pmlc/target/intel_gen/passes.h"
#include "pmlc/target/x86/passes.h"

using namespace mlir; // NOLINT[build/namespaces]

namespace pmlc::target::intel_gen {

namespace pxa = pmlc::dialect::pxa;

namespace {

struct LowerPXAToAffinePass
    : public ConvertPXAToAffineBase<LowerPXAToAffinePass> {
  void runOnOperation() final {
    auto &ctx = getContext();
    conversion::pxa_to_affine::PXAToAffineConversionTarget target(ctx);

    OwningRewritePatternList patterns;
    x86::populatePXAPrngToAffineConversionPatterns(patterns, &ctx);
    conversion::pxa_to_affine::populatePXAToAffineConversionPatterns(patterns,
                                                                     &ctx);

    if (failed(applyPartialConversion(getOperation(), target, patterns,
                                      nullptr))) {
      getOperation().emitError("Error lowering pxa -> affine\n");
      signalPassFailure();
    }
  }
};

struct ConvertStandardToLLVMPass
    : public ConvertStandardToLLVMBase<ConvertStandardToLLVMPass> {
  void runOnOperation() override {
    auto module = getOperation();
    auto *context = module.getContext();

    LowerToLLVMOptions options = {
        /*useBarePtrCallConv=*/false,
        /*emitCWrappers=*/true,
        /*indexBitwidth=*/kDeriveIndexBitwidthFromDataLayout,
        /*useAlignedAlloc=*/false,
    };
    LLVMTypeConverter typeConverter(context, options);

    OwningRewritePatternList patterns;
    populateExpandTanhPattern(patterns, context);
    populateStdToLLVMConversionPatterns(typeConverter, patterns);
    conversion::stdx_to_llvm::populateStdXToLLVMConversionPatterns(
        typeConverter, patterns);

    LLVMConversionTarget target(*context);
    if (failed(applyPartialConversion(module, target, patterns))) {
      signalPassFailure();
    }
  }
};

struct ParallelLoopToGpuPass
    : public ConvertParallelLoopToGpuBase<ParallelLoopToGpuPass> {
  void runOnOperation() override {
    OwningRewritePatternList patterns;
    populateParallelLoopToGPUPatterns(patterns, &getContext());
    ConversionTarget target(getContext());
    target.addLegalDialect<StandardOpsDialect>();
    target.addLegalDialect<pmlc::dialect::stdx::StdXDialect>();
    target.addLegalDialect<AffineDialect>();
    target.addLegalDialect<gpu::GPUDialect>();
    target.addLegalDialect<scf::SCFDialect>();
    target.addIllegalOp<scf::ParallelOp>();
    if (failed(applyPartialConversion(getOperation(), target, patterns)))
      signalPassFailure();
  }
};

} // namespace

std::unique_ptr<Pass> createConvertStandardToLLVM() {
  return std::make_unique<ConvertStandardToLLVMPass>();
}

std::unique_ptr<Pass> createParallelLoopToGpuPass() {
  return std::make_unique<ParallelLoopToGpuPass>();
}

std::unique_ptr<Pass> createLowerPXAToAffinePass() {
  return std::make_unique<LowerPXAToAffinePass>();
}

void pipelineBuilder(OpPassManager &pm) {
  // Bound + pad initial tile code
  pm.addPass(dialect::tile::createComputeBoundsPass());
  pm.addPass(dialect::tile::createPadRangesPass());
  pm.addPass(dialect::tile::createPadConstraintsPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Lower to PXA
  pm.addPass(conversion::tile_to_pxa::createLowerTileToPXAPass());
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do subgroup or accumulation
  pm.addPass(pmlc::dialect::pxa::createSubgroupsPass());
  // pm.addPass(pmlc::dialect::pxa::createTileAccumulatePass());
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass(/*promote=*/false));
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Assign GPU blocks + threads to outermost loop
  pm.addPass(pmlc::dialect::pxa::createGPUThreadPass(/*maxThreads=*/64));
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Lower out of PXA memory semantics
  pm.addPass(createLowerPXAToAffinePass());

  // Unroll affine.for loops.
  pm.addPass(createLoopUnrollPass(
                      /*unrollFactor=*/6,
                      /*unrollUpToFactor=*/true));
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Pack dims
  pm.addPass(createAffineIndexPackPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do a custom version of lower-affine which also set GPU mappings
  pm.addPass(createIntelGenLowerAffinePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Fix booleans
  pm.addPass(dialect::stdx::createI1StorageToI32Pass());

  // Devectorize
  pm.addPass(createSubgroupBroadcastPass());
  pm.addPass(createCSEPass());

  // Lower mapped scf.parallel's to GPU
  pm.addPass(createParallelLoopToGpuPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do kernel outlining
  pm.addPass(conversion::gpu::createGpuKernelOutliningPass());

  // GPU to SPIR-V.
  pm.addPass(createLegalizeStdOpsForSPIRVLoweringPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());
  pm.addPass(conversion::gpu_to_spirv::createGPUToSPIRVCustomPass());

  // SPIR-V passes for lowering attributes.
  pm.addPass(spirv::createLowerABIAttributesPass());
  pm.addPass(spirv::createUpdateVersionCapabilityExtensionPass());

  // GPU to Vulkan.
  pm.addPass(conversion::gpu::createConvertGpuLaunchFuncToVulkanCallsPass());

  // Convert Vulkan calls to LLVM code
  pm.addPass(createConvertStandardToLLVM());
}

static PassPipelineRegistration<>
    passPipelineReg("target-intel_gen", "Target pipeline for Intel GEN iGPUs",
                    pipelineBuilder);

static compiler::TargetRegistration targetReg("intel_gen", pipelineBuilder);

} // namespace pmlc::target::intel_gen
<commit_msg>Adjusted the loop unroll factor (#1446)<commit_after>// Copyright 2020, Intel Corporation

#include "mlir/Conversion/GPUToVulkan/ConvertGPUToVulkanPass.h"
#include "mlir/Conversion/SCFToGPU/SCFToGPU.h"
#include "mlir/Conversion/SCFToGPU/SCFToGPUPass.h"
#include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
#include "mlir/Conversion/StandardToSPIRV/ConvertStandardToSPIRVPass.h"
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/GPU/Passes.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/SPIRV/Passes.h"
#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/SPIRVOps.h"
#include "mlir/Dialect/StandardOps/Transforms/Passes.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Transforms/Passes.h"

#include "pmlc/compiler/registry.h"
#include "pmlc/conversion/gpu/lowering.h"
#include "pmlc/conversion/gpu_to_spirv/passes.h"
#include "pmlc/conversion/pxa_to_affine/passes.h"
#include "pmlc/conversion/stdx_to_llvm/passes.h"
#include "pmlc/conversion/tile_to_pxa/passes.h"
#include "pmlc/dialect/pxa/transforms/passes.h"
#include "pmlc/dialect/stdx/ir/ops.h"
#include "pmlc/dialect/stdx/transforms/passes.h"
#include "pmlc/dialect/tile/transforms/passes.h"
#include "pmlc/target/intel_gen/pass_detail.h"
#include "pmlc/target/intel_gen/passes.h"
#include "pmlc/target/x86/passes.h"

using namespace mlir; // NOLINT[build/namespaces]

namespace pmlc::target::intel_gen {

namespace pxa = pmlc::dialect::pxa;

namespace {

struct LowerPXAToAffinePass
    : public ConvertPXAToAffineBase<LowerPXAToAffinePass> {
  void runOnOperation() final {
    auto &ctx = getContext();
    conversion::pxa_to_affine::PXAToAffineConversionTarget target(ctx);

    OwningRewritePatternList patterns;
    x86::populatePXAPrngToAffineConversionPatterns(patterns, &ctx);
    conversion::pxa_to_affine::populatePXAToAffineConversionPatterns(patterns,
                                                                     &ctx);

    if (failed(applyPartialConversion(getOperation(), target, patterns,
                                      nullptr))) {
      getOperation().emitError("Error lowering pxa -> affine\n");
      signalPassFailure();
    }
  }
};

struct ConvertStandardToLLVMPass
    : public ConvertStandardToLLVMBase<ConvertStandardToLLVMPass> {
  void runOnOperation() override {
    auto module = getOperation();
    auto *context = module.getContext();

    LowerToLLVMOptions options = {
        /*useBarePtrCallConv=*/false,
        /*emitCWrappers=*/true,
        /*indexBitwidth=*/kDeriveIndexBitwidthFromDataLayout,
        /*useAlignedAlloc=*/false,
    };
    LLVMTypeConverter typeConverter(context, options);

    OwningRewritePatternList patterns;
    populateExpandTanhPattern(patterns, context);
    populateStdToLLVMConversionPatterns(typeConverter, patterns);
    conversion::stdx_to_llvm::populateStdXToLLVMConversionPatterns(
        typeConverter, patterns);

    LLVMConversionTarget target(*context);
    if (failed(applyPartialConversion(module, target, patterns))) {
      signalPassFailure();
    }
  }
};

struct ParallelLoopToGpuPass
    : public ConvertParallelLoopToGpuBase<ParallelLoopToGpuPass> {
  void runOnOperation() override {
    OwningRewritePatternList patterns;
    populateParallelLoopToGPUPatterns(patterns, &getContext());
    ConversionTarget target(getContext());
    target.addLegalDialect<StandardOpsDialect>();
    target.addLegalDialect<pmlc::dialect::stdx::StdXDialect>();
    target.addLegalDialect<AffineDialect>();
    target.addLegalDialect<gpu::GPUDialect>();
    target.addLegalDialect<scf::SCFDialect>();
    target.addIllegalOp<scf::ParallelOp>();
    if (failed(applyPartialConversion(getOperation(), target, patterns)))
      signalPassFailure();
  }
};

} // namespace

std::unique_ptr<Pass> createConvertStandardToLLVM() {
  return std::make_unique<ConvertStandardToLLVMPass>();
}

std::unique_ptr<Pass> createParallelLoopToGpuPass() {
  return std::make_unique<ParallelLoopToGpuPass>();
}

std::unique_ptr<Pass> createLowerPXAToAffinePass() {
  return std::make_unique<LowerPXAToAffinePass>();
}

void pipelineBuilder(OpPassManager &pm) {
  // Bound + pad initial tile code
  pm.addPass(dialect::tile::createComputeBoundsPass());
  pm.addPass(dialect::tile::createPadRangesPass());
  pm.addPass(dialect::tile::createPadConstraintsPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Lower to PXA
  pm.addPass(conversion::tile_to_pxa::createLowerTileToPXAPass());
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do subgroup or accumulation
  pm.addPass(pmlc::dialect::pxa::createSubgroupsPass());
  // pm.addPass(pmlc::dialect::pxa::createTileAccumulatePass());
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass(/*promote=*/false));
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Assign GPU blocks + threads to outermost loop
  pm.addPass(pmlc::dialect::pxa::createGPUThreadPass(/*maxThreads=*/64));
  pm.addPass(pmlc::dialect::pxa::createAffineNormalizePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Lower out of PXA memory semantics
  pm.addPass(createLowerPXAToAffinePass());

  // Unroll affine.for loops.
  pm.addPass(createLoopUnrollPass(
                      /*unrollFactor=*/256,
                      /*unrollUpToFactor=*/true));
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Pack dims
  pm.addPass(createAffineIndexPackPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do a custom version of lower-affine which also set GPU mappings
  pm.addPass(createIntelGenLowerAffinePass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Fix booleans
  pm.addPass(dialect::stdx::createI1StorageToI32Pass());

  // Devectorize
  pm.addPass(createSubgroupBroadcastPass());
  pm.addPass(createCSEPass());

  // Lower mapped scf.parallel's to GPU
  pm.addPass(createParallelLoopToGpuPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());

  // Do kernel outlining
  pm.addPass(conversion::gpu::createGpuKernelOutliningPass());

  // GPU to SPIR-V.
  pm.addPass(createLegalizeStdOpsForSPIRVLoweringPass());
  pm.addPass(createCanonicalizerPass());
  pm.addPass(createCSEPass());
  pm.addPass(conversion::gpu_to_spirv::createGPUToSPIRVCustomPass());

  // SPIR-V passes for lowering attributes.
  pm.addPass(spirv::createLowerABIAttributesPass());
  pm.addPass(spirv::createUpdateVersionCapabilityExtensionPass());

  // GPU to Vulkan.
  pm.addPass(conversion::gpu::createConvertGpuLaunchFuncToVulkanCallsPass());

  // Convert Vulkan calls to LLVM code
  pm.addPass(createConvertStandardToLLVM());
}

static PassPipelineRegistration<>
    passPipelineReg("target-intel_gen", "Target pipeline for Intel GEN iGPUs",
                    pipelineBuilder);

static compiler::TargetRegistration targetReg("intel_gen", pipelineBuilder);

} // namespace pmlc::target::intel_gen
<|endoftext|>


<commit_before><commit_msg>throw error if mcnp_to_id is unsuccessful<commit_after><|endoftext|>


<commit_before><commit_msg>New correct fix for memory leaks in AliTPCDigitizer<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "BaseTestBlock.hpp"

#include <iterator>
#include <boost/math/constants/constants.hpp>

#include <nix/hydra/multiArray.hpp>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>

using namespace nix;
using namespace valid;

void BaseTestBlock::testValidate() {
    valid::Result result = validate(block);
    CPPUNIT_ASSERT(result.getErrors().size() == 0);
    CPPUNIT_ASSERT(result.getWarnings().size() == 0);
}

void BaseTestBlock::testId() {
    CPPUNIT_ASSERT(block.id().size() == 36);
}

void BaseTestBlock::testName() {
    CPPUNIT_ASSERT(block.name() == "block_one");
}

void BaseTestBlock::testType() {
    CPPUNIT_ASSERT(block.type() == "dataset");
    std::string typ = util::createId();
    block.type(typ);
    CPPUNIT_ASSERT(block.type() == typ);
}

void BaseTestBlock::testDefinition() {
    std::string def = util::createId();
    block.definition(def);
    CPPUNIT_ASSERT(*block.definition() == def);
}

void BaseTestBlock::testMetadataAccess() {
    CPPUNIT_ASSERT(!block.metadata());
    block.metadata(section);
    CPPUNIT_ASSERT(block.metadata());
    // test none-unsetter
    block.metadata(none);
    CPPUNIT_ASSERT(!block.metadata());
    // test deleter removing link too
    block.metadata(section);
    file.deleteSection(section.id());
    CPPUNIT_ASSERT(!block.metadata());
    // re-create section
    section = file.createSection("foo_section", "metadata");
}

void BaseTestBlock::testSourceAccess() {
    std::vector<std::string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
    Source s;
    CPPUNIT_ASSERT(!block.hasSource(s));
    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasSource("invalid_id"));
    CPPUNIT_ASSERT_THROW(block.getSource(block.sourceCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (const auto &name : names) {
        Source src = block.createSource(name, "channel");
        CPPUNIT_ASSERT(src.name() == name);
        CPPUNIT_ASSERT(block.hasSource(name));
        CPPUNIT_ASSERT(block.hasSource(src));

        ids.push_back(src.id());
    }
    CPPUNIT_ASSERT_THROW(block.createSource(names[0], "channel"), DuplicateName);
    CPPUNIT_ASSERT_THROW(block.createSource("", "test"), nix::EmptyString);

    CPPUNIT_ASSERT(block.sourceCount() == names.size());
    CPPUNIT_ASSERT(block.sources().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getSource(block.sourceCount() + 10), OutOfBounds);

    for (const auto &id : ids) {
        Source src = block.getSource(id);
        CPPUNIT_ASSERT(block.hasSource(id) == true);
        CPPUNIT_ASSERT(src.id() == id);
        block.deleteSource(id);
    }

    s = block.createSource("test", "test");
    CPPUNIT_ASSERT(block.sourceCount() == 1);
    CPPUNIT_ASSERT_NO_THROW(block.deleteSource(s));

    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
}

void BaseTestBlock::testDataArrayAccess() {
    std::vector<std::string> names = { "data_array_a", "data_array_b", "data_array_c",
                                       "data_array_d", "data_array_e" };
    DataArray data_array, a;

    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);

    std::vector<std::string> ids;
    for (const auto &name : names) {
        data_array = block.createDataArray(name, "channel", DataType::Double, nix::NDSize({ 0 }));
        CPPUNIT_ASSERT(data_array.name() == name);
        CPPUNIT_ASSERT(data_array.type() == "channel");
        ids.push_back(data_array.id());
    }

    CPPUNIT_ASSERT_THROW(block.createDataArray(names[0], "channel", DataType::Double, nix::NDSize({ 0 })), DuplicateName);
    CPPUNIT_ASSERT_THROW(block.createDataArray("", "channel", DataType::Double, nix::NDSize({ 0 })), EmptyString);

    CPPUNIT_ASSERT(block.hasDataArray(data_array));
    CPPUNIT_ASSERT(!block.hasDataArray(a));
    CPPUNIT_ASSERT(block.dataArrayCount() == names.size());
    CPPUNIT_ASSERT(block.dataArrays().size() == names.size());

    for (const auto &name : names) {
        DataArray da_name = block.getDataArray(name);
        CPPUNIT_ASSERT(da_name);
        DataArray da_id = block.getDataArray(da_name.id());
        CPPUNIT_ASSERT(da_id);
        CPPUNIT_ASSERT_EQUAL(da_name.name(), da_id.name());
    }

    std::vector<DataArray> filteredArrays = block.dataArrays(util::TypeFilter<DataArray>("channel"));
    CPPUNIT_ASSERT_EQUAL(names.size(), filteredArrays.size());

    filteredArrays = block.dataArrays(util::NameFilter<DataArray>("data_array_c"));
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), filteredArrays.size());
    if (filteredArrays.size() > 0) {
        boost::optional<std::string> name = filteredArrays[0].name();
        CPPUNIT_ASSERT(name && *name == "data_array_c");
    }

    for (auto it = ids.begin(); it != ids.end(); it++) {
        CPPUNIT_ASSERT(block.hasDataArray(*it));
        CPPUNIT_ASSERT(block.getDataArray(*it).id() == *it);
        block.deleteDataArray(*it);
    }
    CPPUNIT_ASSERT(!block.deleteDataArray(a));
    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);
}

void BaseTestBlock::testTagAccess() {
    std::vector<std::string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    std::vector<std::string> array_names = { "data_array_a", "data_array_b", "data_array_c",
                                             "data_array_d", "data_array_e" };
    std::vector<DataArray> refs;
    Tag tag, t;
    for (const auto &name : array_names) {
        refs.push_back(block.createDataArray(name,
                                         "reference",
                                         DataType::Double,
                                         nix::NDSize({ 0 })));
    }

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasTag(t));

    std::vector<std::string> ids;
    for (auto it = names.begin(); it != names.end(); ++it) {
        tag = block.createTag(*it, "segment", {0.0, 2.0, 3.4});
        tag.references(refs);
        CPPUNIT_ASSERT(tag.name() == *it);
        CPPUNIT_ASSERT(block.hasTag(tag));
        ids.push_back(tag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createTag(names[0], "segment", {0.0, 2.0, 3.4}),
                         DuplicateName);

    CPPUNIT_ASSERT(block.tagCount() == names.size());
    CPPUNIT_ASSERT(block.tags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); ++it) {
        tag = block.getTag(*it);
        CPPUNIT_ASSERT(block.hasTag(*it));
        CPPUNIT_ASSERT(tag.id() == *it);

        block.deleteTag(*it);
    }

    tag = block.createTag("test", "test", {0.0});
    CPPUNIT_ASSERT(block.hasTag(tag));
    CPPUNIT_ASSERT(block.deleteTag(tag));
    CPPUNIT_ASSERT(!block.deleteTag(t));

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
}

void BaseTestBlock::testMultiTagAccess() {
    std::vector<std::string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    MultiTag mtag, m;
    // create a valid positions data array below
    DataArray positions = block.createDataArray("array_one", "testdata",
                                                DataType::Double, nix::NDSize({ 3, 4, 2 }));

    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasMultiTag(m));
    std::vector<std::string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        mtag = block.createMultiTag(*it, "segment", positions);
        CPPUNIT_ASSERT(mtag.name() == *it);
        CPPUNIT_ASSERT(block.hasMultiTag(mtag));
        ids.push_back(mtag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createMultiTag(names[0], "segment", positions),
                         DuplicateName);

    CPPUNIT_ASSERT(block.multiTagCount() == names.size());
    CPPUNIT_ASSERT(block.multiTags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        mtag = block.getMultiTag(*it);
        CPPUNIT_ASSERT(block.hasMultiTag(*it));
        CPPUNIT_ASSERT(mtag.id() == *it);

        block.deleteMultiTag(*it);
    }
    mtag = block.createMultiTag("test", "test", positions);
    CPPUNIT_ASSERT(block.hasMultiTag(mtag));
    CPPUNIT_ASSERT(!block.deleteMultiTag(m));
    CPPUNIT_ASSERT(block.deleteMultiTag(mtag));
    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
}

void BaseTestBlock::testGroupAccess() {
    std::vector<std::string> names = { "group_a", "group_b", "group_c", "group_d", "group_e" };
    Group g;
    CPPUNIT_ASSERT(!block.hasGroup(g));
    CPPUNIT_ASSERT(block.groupCount() == 0);
    CPPUNIT_ASSERT(block.groups().size() == 0);
    CPPUNIT_ASSERT(block.getGroup("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasGroup("invalid_id"));

    std::vector<std::string> ids;
    for (const auto &name : names) {
        Group gr = block.createGroup(name, "group");
        CPPUNIT_ASSERT(gr.name() == name);
        CPPUNIT_ASSERT(block.hasGroup(name));
        CPPUNIT_ASSERT(block.hasGroup(gr));

        ids.push_back(gr.id());
    }
    CPPUNIT_ASSERT_THROW(block.createGroup(names[0], "group"),
                         DuplicateName);

    CPPUNIT_ASSERT(block.groupCount() == names.size());
    CPPUNIT_ASSERT(block.groups().size() == names.size());

    for (const auto &id : ids) {
        Group gr = block.getGroup(id);
        CPPUNIT_ASSERT(block.hasGroup(id));
        CPPUNIT_ASSERT(gr.id() == id);
        block.deleteGroup(id);
    }

    g = block.createGroup("test", "test");
    CPPUNIT_ASSERT(block.groupCount() == 1);
    CPPUNIT_ASSERT(block.deleteGroup(g));

    CPPUNIT_ASSERT(block.groupCount() == 0);
    CPPUNIT_ASSERT(block.groups().size() == 0);
    CPPUNIT_ASSERT(block.getGroup("invalid_id") == false);
}

void BaseTestBlock::testOperators() {
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    CPPUNIT_ASSERT(block != false);
    CPPUNIT_ASSERT(block != none);

    CPPUNIT_ASSERT(block == block);
    CPPUNIT_ASSERT(block != block_other);

    block_other = block;
    CPPUNIT_ASSERT(block == block_other);

    block_other = none;
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    std::stringstream str;
    str << block;
}

void BaseTestBlock::testCreatedAt() {
    CPPUNIT_ASSERT(block.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    block.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(block.createdAt() == past_time);
}

void BaseTestBlock::testUpdatedAt() {
    CPPUNIT_ASSERT(block.updatedAt() >= startup_time);
}

void BaseTestBlock::testCompare() {
    std::string other_name = block_other.name();
    std::string block_name = block.name();

    CPPUNIT_ASSERT(block.compare(block) == 0);
    CPPUNIT_ASSERT(block.compare(block_other) ==  block_name.compare(other_name));
}
<commit_msg>[test] Block: add missing OOB access checks<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "BaseTestBlock.hpp"

#include <iterator>
#include <boost/math/constants/constants.hpp>

#include <nix/hydra/multiArray.hpp>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>

using namespace nix;
using namespace valid;

void BaseTestBlock::testValidate() {
    valid::Result result = validate(block);
    CPPUNIT_ASSERT(result.getErrors().size() == 0);
    CPPUNIT_ASSERT(result.getWarnings().size() == 0);
}

void BaseTestBlock::testId() {
    CPPUNIT_ASSERT(block.id().size() == 36);
}

void BaseTestBlock::testName() {
    CPPUNIT_ASSERT(block.name() == "block_one");
}

void BaseTestBlock::testType() {
    CPPUNIT_ASSERT(block.type() == "dataset");
    std::string typ = util::createId();
    block.type(typ);
    CPPUNIT_ASSERT(block.type() == typ);
}

void BaseTestBlock::testDefinition() {
    std::string def = util::createId();
    block.definition(def);
    CPPUNIT_ASSERT(*block.definition() == def);
}

void BaseTestBlock::testMetadataAccess() {
    CPPUNIT_ASSERT(!block.metadata());
    block.metadata(section);
    CPPUNIT_ASSERT(block.metadata());
    // test none-unsetter
    block.metadata(none);
    CPPUNIT_ASSERT(!block.metadata());
    // test deleter removing link too
    block.metadata(section);
    file.deleteSection(section.id());
    CPPUNIT_ASSERT(!block.metadata());
    // re-create section
    section = file.createSection("foo_section", "metadata");
}

void BaseTestBlock::testSourceAccess() {
    std::vector<std::string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
    Source s;
    CPPUNIT_ASSERT(!block.hasSource(s));
    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasSource("invalid_id"));
    CPPUNIT_ASSERT_THROW(block.getSource(block.sourceCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (const auto &name : names) {
        Source src = block.createSource(name, "channel");
        CPPUNIT_ASSERT(src.name() == name);
        CPPUNIT_ASSERT(block.hasSource(name));
        CPPUNIT_ASSERT(block.hasSource(src));

        ids.push_back(src.id());
    }
    CPPUNIT_ASSERT_THROW(block.createSource(names[0], "channel"), DuplicateName);
    CPPUNIT_ASSERT_THROW(block.createSource("", "test"), nix::EmptyString);

    CPPUNIT_ASSERT(block.sourceCount() == names.size());
    CPPUNIT_ASSERT(block.sources().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getSource(block.sourceCount() + 10), OutOfBounds);

    for (const auto &id : ids) {
        Source src = block.getSource(id);
        CPPUNIT_ASSERT(block.hasSource(id) == true);
        CPPUNIT_ASSERT(src.id() == id);
        block.deleteSource(id);
    }

    s = block.createSource("test", "test");
    CPPUNIT_ASSERT(block.sourceCount() == 1);
    CPPUNIT_ASSERT_NO_THROW(block.deleteSource(s));

    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
}

void BaseTestBlock::testDataArrayAccess() {
    std::vector<std::string> names = { "data_array_a", "data_array_b", "data_array_c",
                                       "data_array_d", "data_array_e" };
    DataArray data_array, a;

    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);
    CPPUNIT_ASSERT_THROW(block.getDataArray(block.dataArrayCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (const auto &name : names) {
        data_array = block.createDataArray(name, "channel", DataType::Double, nix::NDSize({ 0 }));
        CPPUNIT_ASSERT(data_array.name() == name);
        CPPUNIT_ASSERT(data_array.type() == "channel");
        ids.push_back(data_array.id());
    }

    CPPUNIT_ASSERT_THROW(block.createDataArray(names[0], "channel", DataType::Double, nix::NDSize({ 0 })), DuplicateName);
    CPPUNIT_ASSERT_THROW(block.createDataArray("", "channel", DataType::Double, nix::NDSize({ 0 })), EmptyString);

    CPPUNIT_ASSERT(block.hasDataArray(data_array));
    CPPUNIT_ASSERT(!block.hasDataArray(a));
    CPPUNIT_ASSERT(block.dataArrayCount() == names.size());
    CPPUNIT_ASSERT(block.dataArrays().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getDataArray(block.dataArrayCount() + 10), OutOfBounds);

    for (const auto &name : names) {
        DataArray da_name = block.getDataArray(name);
        CPPUNIT_ASSERT(da_name);
        DataArray da_id = block.getDataArray(da_name.id());
        CPPUNIT_ASSERT(da_id);
        CPPUNIT_ASSERT_EQUAL(da_name.name(), da_id.name());
    }

    std::vector<DataArray> filteredArrays = block.dataArrays(util::TypeFilter<DataArray>("channel"));
    CPPUNIT_ASSERT_EQUAL(names.size(), filteredArrays.size());

    filteredArrays = block.dataArrays(util::NameFilter<DataArray>("data_array_c"));
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), filteredArrays.size());
    if (filteredArrays.size() > 0) {
        boost::optional<std::string> name = filteredArrays[0].name();
        CPPUNIT_ASSERT(name && *name == "data_array_c");
    }

    for (auto it = ids.begin(); it != ids.end(); it++) {
        CPPUNIT_ASSERT(block.hasDataArray(*it));
        CPPUNIT_ASSERT(block.getDataArray(*it).id() == *it);
        block.deleteDataArray(*it);
    }
    CPPUNIT_ASSERT(!block.deleteDataArray(a));
    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);
}

void BaseTestBlock::testTagAccess() {
    std::vector<std::string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    std::vector<std::string> array_names = { "data_array_a", "data_array_b", "data_array_c",
                                             "data_array_d", "data_array_e" };
    std::vector<DataArray> refs;
    Tag tag, t;
    for (const auto &name : array_names) {
        refs.push_back(block.createDataArray(name,
                                         "reference",
                                         DataType::Double,
                                         nix::NDSize({ 0 })));
    }

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasTag(t));
    CPPUNIT_ASSERT_THROW(block.getTag(block.tagCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (auto it = names.begin(); it != names.end(); ++it) {
        tag = block.createTag(*it, "segment", {0.0, 2.0, 3.4});
        tag.references(refs);
        CPPUNIT_ASSERT(tag.name() == *it);
        CPPUNIT_ASSERT(block.hasTag(tag));
        ids.push_back(tag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createTag(names[0], "segment", {0.0, 2.0, 3.4}),
                         DuplicateName);

    CPPUNIT_ASSERT(block.tagCount() == names.size());
    CPPUNIT_ASSERT(block.tags().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getTag(block.tagCount() + 10), OutOfBounds);

    for (auto it = ids.begin(); it != ids.end(); ++it) {
        tag = block.getTag(*it);
        CPPUNIT_ASSERT(block.hasTag(*it));
        CPPUNIT_ASSERT(tag.id() == *it);

        block.deleteTag(*it);
    }

    tag = block.createTag("test", "test", {0.0});
    CPPUNIT_ASSERT(block.hasTag(tag));
    CPPUNIT_ASSERT(block.deleteTag(tag));
    CPPUNIT_ASSERT(!block.deleteTag(t));

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
}

void BaseTestBlock::testMultiTagAccess() {
    std::vector<std::string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    MultiTag mtag, m;
    // create a valid positions data array below
    DataArray positions = block.createDataArray("array_one", "testdata",
                                                DataType::Double, nix::NDSize({ 3, 4, 2 }));

    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasMultiTag(m));
    CPPUNIT_ASSERT_THROW(block.getMultiTag(block.multiTagCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        mtag = block.createMultiTag(*it, "segment", positions);
        CPPUNIT_ASSERT(mtag.name() == *it);
        CPPUNIT_ASSERT(block.hasMultiTag(mtag));
        ids.push_back(mtag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createMultiTag(names[0], "segment", positions),
                         DuplicateName);

    CPPUNIT_ASSERT(block.multiTagCount() == names.size());
    CPPUNIT_ASSERT(block.multiTags().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getMultiTag(block.multiTagCount() + 10), OutOfBounds);

    for (auto it = ids.begin(); it != ids.end(); it++) {
        mtag = block.getMultiTag(*it);
        CPPUNIT_ASSERT(block.hasMultiTag(*it));
        CPPUNIT_ASSERT(mtag.id() == *it);

        block.deleteMultiTag(*it);
    }
    mtag = block.createMultiTag("test", "test", positions);
    CPPUNIT_ASSERT(block.hasMultiTag(mtag));
    CPPUNIT_ASSERT(!block.deleteMultiTag(m));
    CPPUNIT_ASSERT(block.deleteMultiTag(mtag));
    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
}

void BaseTestBlock::testGroupAccess() {
    std::vector<std::string> names = { "group_a", "group_b", "group_c", "group_d", "group_e" };
    Group g;
    CPPUNIT_ASSERT(!block.hasGroup(g));
    CPPUNIT_ASSERT(block.groupCount() == 0);
    CPPUNIT_ASSERT(block.groups().size() == 0);
    CPPUNIT_ASSERT(block.getGroup("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasGroup("invalid_id"));
    CPPUNIT_ASSERT_THROW(block.getGroup(block.groupCount() + 10), OutOfBounds);

    std::vector<std::string> ids;
    for (const auto &name : names) {
        Group gr = block.createGroup(name, "group");
        CPPUNIT_ASSERT(gr.name() == name);
        CPPUNIT_ASSERT(block.hasGroup(name));
        CPPUNIT_ASSERT(block.hasGroup(gr));

        ids.push_back(gr.id());
    }
    CPPUNIT_ASSERT_THROW(block.createGroup(names[0], "group"),
                         DuplicateName);

    CPPUNIT_ASSERT(block.groupCount() == names.size());
    CPPUNIT_ASSERT(block.groups().size() == names.size());
    CPPUNIT_ASSERT_THROW(block.getGroup(block.groupCount() + 10), OutOfBounds);

    for (const auto &id : ids) {
        Group gr = block.getGroup(id);
        CPPUNIT_ASSERT(block.hasGroup(id));
        CPPUNIT_ASSERT(gr.id() == id);
        block.deleteGroup(id);
    }

    g = block.createGroup("test", "test");
    CPPUNIT_ASSERT(block.groupCount() == 1);
    CPPUNIT_ASSERT(block.deleteGroup(g));

    CPPUNIT_ASSERT(block.groupCount() == 0);
    CPPUNIT_ASSERT(block.groups().size() == 0);
    CPPUNIT_ASSERT(block.getGroup("invalid_id") == false);
}

void BaseTestBlock::testOperators() {
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    CPPUNIT_ASSERT(block != false);
    CPPUNIT_ASSERT(block != none);

    CPPUNIT_ASSERT(block == block);
    CPPUNIT_ASSERT(block != block_other);

    block_other = block;
    CPPUNIT_ASSERT(block == block_other);

    block_other = none;
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    std::stringstream str;
    str << block;
}

void BaseTestBlock::testCreatedAt() {
    CPPUNIT_ASSERT(block.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    block.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(block.createdAt() == past_time);
}

void BaseTestBlock::testUpdatedAt() {
    CPPUNIT_ASSERT(block.updatedAt() >= startup_time);
}

void BaseTestBlock::testCompare() {
    std::string other_name = block_other.name();
    std::string block_name = block.name();

    CPPUNIT_ASSERT(block.compare(block) == 0);
    CPPUNIT_ASSERT(block.compare(block_other) ==  block_name.compare(other_name));
}
<|endoftext|>


<commit_before>#include "NotificationLoader.h"

CNotificationLoader::CNotificationLoader()
{
	m_hNotificationDLL			= NULL;
	lpfn_Notify_FindClose		= NULL;
	lpfn_Notify_FindFirst		= NULL;
	lpfn_Notify_FindNext		= NULL;
	lpfn_Notify_SetCycleInfo	= NULL;
	lpfn_Notify_GetCycleInfo	= NULL;
	lpfn_Notify_SetState		= NULL;
	lpfn_Notify_GetState		= NULL;
	int m_iBeeperIndex			= -1;
	int m_iVibrateIndex			= -1;
}

CNotificationLoader::~CNotificationLoader()
{
	UnloadNotificationDLL();
}

//  Loading Notification DLL dynamically
BOOL CNotificationLoader::LoadNotificationDLL()
{
	m_hNotificationDLL = LoadLibrary(NOTIFY_DLL);
	if (!m_hNotificationDLL)
	{
		return FALSE;
	}
	//  Map the function pointers to functions exported from the DLL
	lpfn_Notify_FindClose = (LPFN_NOTIFY_FINDCLOSE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindClose");
	lpfn_Notify_FindNext = (LPFN_NOTIFY_FINDNEXT_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindNext");
	lpfn_Notify_FindFirst = (LPFN_NOTIFY_FINDFIRST_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindFirst");
	lpfn_Notify_SetCycleInfo = (LPFN_NOTIFY_SETCYCLEINFO_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_SetCycleInfo");
	lpfn_Notify_GetCycleInfo = (LPFN_NOTIFY_GETCYCLEINFO_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_GetCycleInfo");
	lpfn_Notify_SetState = (LPFN_NOTIFY_SETSTATE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_SetState");
	lpfn_Notify_GetState = (LPFN_NOTIFY_GETSTATE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_GetState");

	if (lpfn_Notify_FindClose	== NULL ||
		lpfn_Notify_FindNext	== NULL ||
		lpfn_Notify_FindFirst	== NULL ||
		lpfn_Notify_SetCycleInfo== NULL ||
		lpfn_Notify_GetCycleInfo== NULL ||
		lpfn_Notify_SetState	== NULL ||
		lpfn_Notify_GetState	== NULL)
	{
		m_hNotificationDLL = NULL;
		return FALSE;
	}
	else
	{
		//  Set the indices of the beeper and vibrate index
		NOTIFY_FINDINFO notifyObject;
		HANDLE	hFindHandle = NULL;
		SI_ALLOC_ALL(&notifyObject);
		notifyObject.StructInfo.dwUsed = 0;
		if(lpfn_Notify_FindFirst(&notifyObject, &hFindHandle) == E_NTFY_SUCCESS)
		{
			int iObCount = 0;
			int m_iBeeperIndexForSoftwareOrHardware = 0;
			do
			{

				if(notifyObject.dwObjectType == NOTIFY_TYPE_BEEPER)
				{
					//  Found the Beeper
					if(m_iBeeperIndexForSoftwareOrHardware == 0)
                         m_iBeeperIndexForSoftwareOrHardware = iObCount;

                    m_iBeeperIndex = m_iBeeperIndexForSoftwareOrHardware;

					//continue;
				}
				else if (notifyObject.dwObjectType == NOTIFY_TYPE_VIBRATOR)
				{
					m_iVibrateIndex = iObCount;
				}
				iObCount++;
				SI_ALLOC_ALL(&notifyObject);
				notifyObject.StructInfo.dwUsed = 0;
			} while(lpfn_Notify_FindNext(&notifyObject, hFindHandle) == E_NTFY_SUCCESS);
		}
		lpfn_Notify_FindClose(hFindHandle);
		return TRUE;
	}
}

BOOL CNotificationLoader::UnloadNotificationDLL()
{
	if (m_hNotificationDLL)
	{
		FreeLibrary(m_hNotificationDLL);
		m_hNotificationDLL		= NULL;
		lpfn_Notify_FindClose	= NULL;
		lpfn_Notify_FindNext	= NULL;
		lpfn_Notify_FindFirst	= NULL;
		lpfn_Notify_SetCycleInfo= NULL;
		lpfn_Notify_GetCycleInfo= NULL;
		lpfn_Notify_SetState	= NULL;
		lpfn_Notify_GetState	= NULL;
	}
	return TRUE;
}

BOOL CNotificationLoader::Beep(int iFrequency, int iVolume, int iDuration)
{
	if (m_iBeeperIndex < 0)
		return FALSE;

	CYCLE_INFO cycleInfo;
	SI_INIT(&cycleInfo);
	DWORD dwResult = lpfn_Notify_GetCycleInfo(m_iBeeperIndex, &cycleInfo);
	if(dwResult != E_NTFY_SUCCESS)
		return FALSE;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwFrequency = iFrequency;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwVolume = iVolume;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwDuration = iDuration;
	dwResult = lpfn_Notify_SetCycleInfo(m_iBeeperIndex, &cycleInfo);
	dwResult = lpfn_Notify_SetState(m_iBeeperIndex, NOTIFY_STATE_CYCLE);

	return TRUE;
}

BOOL CNotificationLoader::Vibrate(int iDuration)
{
	if (m_iVibrateIndex < 0)
		return FALSE;

	CYCLE_INFO cycleInfo;
	SI_INIT(&cycleInfo);
	DWORD dwResult = lpfn_Notify_GetCycleInfo(m_iVibrateIndex, &cycleInfo);
	if(dwResult != E_NTFY_SUCCESS)
		return FALSE;
	cycleInfo.ObjectTypeSpecific.VibratorSpecific.dwDuration = iDuration;

	dwResult = lpfn_Notify_SetCycleInfo(m_iVibrateIndex, &cycleInfo);
	dwResult = lpfn_Notify_SetState(m_iVibrateIndex, NOTIFY_STATE_CYCLE);
	return dwResult == E_NTFY_SUCCESS;
}
<commit_msg>Update NotificationLoader.cpp<commit_after>#include "NotificationLoader.h"

CNotificationLoader::CNotificationLoader()
{
	m_hNotificationDLL			= NULL;
	lpfn_Notify_FindClose		= NULL;
	lpfn_Notify_FindFirst		= NULL;
	lpfn_Notify_FindNext		= NULL;
	lpfn_Notify_SetCycleInfo	= NULL;
	lpfn_Notify_GetCycleInfo	= NULL;
	lpfn_Notify_SetState		= NULL;
	lpfn_Notify_GetState		= NULL;
	int m_iBeeperIndex			= -1;
	int m_iVibrateIndex			= -1;
}

CNotificationLoader::~CNotificationLoader()
{
	UnloadNotificationDLL();
}

//  Loading Notification DLL dynamically
BOOL CNotificationLoader::LoadNotificationDLL()
{
	m_hNotificationDLL = LoadLibrary(NOTIFY_DLL);
	if (!m_hNotificationDLL)
	{
		return FALSE;
	}
	//  Map the function pointers to functions exported from the DLL
	lpfn_Notify_FindClose = (LPFN_NOTIFY_FINDCLOSE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindClose");
	lpfn_Notify_FindNext = (LPFN_NOTIFY_FINDNEXT_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindNext");
	lpfn_Notify_FindFirst = (LPFN_NOTIFY_FINDFIRST_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_FindFirst");
	lpfn_Notify_SetCycleInfo = (LPFN_NOTIFY_SETCYCLEINFO_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_SetCycleInfo");
	lpfn_Notify_GetCycleInfo = (LPFN_NOTIFY_GETCYCLEINFO_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_GetCycleInfo");
	lpfn_Notify_SetState = (LPFN_NOTIFY_SETSTATE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_SetState");
	lpfn_Notify_GetState = (LPFN_NOTIFY_GETSTATE_T)GetProcAddress
		(m_hNotificationDLL, L"NOTIFY_GetState");

	if (lpfn_Notify_FindClose	== NULL ||
		lpfn_Notify_FindNext	== NULL ||
		lpfn_Notify_FindFirst	== NULL ||
		lpfn_Notify_SetCycleInfo== NULL ||
		lpfn_Notify_GetCycleInfo== NULL ||
		lpfn_Notify_SetState	== NULL ||
		lpfn_Notify_GetState	== NULL)
	{
		m_hNotificationDLL = NULL;
		return FALSE;
	}
	else
	{
		//  Set the indices of the beeper and vibrate index
		NOTIFY_FINDINFO notifyObject;
		HANDLE	hFindHandle = NULL;
		SI_ALLOC_ALL(&notifyObject);
		notifyObject.StructInfo.dwUsed = 0;
		if(lpfn_Notify_FindFirst(&notifyObject, &hFindHandle) == E_NTFY_SUCCESS)
		{
			int iObCount = 0;
			int m_iBeeperIndexForSoftwareOrHardware = 0;
			do
			{
				if(notifyObject.dwObjectType == NOTIFY_TYPE_BEEPER)
				{
					//  Found the Beeper
					if(m_iBeeperIndexForSoftwareOrHardware == 0)
					{
                         			m_iBeeperIndexForSoftwareOrHardware = iObCount;
					}
                    			m_iBeeperIndex = m_iBeeperIndexForSoftwareOrHardware;
					//continue;
				}
				else if (notifyObject.dwObjectType == NOTIFY_TYPE_VIBRATOR)
				{
					m_iVibrateIndex = iObCount;
				}
				iObCount++;
				SI_ALLOC_ALL(&notifyObject);
				notifyObject.StructInfo.dwUsed = 0;
			} while(lpfn_Notify_FindNext(&notifyObject, hFindHandle) == E_NTFY_SUCCESS);
		}
		lpfn_Notify_FindClose(hFindHandle);
		return TRUE;
	}
}

BOOL CNotificationLoader::UnloadNotificationDLL()
{
	if (m_hNotificationDLL)
	{
		FreeLibrary(m_hNotificationDLL);
		m_hNotificationDLL		= NULL;
		lpfn_Notify_FindClose	= NULL;
		lpfn_Notify_FindNext	= NULL;
		lpfn_Notify_FindFirst	= NULL;
		lpfn_Notify_SetCycleInfo= NULL;
		lpfn_Notify_GetCycleInfo= NULL;
		lpfn_Notify_SetState	= NULL;
		lpfn_Notify_GetState	= NULL;
	}
	return TRUE;
}

BOOL CNotificationLoader::Beep(int iFrequency, int iVolume, int iDuration)
{
	if (m_iBeeperIndex < 0)
		return FALSE;

	CYCLE_INFO cycleInfo;
	SI_INIT(&cycleInfo);
	DWORD dwResult = lpfn_Notify_GetCycleInfo(m_iBeeperIndex, &cycleInfo);
	if(dwResult != E_NTFY_SUCCESS)
		return FALSE;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwFrequency = iFrequency;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwVolume = iVolume;
	cycleInfo.ObjectTypeSpecific.BeeperSpecific.dwDuration = iDuration;
	dwResult = lpfn_Notify_SetCycleInfo(m_iBeeperIndex, &cycleInfo);
	dwResult = lpfn_Notify_SetState(m_iBeeperIndex, NOTIFY_STATE_CYCLE);

	return TRUE;
}

BOOL CNotificationLoader::Vibrate(int iDuration)
{
	if (m_iVibrateIndex < 0)
		return FALSE;

	CYCLE_INFO cycleInfo;
	SI_INIT(&cycleInfo);
	DWORD dwResult = lpfn_Notify_GetCycleInfo(m_iVibrateIndex, &cycleInfo);
	if(dwResult != E_NTFY_SUCCESS)
		return FALSE;
	cycleInfo.ObjectTypeSpecific.VibratorSpecific.dwDuration = iDuration;

	dwResult = lpfn_Notify_SetCycleInfo(m_iVibrateIndex, &cycleInfo);
	dwResult = lpfn_Notify_SetState(m_iVibrateIndex, NOTIFY_STATE_CYCLE);
	return dwResult == E_NTFY_SUCCESS;
}
<|endoftext|>