<commit_before>/* Copyright (C) 2000-2003 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; either version 2 of the License, or
   (at your option) any later version.

   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 */

/*
  UNION  of select's
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
*/

#include "mysql_priv.h"
#include "sql_select.h"

int mysql_union(THD *thd, LEX *lex, select_result *result,
		SELECT_LEX_UNIT *unit, bool tables_and_fields_initied)
{
  DBUG_ENTER("mysql_union");
  int res= 0;
  if (!(res= unit->prepare(thd, result, tables_and_fields_initied)))
    res= unit->exec();
  res|= unit->cleanup();
  DBUG_RETURN(res);
}

/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/

select_union::select_union(TABLE *table_par)
  :table(table_par), not_describe(0)
{
  bzero((char*) &info,sizeof(info));
  /*
    We can always use DUP_IGNORE because the temporary table will only
    contain a unique key if we are using not using UNION ALL
  */
  info.handle_duplicates= DUP_IGNORE;
}

select_union::~select_union()
{
}

int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
  unit= u;
  if (not_describe && list.elements != table->fields)
  {
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
	       ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
    return -1;
  }
  return 0;
}

bool select_union::send_data(List<Item> &values)
{
  if (unit->offset_limit_cnt)
  {						// using limit offset,count
    unit->offset_limit_cnt--;
    return 0;
  }
  fill_record(table->field,values);
  if (thd->net.report_error || write_record(table,&info))
  {
    if (thd->net.last_errno == ER_RECORD_FILE_FULL)
    {
      thd->clear_error(); // do not report user about table overflow
      if (create_myisam_from_heap(thd, table, tmp_table_param,
				  info.last_errno, 0))
	return 1;
    }
    else
      return 1;
  }
  return 0;
}

bool select_union::send_eof()
{
  return 0;
}

bool select_union::flush()
{
  int error;
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
  {
    table->file->print_error(error,MYF(0));
    ::send_error(thd);
    return 1;
  }
  return 0;
}

int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
				bool tables_and_fields_initied)
{
  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
  SELECT_LEX *select_cursor;
  TMP_TABLE_PARAM tmp_table_param;
  DBUG_ENTER("st_select_lex_unit::prepare");

  if (prepared)
    DBUG_RETURN(0);
  prepared= 1;
  res= 0;
  found_rows_for_union= 0;
  TMP_TABLE_PARAM *tmp_table_param= (TMP_TABLE_PARAM *)sql_calloc(sizeof(TMP_TABLE_PARAM));
  result= sel_result;
  t_and_f= tables_and_fields_initied;

  thd->lex.current_select= select_cursor= first_select_in_union();
  /* Global option */
  if (((void*)(global_parameters)) == ((void*)this))
  {
    found_rows_for_union= first_select()->options & OPTION_FOUND_ROWS &&
      global_parameters->select_limit;
    if (found_rows_for_union)
      first_select()->options ^=  OPTION_FOUND_ROWS;
  }
  if (t_and_f)
  {
    // Item list and tables will be initialized by mysql_derived
    item_list= select_cursor->item_list;
  }
  else
  {
    item_list.empty();
    TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;

    if (setup_tables(first_table) ||
	setup_wild(thd, first_table, select_cursor->item_list, 0,
		   select_cursor->with_wild))
      goto err;
    List_iterator<Item> it(select_cursor->item_list);
    Item *item;
    while((item=it++))
      item->maybe_null=1;
    item_list= select_cursor->item_list;
    select_cursor->with_wild= 0;
    if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
			(item_list.elements + select_cursor->with_sum_func +
			 select_cursor->order_list.elements +
			 select_cursor->group_list.elements)) ||
	setup_fields(thd, select_cursor->ref_pointer_array, first_table,
		     item_list, 0, 0, 1))
      goto err;
    t_and_f= 1;
  }

  tmp_table_param->field_count=item_list.elements;
  if (!(table= create_tmp_table(thd, tmp_table_param, item_list,
				(ORDER*) 0, !union_option,
				1, (select_cursor->options | thd->options |
				    TMP_TABLE_ALL_COLUMNS),
				HA_POS_ERROR)))
    goto err;
  table->file->extra(HA_EXTRA_WRITE_CACHE);
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
  bzero((char*) &result_table_list,sizeof(result_table_list));
  result_table_list.db= (char*) "";
  result_table_list.real_name=result_table_list.alias= (char*) "union";
  result_table_list.table=table;

  if (!(union_result=new select_union(table)))
    goto err;

  union_result->not_describe=1;
  union_result->tmp_table_param=tmp_table_param;

  /*
    The following piece of code is placed here solely for the purpose of
    getting correct results with EXPLAIN when UNION is withing a sub-select
    or derived table ...
  */

  if (thd->lex.describe)
  {
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
    {
      JOIN *join= new JOIN(thd, sl->item_list,
			   sl->options | thd->options | SELECT_NO_UNLOCK,
			   union_result);
      thd->lex.current_select= sl;
      offset_limit_cnt= sl->offset_limit;
      select_limit_cnt= sl->select_limit+sl->offset_limit;
      if (select_limit_cnt < sl->select_limit)
	select_limit_cnt= HA_POS_ERROR;		// no limit
      if (select_limit_cnt == HA_POS_ERROR)
	sl->options&= ~OPTION_FOUND_ROWS;

      res= join->prepare(&sl->ref_pointer_array,
			 (TABLE_LIST*) sl->table_list.first, sl->with_wild,
			 sl->where,
			 ((sl->braces) ? sl->order_list.elements : 0) +
			 sl->group_list.elements,
			 (sl->braces) ?
			 (ORDER *)sl->order_list.first : (ORDER *) 0,
			 (ORDER*) sl->group_list.first,
			 sl->having,
			 (ORDER*) NULL,
			 sl, this, t_and_f);
      t_and_f= 0;
      if (res || thd->is_fatal_error)
	goto err;
    }
  }

  item_list.empty();
  thd->lex.current_select= lex_select_save;
  {
    List_iterator<Item> it(select_cursor->item_list);
    Field **field;

    for (field= table->field; *field; field++)
    {
      (void) it++;
      if (item_list.push_back(new Item_field(*field)))
	DBUG_RETURN(-1);
    }
  }

  DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0);
err:
  thd->lex.current_select= lex_select_save;
  DBUG_RETURN(-1);
}

int st_select_lex_unit::exec()
{
  int do_print_slow= 0;
  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
  SELECT_LEX *select_cursor=first_select_in_union(), *last_select;
  DBUG_ENTER("st_select_lex_unit::exec");

  LINT_INIT(last_select);

  if (executed && !(dependent || uncacheable))
    DBUG_RETURN(0);
  executed= 1;

  if ((dependent || uncacheable) || !item || !item->assigned())
  {
    if (optimized && item && item->assigned())
    {
      item->assigned(0); // We will reinit & rexecute unit
      item->reset();
      table->file->delete_all_rows();
    }
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
    {
      last_select=sl;
      if (optimized)
	res= sl->join->reinit();
      else
      {
	JOIN *join= new JOIN(thd, sl->item_list,
			     sl->options | thd->options | SELECT_NO_UNLOCK,
			     union_result);
	thd->lex.current_select= sl;
	offset_limit_cnt= sl->offset_limit;
	select_limit_cnt= sl->select_limit+sl->offset_limit;
	if (select_limit_cnt < sl->select_limit)
	  select_limit_cnt= HA_POS_ERROR;		// no limit
	if (select_limit_cnt == HA_POS_ERROR)
	  sl->options&= ~OPTION_FOUND_ROWS;

	res= join->prepare(&sl->ref_pointer_array,
			   (TABLE_LIST*) sl->table_list.first, sl->with_wild,
			   sl->where,
			   ((sl->braces) ? sl->order_list.elements : 0) +
			   sl->group_list.elements,
			   (sl->braces) ?
			   (ORDER *)sl->order_list.first : (ORDER *) 0,
			   (ORDER*) sl->group_list.first,
			   sl->having,
			   (ORDER*) NULL,
			   sl, this, t_and_f);
	t_and_f=0;
	if (res | thd->is_fatal_error)
	{
	  thd->lex.current_select= lex_select_save;
	  DBUG_RETURN(res);
	}
	res= sl->join->optimize();
      }
      if (!res)
      {
	sl->join->exec();
	res= sl->join->error;
	if (!res && union_result->flush())
	{
	  thd->lex.current_select= lex_select_save;
	  DBUG_RETURN(1);
	}
      }
      if (res)
      {
	thd->lex.current_select= lex_select_save;
	DBUG_RETURN(res);
      }
      do_print_slow|= select_cursor->options;
    }
  }
  optimized= 1;

  /* Send result to 'result' */

  // to correct ORDER BY reference resolving
  thd->lex.current_select= select_cursor;
  res= -1;
  {
    List<Item_func_match> empty_list;
    empty_list.empty();

    if (!thd->is_fatal_error)			// Check if EOM
    {
      SELECT_LEX *fake_select  = new SELECT_LEX();
      fake_select->make_empty_select(last_select);
      offset_limit_cnt= (select_cursor->braces ?
			 global_parameters->offset_limit : 0);
      select_limit_cnt= (select_cursor->braces ?
			 global_parameters->select_limit+
			 global_parameters->offset_limit : HA_POS_ERROR);
      if (select_limit_cnt < global_parameters->select_limit)
	select_limit_cnt= HA_POS_ERROR;		// no limit
      if (select_limit_cnt == HA_POS_ERROR)
	thd->options&= ~OPTION_FOUND_ROWS;
      fake_select->ftfunc_list= &empty_list;

      res= mysql_select(thd, &ref_pointer_array, &result_table_list,
			0, item_list, NULL,
			global_parameters->order_list.elements,
			(ORDER*)global_parameters->order_list.first,
			(ORDER*) NULL, NULL, (ORDER*) NULL,
			thd->options, result, this, fake_select, 0);
      if (found_rows_for_union && !res)
	thd->limit_found_rows = (ulonglong)table->file->records;
      fake_select->exclude();
      delete fake_select;
      /*
	Mark for slow query log if any of the union parts didn't use
	indexes efficiently
      */
      select_cursor->options= ((select_cursor->options &
				~(QUERY_NO_INDEX_USED |
				  QUERY_NO_GOOD_INDEX_USED)) |
			       do_print_slow &
			       (QUERY_NO_INDEX_USED |
				QUERY_NO_GOOD_INDEX_USED));
    }
  }
  thd->lex.current_select= lex_select_save;
  DBUG_RETURN(res);
}

int st_select_lex_unit::cleanup()
{
  int error= 0;
  DBUG_ENTER("st_select_lex_unit::cleanup");

  if (union_result)
  {
    delete union_result;
    if (table)
      free_tmp_table(thd, table);
    table= 0; // Safety
  }
  for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
  {
    JOIN *join;
    if ((join= sl->join))
    {
      error|= sl->join->cleanup(thd);
      delete join;
    }
  }
  DBUG_RETURN(error);
}
<commit_msg>Post - post merge fix.<commit_after>/* Copyright (C) 2000-2003 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; either version 2 of the License, or
   (at your option) any later version.

   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 */

/*
  UNION  of select's
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
*/

#include "mysql_priv.h"
#include "sql_select.h"

int mysql_union(THD *thd, LEX *lex, select_result *result,
		SELECT_LEX_UNIT *unit, bool tables_and_fields_initied)
{
  DBUG_ENTER("mysql_union");
  int res= 0;
  if (!(res= unit->prepare(thd, result, tables_and_fields_initied)))
    res= unit->exec();
  res|= unit->cleanup();
  DBUG_RETURN(res);
}

/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/

select_union::select_union(TABLE *table_par)
  :table(table_par), not_describe(0)
{
  bzero((char*) &info,sizeof(info));
  /*
    We can always use DUP_IGNORE because the temporary table will only
    contain a unique key if we are using not using UNION ALL
  */
  info.handle_duplicates= DUP_IGNORE;
}

select_union::~select_union()
{
}

int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
  unit= u;
  if (not_describe && list.elements != table->fields)
  {
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
	       ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
    return -1;
  }
  return 0;
}

bool select_union::send_data(List<Item> &values)
{
  if (unit->offset_limit_cnt)
  {						// using limit offset,count
    unit->offset_limit_cnt--;
    return 0;
  }
  fill_record(table->field,values);
  if (thd->net.report_error || write_record(table,&info))
  {
    if (thd->net.last_errno == ER_RECORD_FILE_FULL)
    {
      thd->clear_error(); // do not report user about table overflow
      if (create_myisam_from_heap(thd, table, tmp_table_param,
				  info.last_errno, 0))
	return 1;
    }
    else
      return 1;
  }
  return 0;
}

bool select_union::send_eof()
{
  return 0;
}

bool select_union::flush()
{
  int error;
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
  {
    table->file->print_error(error,MYF(0));
    ::send_error(thd);
    return 1;
  }
  return 0;
}

int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
				bool tables_and_fields_initied)
{
  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
  SELECT_LEX *select_cursor;
  DBUG_ENTER("st_select_lex_unit::prepare");

  if (prepared)
    DBUG_RETURN(0);
  prepared= 1;
  res= 0;
  found_rows_for_union= 0;
  TMP_TABLE_PARAM *tmp_table_param= (TMP_TABLE_PARAM *)sql_calloc(sizeof(TMP_TABLE_PARAM));
  result= sel_result;
  t_and_f= tables_and_fields_initied;

  thd->lex.current_select= select_cursor= first_select_in_union();
  /* Global option */
  if (((void*)(global_parameters)) == ((void*)this))
  {
    found_rows_for_union= first_select()->options & OPTION_FOUND_ROWS &&
      global_parameters->select_limit;
    if (found_rows_for_union)
      first_select()->options ^=  OPTION_FOUND_ROWS;
  }
  if (t_and_f)
  {
    // Item list and tables will be initialized by mysql_derived
    item_list= select_cursor->item_list;
  }
  else
  {
    item_list.empty();
    TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;

    if (setup_tables(first_table) ||
	setup_wild(thd, first_table, select_cursor->item_list, 0,
		   select_cursor->with_wild))
      goto err;
    List_iterator<Item> it(select_cursor->item_list);
    Item *item;
    while((item=it++))
      item->maybe_null=1;
    item_list= select_cursor->item_list;
    select_cursor->with_wild= 0;
    if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
			(item_list.elements + select_cursor->with_sum_func +
			 select_cursor->order_list.elements +
			 select_cursor->group_list.elements)) ||
	setup_fields(thd, select_cursor->ref_pointer_array, first_table,
		     item_list, 0, 0, 1))
      goto err;
    t_and_f= 1;
  }

  tmp_table_param->field_count=item_list.elements;
  if (!(table= create_tmp_table(thd, tmp_table_param, item_list,
				(ORDER*) 0, !union_option,
				1, (select_cursor->options | thd->options |
				    TMP_TABLE_ALL_COLUMNS),
				HA_POS_ERROR)))
    goto err;
  table->file->extra(HA_EXTRA_WRITE_CACHE);
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
  bzero((char*) &result_table_list,sizeof(result_table_list));
  result_table_list.db= (char*) "";
  result_table_list.real_name=result_table_list.alias= (char*) "union";
  result_table_list.table=table;

  if (!(union_result=new select_union(table)))
    goto err;

  union_result->not_describe=1;
  union_result->tmp_table_param=tmp_table_param;

  /*
    The following piece of code is placed here solely for the purpose of
    getting correct results with EXPLAIN when UNION is withing a sub-select
    or derived table ...
  */

  if (thd->lex.describe)
  {
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
    {
      JOIN *join= new JOIN(thd, sl->item_list,
			   sl->options | thd->options | SELECT_NO_UNLOCK,
			   union_result);
      thd->lex.current_select= sl;
      offset_limit_cnt= sl->offset_limit;
      select_limit_cnt= sl->select_limit+sl->offset_limit;
      if (select_limit_cnt < sl->select_limit)
	select_limit_cnt= HA_POS_ERROR;		// no limit
      if (select_limit_cnt == HA_POS_ERROR)
	sl->options&= ~OPTION_FOUND_ROWS;

      res= join->prepare(&sl->ref_pointer_array,
			 (TABLE_LIST*) sl->table_list.first, sl->with_wild,
			 sl->where,
			 ((sl->braces) ? sl->order_list.elements : 0) +
			 sl->group_list.elements,
			 (sl->braces) ?
			 (ORDER *)sl->order_list.first : (ORDER *) 0,
			 (ORDER*) sl->group_list.first,
			 sl->having,
			 (ORDER*) NULL,
			 sl, this, t_and_f);
      t_and_f= 0;
      if (res || thd->is_fatal_error)
	goto err;
    }
  }

  item_list.empty();
  thd->lex.current_select= lex_select_save;
  {
    List_iterator<Item> it(select_cursor->item_list);
    Field **field;

    for (field= table->field; *field; field++)
    {
      (void) it++;
      if (item_list.push_back(new Item_field(*field)))
	DBUG_RETURN(-1);
    }
  }

  DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0);
err:
  thd->lex.current_select= lex_select_save;
  DBUG_RETURN(-1);
}

int st_select_lex_unit::exec()
{
  int do_print_slow= 0;
  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
  SELECT_LEX *select_cursor=first_select_in_union(), *last_select;
  DBUG_ENTER("st_select_lex_unit::exec");

  LINT_INIT(last_select);

  if (executed && !(dependent || uncacheable))
    DBUG_RETURN(0);
  executed= 1;

  if ((dependent || uncacheable) || !item || !item->assigned())
  {
    if (optimized && item && item->assigned())
    {
      item->assigned(0); // We will reinit & rexecute unit
      item->reset();
      table->file->delete_all_rows();
    }
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
    {
      last_select=sl;
      if (optimized)
	res= sl->join->reinit();
      else
      {
	JOIN *join= new JOIN(thd, sl->item_list,
			     sl->options | thd->options | SELECT_NO_UNLOCK,
			     union_result);
	thd->lex.current_select= sl;
	offset_limit_cnt= sl->offset_limit;
	select_limit_cnt= sl->select_limit+sl->offset_limit;
	if (select_limit_cnt < sl->select_limit)
	  select_limit_cnt= HA_POS_ERROR;		// no limit
	if (select_limit_cnt == HA_POS_ERROR)
	  sl->options&= ~OPTION_FOUND_ROWS;

	res= join->prepare(&sl->ref_pointer_array,
			   (TABLE_LIST*) sl->table_list.first, sl->with_wild,
			   sl->where,
			   ((sl->braces) ? sl->order_list.elements : 0) +
			   sl->group_list.elements,
			   (sl->braces) ?
			   (ORDER *)sl->order_list.first : (ORDER *) 0,
			   (ORDER*) sl->group_list.first,
			   sl->having,
			   (ORDER*) NULL,
			   sl, this, t_and_f);
	t_and_f=0;
	if (res | thd->is_fatal_error)
	{
	  thd->lex.current_select= lex_select_save;
	  DBUG_RETURN(res);
	}
	res= sl->join->optimize();
      }
      if (!res)
      {
	sl->join->exec();
	res= sl->join->error;
	if (!res && union_result->flush())
	{
	  thd->lex.current_select= lex_select_save;
	  DBUG_RETURN(1);
	}
      }
      if (res)
      {
	thd->lex.current_select= lex_select_save;
	DBUG_RETURN(res);
      }
      do_print_slow|= select_cursor->options;
    }
  }
  optimized= 1;

  /* Send result to 'result' */

  // to correct ORDER BY reference resolving
  thd->lex.current_select= select_cursor;
  res= -1;
  {
    List<Item_func_match> empty_list;
    empty_list.empty();

    if (!thd->is_fatal_error)			// Check if EOM
    {
      SELECT_LEX *fake_select  = new SELECT_LEX();
      fake_select->make_empty_select(last_select);
      offset_limit_cnt= (select_cursor->braces ?
			 global_parameters->offset_limit : 0);
      select_limit_cnt= (select_cursor->braces ?
			 global_parameters->select_limit+
			 global_parameters->offset_limit : HA_POS_ERROR);
      if (select_limit_cnt < global_parameters->select_limit)
	select_limit_cnt= HA_POS_ERROR;		// no limit
      if (select_limit_cnt == HA_POS_ERROR)
	thd->options&= ~OPTION_FOUND_ROWS;
      fake_select->ftfunc_list= &empty_list;

      res= mysql_select(thd, &ref_pointer_array, &result_table_list,
			0, item_list, NULL,
			global_parameters->order_list.elements,
			(ORDER*)global_parameters->order_list.first,
			(ORDER*) NULL, NULL, (ORDER*) NULL,
			thd->options, result, this, fake_select, 0);
      if (found_rows_for_union && !res)
	thd->limit_found_rows = (ulonglong)table->file->records;
      fake_select->exclude();
      delete fake_select;
      /*
	Mark for slow query log if any of the union parts didn't use
	indexes efficiently
      */
      select_cursor->options= ((select_cursor->options &
				~(QUERY_NO_INDEX_USED |
				  QUERY_NO_GOOD_INDEX_USED)) |
			       do_print_slow &
			       (QUERY_NO_INDEX_USED |
				QUERY_NO_GOOD_INDEX_USED));
    }
  }
  thd->lex.current_select= lex_select_save;
  DBUG_RETURN(res);
}

int st_select_lex_unit::cleanup()
{
  int error= 0;
  DBUG_ENTER("st_select_lex_unit::cleanup");

  if (union_result)
  {
    delete union_result;
    if (table)
      free_tmp_table(thd, table);
    table= 0; // Safety
  }
  for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
  {
    JOIN *join;
    if ((join= sl->join))
    {
      error|= sl->join->cleanup(thd);
      delete join;
    }
  }
  DBUG_RETURN(error);
}
<|endoftext|>


<commit_before>/*
 * Appender.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "PortabilityImpl.hh"
#include <log4cpp/Appender.hh>
#include <iostream>

namespace log4cpp {
	static int appenders_nifty_counter; // zero initialized at load time
	static char appenderMapStorage_buf[sizeof(Appender::AppenderMapStorage)]; // memory for the nifty-counter singleton object
	Appender::AppenderMapStorage &Appender::_appenderMapStorageInstance = reinterpret_cast<Appender::AppenderMapStorage&> (appenderMapStorage_buf); // memory for placement new

	Appender::AppenderMapStorage::AppenderMapStorage()  {
		_allAppenders = new AppenderMap();
	};
	Appender::AppenderMapStorage::~AppenderMapStorage() {
		_deleteAllAppenders();
		delete _allAppenders;
	};

	Appender::AppenderMapStorageInitializer::AppenderMapStorageInitializer() {
		 if (appenders_nifty_counter++ == 0) {
// MSVC's <crtdbg.h> requires redefinition of the new operator, but could not deal with placement new form of it
#ifdef MSVC_MEMORY_LEAK_CHECK
#pragma push_macro("new")
#define new new
#endif // MSVC_MEMORY_LEAK_CHECK
			 new (&_appenderMapStorageInstance) AppenderMapStorage(); // placement new
#ifdef MSVC_MEMORY_LEAK_CHECK
#pragma pop_macro("new")
#endif // MSVC_MEMORY_LEAK_CHECK
		 }
 	}
	Appender::AppenderMapStorageInitializer::~AppenderMapStorageInitializer() {
		if (--appenders_nifty_counter == 0) {
			(&_appenderMapStorageInstance)->~AppenderMapStorage ();
		}
	}

    /* assume _appenderMapMutex locked */
    Appender::AppenderMap& Appender::_getAllAppenders() {
		return *_appenderMapStorageInstance._allAppenders;
    }

    Appender* Appender::getAppender(const std::string& name) {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        AppenderMap& allAppenders = Appender::_getAllAppenders();
        AppenderMap::iterator i = allAppenders.find(name);
        return (allAppenders.end() == i) ? NULL : ((*i).second);
    }

    void Appender::_addAppender(Appender* appender) {
        //REQUIRE(_allAppenders.find(appender->getName()) == _getAllAppenders().end())
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        _getAllAppenders()[appender->getName()] = appender;
    }

    void Appender::_removeAppender(Appender* appender) {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
		//private called from destructor only, but may be triggered by client code in several treads
        _getAllAppenders().erase(appender->getName());
    }

    bool Appender::reopenAll() {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        bool result = true;
        AppenderMap& allAppenders = _getAllAppenders();
        for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
            result = result && ((*i).second)->reopen();
        }

        return result;
    }

    void Appender::closeAll() {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        AppenderMap& allAppenders = _getAllAppenders();
        for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
            ((*i).second)->close();
        }
    }

    void Appender::_deleteAllAppenders() {
		// deleting each appenders will cause a lock on Appender::_appenderMapMutex to be obtained again within destructor. to avoid nested locks:
		std::vector<Appender*> appenders;
		{
			threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
			AppenderMap& allAppenders = _getAllAppenders();
			appenders.reserve(allAppenders.size());
			for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); ) {
				Appender* app = (*i).second;
				++i;
				appenders.push_back(app);
			}
		    allAppenders.clear();
		}
		_deleteAllAppendersWOLock(appenders);
	}

    void Appender::_deleteAllAppendersWOLock(std::vector<Appender*> &appenders) {
    /* assume Appender::_appenderMapMutex not locked */
        AppenderMap& allAppenders = _getAllAppenders();
        for(std::vector<Appender*>::iterator i = appenders.begin(); i != appenders.end(); ++i) {
            Appender *app = (*i);
            delete (app);
        }
    }

    Appender::Appender(const std::string& name) :
        _name(name) {
        _addAppender(this);
    }

    Appender::~Appender() {
        _removeAppender(this);
    }
}
<commit_msg>fix for bug 146 by Ryan Schmidt<commit_after>/*
 * Appender.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "PortabilityImpl.hh"
#include <log4cpp/Appender.hh>
#include <iostream>

namespace log4cpp {
	static int appenders_nifty_counter; // zero initialized at load time
	static char appenderMapStorage_buf[sizeof(Appender::AppenderMapStorage)]; // memory for the nifty-counter singleton object
	Appender::AppenderMapStorage &Appender::_appenderMapStorageInstance = reinterpret_cast<Appender::AppenderMapStorage&> (appenderMapStorage_buf); // memory for placement new

	Appender::AppenderMapStorage::AppenderMapStorage()  {
		_allAppenders = new AppenderMap();
	}
	Appender::AppenderMapStorage::~AppenderMapStorage() {
		_deleteAllAppenders();
		delete _allAppenders;
	}

	Appender::AppenderMapStorageInitializer::AppenderMapStorageInitializer() {
		 if (appenders_nifty_counter++ == 0) {
// MSVC's <crtdbg.h> requires redefinition of the new operator, but could not deal with placement new form of it
#ifdef MSVC_MEMORY_LEAK_CHECK
#pragma push_macro("new")
#define new new
#endif // MSVC_MEMORY_LEAK_CHECK
			 new (&_appenderMapStorageInstance) AppenderMapStorage(); // placement new
#ifdef MSVC_MEMORY_LEAK_CHECK
#pragma pop_macro("new")
#endif // MSVC_MEMORY_LEAK_CHECK
		 }
 	}
	Appender::AppenderMapStorageInitializer::~AppenderMapStorageInitializer() {
		if (--appenders_nifty_counter == 0) {
			(&_appenderMapStorageInstance)->~AppenderMapStorage ();
		}
	}

    /* assume _appenderMapMutex locked */
    Appender::AppenderMap& Appender::_getAllAppenders() {
		return *_appenderMapStorageInstance._allAppenders;
    }

    Appender* Appender::getAppender(const std::string& name) {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        AppenderMap& allAppenders = Appender::_getAllAppenders();
        AppenderMap::iterator i = allAppenders.find(name);
        return (allAppenders.end() == i) ? NULL : ((*i).second);
    }

    void Appender::_addAppender(Appender* appender) {
        //REQUIRE(_allAppenders.find(appender->getName()) == _getAllAppenders().end())
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        _getAllAppenders()[appender->getName()] = appender;
    }

    void Appender::_removeAppender(Appender* appender) {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
		//private called from destructor only, but may be triggered by client code in several treads
        _getAllAppenders().erase(appender->getName());
    }

    bool Appender::reopenAll() {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        bool result = true;
        AppenderMap& allAppenders = _getAllAppenders();
        for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
            result = result && ((*i).second)->reopen();
        }

        return result;
    }

    void Appender::closeAll() {
        threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
        AppenderMap& allAppenders = _getAllAppenders();
        for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
            ((*i).second)->close();
        }
    }

    void Appender::_deleteAllAppenders() {
		// deleting each appenders will cause a lock on Appender::_appenderMapMutex to be obtained again within destructor. to avoid nested locks:
		std::vector<Appender*> appenders;
		{
			threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
			AppenderMap& allAppenders = _getAllAppenders();
			appenders.reserve(allAppenders.size());
			for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); ) {
				Appender* app = (*i).second;
				++i;
				appenders.push_back(app);
			}
		    allAppenders.clear();
		}
		_deleteAllAppendersWOLock(appenders);
	}

    void Appender::_deleteAllAppendersWOLock(std::vector<Appender*> &appenders) {
    /* assume Appender::_appenderMapMutex not locked */
        AppenderMap& allAppenders = _getAllAppenders();
        for(std::vector<Appender*>::iterator i = appenders.begin(); i != appenders.end(); ++i) {
            Appender *app = (*i);
            delete (app);
        }
    }

    Appender::Appender(const std::string& name) :
        _name(name) {
        _addAppender(this);
    }

    Appender::~Appender() {
        _removeAppender(this);
    }
}
<|endoftext|>


<commit_before>#include <mi/Argument.hpp>
#include <mi/Parse.hpp>
#include <deque>

namespace mi
{
        class Argument::Impl
        {
        private:
                Impl ( const Impl& that );
                void operator = ( const Impl& that );
        public:
                Impl ( void )
                {
                        return;
                }

                ~Impl ( void )
                {
                        this->_argv.clear();
                        return;
                }

                void add ( const std::string& str )
                {
                        this->_argv.push_back ( str );
                        return;
                }

                std::string get ( const int i ) const
                {
                        if ( this->is_valid ( i ) ) return this->_argv.at ( i );
                        else return std::string();
                }

                int size ( void ) const
                {
                        return static_cast<int> ( this->_argv.size() );
                }
        private:
                bool is_valid ( const int i ) const
                {
                        return ( 0 <= i && i < this->size() );
                }
        private:
                std::deque<std::string>  _argv; ///< Arguments.
        };

        Argument::Argument ( int argc, char** argv ) : _impl ( new Argument::Impl() )
        {
                for ( int i = 0 ; i < argc ; ++i ) {
                        this->_impl->add ( std::string ( argv[i] ) );
                }
                return;
        }

        Argument::~Argument ( void )
        {
                if ( this->_impl != NULL ) {
                        delete this->_impl;
                        this->_impl = NULL;
                }
                return;
        }

        int
        Argument::size ( void ) const
        {
                return this->_impl->size();
        }

        Argument&
        Argument::add ( const std::string& str )
        {
                this->_impl->add ( str );
                return *this;
        }

        bool
        Argument::exist ( const std::string& key, const int offset ) const
        {
                return ( this->find ( key, offset ) > -1 );
        }

        template <typename T>
        T
        Argument::get ( const int idx ) const
        {
                return mi::parse<T> ( this->_impl->get ( idx ) ) ;
        }

        int
        Argument::find ( const std::string& key, const int offset ) const
        {
                if ( offset < 0 ) return -1;
                for ( int i = 0 ; i < this->size() - offset ; ++i ) {
                        if ( this->_impl->get ( i ).compare ( key ) == 0 ) return i + offset;
                }
                return -1; // any arguments are not matched.
        };

        void
        Argument::print ( std::ostream& out )
        {
                for ( int i = 0  ; i < this->size() ; ++i ) {
                        std::string str = this->_impl->get ( i );
                        if ( str.find ( "-", 0 ) == 0 ) out << std::endl; //
                        out << str << " ";
                }
                out << std::endl;
                return;
        }

#define ARGUMENT__GET(TYPE) template TYPE Argument::get<TYPE> ( const int idx ) const
        ARGUMENT__GET ( unsigned char );
        ARGUMENT__GET ( char );
        ARGUMENT__GET ( unsigned short );
        ARGUMENT__GET ( short );
        ARGUMENT__GET ( unsigned int );
        ARGUMENT__GET ( int );
        ARGUMENT__GET ( float );
        ARGUMENT__GET ( double );
        ARGUMENT__GET ( std::string );
}

<commit_msg>snapshot<commit_after>#include <mi/Argument.hpp>
#include <mi/Parse.hpp>
#include <deque>

namespace mi
{
        class Argument::Impl
        {
        private:
                Impl ( const Impl& that );
                void operator = ( const Impl& that );
        public:
                Impl ( void )
                {
                        return;
                }

                ~Impl ( void )
                {
                        this->_argv.clear();
                        return;
                }

                void add ( const std::string& str )
                {
                        this->_argv.push_back ( str );
                        return;
                }

                std::string get ( const int i ) const
                {
                        if ( this->is_valid ( i ) ) return this->_argv.at ( i );
                        else return std::string();
                }

                int size ( void ) const
                {
                        return static_cast<int> ( this->_argv.size() );
                }
        private:
                bool is_valid ( const int i ) const
                {
                        return ( 0 <= i && i < this->size() );
                }
        private:
                std::deque<std::string>  _argv; ///< Arguments.
        };

        Argument::Argument ( int argc, char** argv ) : _impl ( new Argument::Impl() )
        {
                for ( int i = 0 ; i < argc ; ++i ) {
                        this->_impl->add ( std::string ( argv[i] ) );
                }
                return;
        }

        Argument::~Argument ( void )
        {
                if ( this->_impl != NULL ) {
                        delete this->_impl;
                        this->_impl = NULL;
                }
                return;
        }

        int
        Argument::size ( void ) const
        {
                return this->_impl->size();
        }

        Argument&
        Argument::add ( const std::string& str )
        {
                this->_impl->add ( str );
                return *this;
        }

        bool
        Argument::exist ( const std::string& key, const int offset ) const
        {
                return ( this->find ( key, offset ) > -1 );
        }

        template <typename T>
        T
        Argument::get ( const int idx ) const
        {
                return mi::parse<T> ( this->_impl->get ( idx ) ) ;
        }

        int
        Argument::find ( const std::string& key, const int offset ) const
        {
                if ( offset < 0 ) return -1;
                for ( int i = 0 ; i < this->size() - offset ; ++i ) {
                        if ( this->_impl->get ( i ).compare ( key ) == 0 ) return i + offset;
                }
                return -1; // any arguments are not matched.
        };

        void
        Argument::print ( std::ostream& out )
        {
                for ( int i = 0  ; i < this->size() ; ++i ) {
                        std::string str = this->_impl->get ( i );
                        if ( str.find ( "-", 0 ) == 0 ) out << std::endl; //
                        out << str << " ";
                }
                out << std::endl;
                return;
        }

#define ARGUMENT__GET(TYPE) template TYPE Argument::get<TYPE> ( const int idx ) const
        ARGUMENT__GET ( unsigned char );
        ARGUMENT__GET ( char );
        ARGUMENT__GET ( unsigned short );
        ARGUMENT__GET ( short );
        ARGUMENT__GET ( unsigned int );
        ARGUMENT__GET ( int );
        ARGUMENT__GET ( float );
        ARGUMENT__GET ( double );
        ARGUMENT__GET ( std::string );
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <Validator.h>
#include <Calculator.h>
#include <Representer.h>
#include <XmlManager.h>

// Some kind of RAII helper.
struct Finally
{
    Finally  (const std::function <void ()> action) : finalAction (action) {};
    ~Finally ()                                      {finalAction ();};
    const std::function <void ()>                     finalAction;
};

int main (int argc, char * argv [])
{
    using Pslrk::Core::Exception;
    using Pslrk::Core::Validator;
    using Pslrk::Core::Calculator;
    using Pslrk::Core::Representer;
    using Pslrk::Core::XmlManager;

    std::vector <std::string> codes;
    XmlManager * xmlManager {nullptr};
    Finally xmlManagerFinally ([&](){delete xmlManager;});

    auto actionHelp = []() {
        std::cout << "[Command]         [Parameters]    [Description]" << std::endl;
        std::cout << "help                              Print this message." << std::endl;
        std::cout << "push code         <string>        Put specified code into local storage." << std::endl;
        std::cout << "push family       <string>        Put family of specified code into local storage." << std::endl;
        std::cout << "show codes                        Print local storage." << std::endl;
        std::cout << "show msl                          Print MSL for each of codes from local storage." << std::endl;
        std::cout << "show family                       Print family for each of codes from local storage." << std::endl;
        std::cout << "show id                           Print ID for each of codes from local storage." << std::endl;
        std::cout << "to string         <int>           Convert each of codes from local storage into string format." << std::endl;
        std::cout << "to hex                            Convert each of codes from local storage into hex format." << std::endl;
        std::cout << "erase code        <int>           Erase code with specified index from local storage." << std::endl;
        std::cout << "clear codes                       Clear local storage." << std::endl;
        std::cout << "open base         <string>        Open XML file (whith codes)." << std::endl;
        std::cout << "close base                        Close XML file." << std::endl;
        std::cout << "save base                         Save XML file." << std::endl;
        std::cout << "show base                         Print codes which contained in XML file." << std::endl;
        std::cout << "add base                          Add code to XML file." << std::endl;
        std::cout << "remove base       <string>        Remove code from XML file." << std::endl;
        std::cout << "search base       <string>        Search code in XML file." << std::endl;
        std::cout << "quit                              Exit the program." << std::endl;
    };

    auto actionPushCode = [&](const std::string & code) {
        codes.push_back (code);
    };

    auto actionPushFamily = [&](const std::string & code) {
        for (const auto & variant : Representer::GenerateCodeFamily (code) ) {
            codes.push_back (variant);
        }
    };

    auto actionShowCodes = [&]() {
        for (const auto & code : codes) {
            std::cout << code << std::endl;
        }
    };

    auto actionShowMsl = [&]() {
        for (const auto & code : codes) {
            std::cout << Calculator::CalculateMsl (code) << std::endl;
        }
    };

    auto actionShowFamily = [&]() {
        for (const auto & code : codes) {
            for (const auto & variant : Representer::GenerateCodeFamily (code) ) {
                std::cout << code << " - " << variant << std::endl;
            }
        }
    };

    auto actionShowId = [&]() {
        for (const auto & code : codes) {
            std::cout << code << " - " << Representer::DetectCodeId (code) << std::endl;
        }
    };

    auto actionToString = [&](const size_t length = 0) {
        for (auto & code : codes) {
            if (length) {
                code = Representer::HexViewToStringView (code, length);
            }
            else {
                code = Representer::HexViewToStringView (code);
            }
        }
    };

    auto actionToHex = [&]() {
        for (auto & code : codes) {
            code = Representer::StringViewToHexView (code);
        }
    };

    auto actionEraseCode = [&](const int position) {
        if (position < codes.size () ) {
            codes.erase (codes.begin () + position);
        }
    };

    auto actionClearCodes = [&]() {
        codes.clear ();
    };

    auto actionOpenBase = [&](const std::string & fileName) {
        try {
            xmlManager = new XmlManager (fileName);
        }
        catch (Exception & e) {
            std::cout << e.what () << std::endl;
        }
    };

    auto actionCloseBase = [&]() {
        delete xmlManager;
        xmlManager = nullptr;
    };

    auto actionSaveBase = [&]() {
        if (xmlManager) {
            try {
                xmlManager->Save ();
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to save file which was not opened." << std::endl;
        }
    };

    auto actionShowBase = [&]() {
        if (xmlManager) {
            const pugi::xml_node codes = xmlManager->Select ("/").node ();
            for (const auto & code : codes.child ("codes").children ("code") ) {
                std::cout << " Code: id       = " << code.attribute ("id").value     () << std::endl <<
                             "       length   = " << code.attribute ("length").value () << std::endl <<
                             "       max PSL  = " << code.attribute ("maxpsl").value () << std::endl <<
                             "       sequence = " << code.child_value ("sequence")      << std::endl;
                std::cout << std::endl;
            }
        }
        else {
            std::cout << "Attempting to print file which was not opened." << std::endl;
        }
    };

    auto actionAddBase = [&]() {
        if (xmlManager) {
            std::string input {""};
            std::cout << "Input code: > ";
            std::getline (std::cin, input);
            std::string stringView;
            if      (Validator::ValidateStringView (input) == Pslrk::Core::viewIsValid) {
                stringView = input;
            }
            else if (Validator::ValidateHexView    (input) == Pslrk::Core::viewIsValid) {
                stringView = Representer::HexViewToStringView (input);
            }
            else {
                std::cout << "Invalid code, stop adding!" << std::endl;
                return;
            }

            const std::string codeId {Representer::DetectCodeId (stringView)};
            const int codeLength = stringView.length ();
            const int maxPsl {Calculator::CalculateMsl (stringView)};

            std::cout << "Sequence: " << stringView << std::endl;
            std::cout << "ID:       " << codeId     << std::endl;
            std::cout << "Length:   " << codeLength << std::endl;
            std::cout << "Max PSL:  " << maxPsl     << std::endl;

            std::cout << "Input reference article: > ";
            std::getline (std::cin, input);
            const std::string referenceArticle  {input};
            std::cout << "Input reference author: > ";
            std::getline (std::cin, input);
            const std::string referenceAuthor {input};
            std::cout << "Input reference link: > ";
            std::getline (std::cin, input);
            const std::string referenceLink   {input};

            xmlManager->Insert (codeId, codeLength, maxPsl, stringView, { {referenceArticle, referenceAuthor, referenceLink} });
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    auto actionRemoveBase = [&](const std::string & id) {
        if (xmlManager) {
            try {
                xmlManager->Remove (id);
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    auto actionSearchBase = [&](const std::string & xPathQuery) {
        if (xmlManager) {
            try {
                pugi::xml_document result;
                result.append_child () = xmlManager->Select (xPathQuery).node ();
                result.print (std::cout);
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    while (true) {
        std::cout << "> ";
        {
            std::string command {""};
            std::getline (std::cin, command);

            if      (0 == command.find ("help") ) {
                actionHelp ();
            }
            else if (0 == command.find ("push code ") ) {
                actionPushCode (command.substr (std::string ("push code ").length () ) );
            }
            else if (0 == command.find ("push family ") ) {
                actionPushFamily (command.substr (std::string ("push family ").length () ) );
            }
            else if (0 == command.find ("show codes") ) {
                actionShowCodes ();
            }
            else if (0 == command.find ("show msl") ) {
                actionShowMsl ();
            }
            else if (0 == command.find ("show family") ) {
                actionShowFamily ();
            }
            else if (0 == command.find ("show id") ) {
                actionShowId ();
            }
            else if (0 == command.find ("to string") ) {
                if (command.length () > std::string ("to string ").length () ) {
                    actionToString (boost::lexical_cast <int> (command.substr (std::string ("to string ").length () ) ) );
                }
                else {
                    actionToString ();
                }
            }
            else if (0 == command.find ("to hex") ) {
                actionToHex ();
            }
            else if (0 == command.find ("quit") ) {
                return EXIT_SUCCESS;
            }
            else if (0 == command.find ("erase code ") ) {
                actionEraseCode (boost::lexical_cast <int> (command.substr (std::string ("erase code ").length () ) ) );
            }
            else if (0 == command.find ("clear codes") ) {
                actionClearCodes ();
            }
            else if (0 == command.find ("open base") ) {
                actionOpenBase (command.substr (std::string ("open base ").length () ) );
            }
            else if (0 == command.find ("close base") ) {
                actionCloseBase ();
            }
            else if (0 == command.find ("save base") ) {
                actionSaveBase ();
            }
            else if (0 == command.find ("show base") ) {
                actionShowBase ();
            }
            else if (0 == command.find ("add base") ) {
                actionAddBase ();
            }
            else if (0 == command.find ("remove base") ) {
                actionRemoveBase (command.substr (std::string ("remove base ").length () ) );
            }
            else if (0 == command.find ("search base") ) {
                actionSearchBase (command.substr (std::string ("search base ").length () ) );
            }
            else {
                std::cout << "Unrecognized command: " << command << std::endl;
            }
        }
    }

    return EXIT_SUCCESS;
}<commit_msg>CodeManager CLI was updated for the last XmlManager API changes.<commit_after>#include <stdlib.h>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <Validator.h>
#include <Calculator.h>
#include <Representer.h>
#include <XmlManager.h>

// Some kind of RAII helper.
struct Finally
{
    Finally  (const std::function <void ()> action) : finalAction (action) {};
    ~Finally ()                                      {finalAction ();};
    const std::function <void ()>                     finalAction;
};

int main (int argc, char * argv [])
{
    using Pslrk::Core::Exception;
    using Pslrk::Core::Validator;
    using Pslrk::Core::Calculator;
    using Pslrk::Core::Representer;
    using Pslrk::Core::XmlManager;

    std::vector <std::string> codes;
    XmlManager * xmlManager {nullptr};
    Finally xmlManagerFinally ([&](){delete xmlManager;});

    auto actionHelp = []() {
        std::cout << "[Command]         [Parameters]    [Description]" << std::endl;
        std::cout << "help                              Print this message." << std::endl;
        std::cout << "push code         <string>        Put specified code into local storage." << std::endl;
        std::cout << "push family       <string>        Put family of specified code into local storage." << std::endl;
        std::cout << "show codes                        Print local storage." << std::endl;
        std::cout << "show msl                          Print MSL for each of codes from local storage." << std::endl;
        std::cout << "show family                       Print family for each of codes from local storage." << std::endl;
        std::cout << "show id                           Print ID for each of codes from local storage." << std::endl;
        std::cout << "to string         <int>           Convert each of codes from local storage into string format." << std::endl;
        std::cout << "to hex                            Convert each of codes from local storage into hex format." << std::endl;
        std::cout << "erase code        <int>           Erase code with specified index from local storage." << std::endl;
        std::cout << "clear codes                       Clear local storage." << std::endl;
        std::cout << "open base         <string>        Open XML file (whith codes)." << std::endl;
        std::cout << "close base                        Close XML file." << std::endl;
        std::cout << "save base                         Save XML file." << std::endl;
        std::cout << "show base                         Print codes which contained in XML file." << std::endl;
        std::cout << "add base                          Add code to XML file." << std::endl;
        std::cout << "remove base       <string>        Remove code from XML file." << std::endl;
        std::cout << "search base       <string>        Search code in XML file." << std::endl;
        std::cout << "quit                              Exit the program." << std::endl;
    };

    auto actionPushCode = [&](const std::string & code) {
        codes.push_back (code);
    };

    auto actionPushFamily = [&](const std::string & code) {
        for (const auto & variant : Representer::GenerateCodeFamily (code) ) {
            codes.push_back (variant);
        }
    };

    auto actionShowCodes = [&]() {
        for (const auto & code : codes) {
            std::cout << code << std::endl;
        }
    };

    auto actionShowMsl = [&]() {
        for (const auto & code : codes) {
            std::cout << Calculator::CalculateMsl (code) << std::endl;
        }
    };

    auto actionShowFamily = [&]() {
        for (const auto & code : codes) {
            for (const auto & variant : Representer::GenerateCodeFamily (code) ) {
                std::cout << code << " - " << variant << std::endl;
            }
        }
    };

    auto actionShowId = [&]() {
        for (const auto & code : codes) {
            std::cout << code << " - " << Representer::DetectCodeId (code) << std::endl;
        }
    };

    auto actionToString = [&](const size_t length = 0) {
        for (auto & code : codes) {
            if (length) {
                code = Representer::HexViewToStringView (code, length);
            }
            else {
                code = Representer::HexViewToStringView (code);
            }
        }
    };

    auto actionToHex = [&]() {
        for (auto & code : codes) {
            code = Representer::StringViewToHexView (code);
        }
    };

    auto actionEraseCode = [&](const int position) {
        if (position < codes.size () ) {
            codes.erase (codes.begin () + position);
        }
    };

    auto actionClearCodes = [&]() {
        codes.clear ();
    };

    auto actionOpenBase = [&](const std::string & fileName) {
        try {
            xmlManager = new XmlManager (fileName);
        }
        catch (Exception & e) {
            std::cout << e.what () << std::endl;
        }
    };

    auto actionCloseBase = [&]() {
        delete xmlManager;
        xmlManager = nullptr;
    };

    auto actionSaveBase = [&]() {
        if (xmlManager) {
            try {
                xmlManager->Save ();
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to save file which was not opened." << std::endl;
        }
    };

    auto actionShowBase = [&]() {
        if (xmlManager) {
            const pugi::xml_node codes = xmlManager->Select ("/").node ();
            for (const auto & code : codes.child ("codes").children ("code") ) {
                std::cout << " Code: id       = " << code.attribute ("id").value     () << std::endl <<
                             "       length   = " << code.attribute ("length").value () << std::endl <<
                             "       max PSL  = " << code.attribute ("maxpsl").value () << std::endl <<
                             "       sequence = " << code.child_value ("sequence")      << std::endl;
                std::cout << std::endl;
            }
        }
        else {
            std::cout << "Attempting to print file which was not opened." << std::endl;
        }
    };

    auto actionAddBase = [&]() {
        if (xmlManager) {
            std::string input {""};
            std::cout << "Input code: > ";
            std::getline (std::cin, input);
            std::string stringView;
            if      (Validator::ValidateStringView (input) == Pslrk::Core::viewIsValid) {
                stringView = input;
            }
            else if (Validator::ValidateHexView    (input) == Pslrk::Core::viewIsValid) {
                stringView = Representer::HexViewToStringView (input);
            }
            else {
                std::cout << "Invalid code, stop adding!" << std::endl;
                return;
            }

            const std::string codeId {Representer::DetectCodeId (stringView)};
            const int codeLength = stringView.length ();
            const int maxPsl {Calculator::CalculateMsl (stringView)};

            std::cout << "Sequence: " << stringView << std::endl;
            std::cout << "ID:       " << codeId     << std::endl;
            std::cout << "Length:   " << codeLength << std::endl;
            std::cout << "Max PSL:  " << maxPsl     << std::endl;

            std::cout << "Input reference article: > ";
            std::getline (std::cin, input);
            const std::string referenceArticle  {input};
            std::cout << "Input reference author: > ";
            std::getline (std::cin, input);
            const std::string referenceAuthor {input};
            std::cout << "Input reference link: > ";
            std::getline (std::cin, input);
            const std::string referenceLink   {input};

            xmlManager->InsertCode (codeId, codeLength, maxPsl, {stringView}, { {referenceArticle, referenceAuthor, referenceLink} });
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    auto actionRemoveBase = [&](const std::string & id) {
        if (xmlManager) {
            try {
                xmlManager->RemoveCode (id);
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    auto actionSearchBase = [&](const std::string & xPathQuery) {
        if (xmlManager) {
            try {
                pugi::xml_document result;
                result.append_child () = xmlManager->Select (xPathQuery).node ();
                result.print (std::cout);
            }
            catch (Exception & e) {
                std::cout << e.what () << std::endl;
            }
        }
        else {
            std::cout << "Attempting to process file which was not opened." << std::endl;
        }
    };

    while (true) {
        std::cout << "> ";
        {
            std::string command {""};
            std::getline (std::cin, command);

            if      (0 == command.find ("help") ) {
                actionHelp ();
            }
            else if (0 == command.find ("push code ") ) {
                actionPushCode (command.substr (std::string ("push code ").length () ) );
            }
            else if (0 == command.find ("push family ") ) {
                actionPushFamily (command.substr (std::string ("push family ").length () ) );
            }
            else if (0 == command.find ("show codes") ) {
                actionShowCodes ();
            }
            else if (0 == command.find ("show msl") ) {
                actionShowMsl ();
            }
            else if (0 == command.find ("show family") ) {
                actionShowFamily ();
            }
            else if (0 == command.find ("show id") ) {
                actionShowId ();
            }
            else if (0 == command.find ("to string") ) {
                if (command.length () > std::string ("to string ").length () ) {
                    actionToString (boost::lexical_cast <int> (command.substr (std::string ("to string ").length () ) ) );
                }
                else {
                    actionToString ();
                }
            }
            else if (0 == command.find ("to hex") ) {
                actionToHex ();
            }
            else if (0 == command.find ("quit") ) {
                return EXIT_SUCCESS;
            }
            else if (0 == command.find ("erase code ") ) {
                actionEraseCode (boost::lexical_cast <int> (command.substr (std::string ("erase code ").length () ) ) );
            }
            else if (0 == command.find ("clear codes") ) {
                actionClearCodes ();
            }
            else if (0 == command.find ("open base") ) {
                actionOpenBase (command.substr (std::string ("open base ").length () ) );
            }
            else if (0 == command.find ("close base") ) {
                actionCloseBase ();
            }
            else if (0 == command.find ("save base") ) {
                actionSaveBase ();
            }
            else if (0 == command.find ("show base") ) {
                actionShowBase ();
            }
            else if (0 == command.find ("add base") ) {
                actionAddBase ();
            }
            else if (0 == command.find ("remove base") ) {
                actionRemoveBase (command.substr (std::string ("remove base ").length () ) );
            }
            else if (0 == command.find ("search base") ) {
                actionSearchBase (command.substr (std::string ("search base ").length () ) );
            }
            else {
                std::cout << "Unrecognized command: " << command << std::endl;
            }
        }
    }

    return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>#include "Globals.h"
#include "Application.h"
#include "ModuleRenderer3D.h"
#include "ModuleCamera3D.h"
#include "ModuleWindow.h"
#include "SceneManager.h"
#include "ModuleGUI.h"
#include "JSONManager.h"
#include "glew-2.1.0\include\GL\glew.h"
#include "SDL\include\SDL_opengl.h"
#include <gl/GL.h>
#include <gl/GLU.h>
#include "imgui.h"

#include "MeshImporter.h"

#pragma comment (lib, "engine/glew-2.1.0/libx86/glew32.lib")    /* link Glew lib     */
#pragma comment (lib, "glu32.lib")    /* link OpenGL Utility lib     */
#pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib   */

#define CHECKERS_HEIGHT 256
#define CHECKERS_WIDTH 256

ModuleRenderer3D::ModuleRenderer3D(bool start_enabled) : Module(start_enabled)
{
	SetName("renderer");
}

// Destructor
ModuleRenderer3D::~ModuleRenderer3D()
{}

// Called before render is available
bool ModuleRenderer3D::Awake(JSONDoc* config)
{
	EDITOR_LOG("Creating 3D Renderer context");
	bool ret = true;

	//Create context
	context = SDL_GL_CreateContext(App->window->window);
	if (context == NULL)
	{
		EDITOR_LOG("OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError());
		ret = false;
	}

	if (ret == true)
	{
		//Init Glew lib
		GLenum err = glewInit();
		if (err != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing Glew! %s\n", glewGetErrorString(err));
			ret = false;
		}
		else
			EDITOR_LOG("Using Glew %s.", glewGetString(GLEW_VERSION));

		//Use Vsync
		vsync = config->GetBool("renderer.vsync");
		if (vsync && SDL_GL_SetSwapInterval(1) < 0)
			EDITOR_LOG("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());

		//Initialize Projection Matrix
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();

		//Check for error
		GLenum error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		//Initialize Modelview Matrix
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		//Check for error
		error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
		glClearDepth(1.0f);

		//Initialize clear color
		glClearColor(0.f, 0.f, 0.f, 1.f);

		//Check for error
		error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		GLfloat LightModelAmbient[] = { 0.4f, 0.4f, 0.4f, 1.0f };
		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightModelAmbient);

		lights[0].ref = GL_LIGHT0;
		lights[0].ambient.Set(0.25f, 0.25f, 0.25f, 1.0f);
		lights[0].diffuse.Set(0.75f, 0.75f, 0.75f, 1.0f);
		lights[0].SetPos(0.0f, 0.0f, 2.5f);
		lights[0].Init();

		GLfloat MaterialAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialAmbient);

		GLfloat MaterialDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialDiffuse);

		glEnable(GL_DEPTH_TEST);
		depth_test = true;
		glEnable(GL_CULL_FACE);
		cull_face = true;
		lights[0].Active(true);
		glEnable(GL_LIGHTING);
		lighting = true;
		glEnable(GL_COLOR_MATERIAL);
		color_material = true;
		glEnable(GL_TEXTURE_2D);
		texture_2d = true;
	}

	// Projection matrix for
	OnResize(App->window->GetWidth(), App->window->GetHeight());

	return ret;
}

bool ModuleRenderer3D::Start()
{
	//create checker texture
	GLubyte checkImage[CHECKERS_HEIGHT][CHECKERS_WIDTH][4];
	for (int i = 0; i < CHECKERS_HEIGHT; i++) {
		for (int j = 0; j < CHECKERS_WIDTH; j++) {
			int c = ((((i & 0x8) == 0) ^ (((j & 0x8)) == 0))) * 255;
			checkImage[i][j][0] = (GLubyte)c;
			checkImage[i][j][1] = (GLubyte)c;
			checkImage[i][j][2] = (GLubyte)c;
			checkImage[i][j][3] = (GLubyte)255;
		}
	}
	checker_id = LoadTextureToVRAM(CHECKERS_WIDTH, CHECKERS_HEIGHT, &checkImage[0][0][0], GL_RGBA);

	return true;
}

// PreUpdate: clear buffer
update_status ModuleRenderer3D::PreUpdate(float dt)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf(App->camera->GetViewMatrix());

	// light 0 on cam pos
	lights[0].SetPos(App->camera->Position.x, App->camera->Position.y, App->camera->Position.z);

	for(uint i = 0; i < MAX_LIGHTS; ++i)
		lights[i].Render();

	return UPDATE_CONTINUE;
}

// PostUpdate present buffer to screen
update_status ModuleRenderer3D::PostUpdate(float dt)
{
	//Rendering pipeline
	App->scene_manager->DrawScenes();
	//Draw debug

	//Draw GUI
	bool light_state = lighting;
	if (lighting == true)		//Disable Lighting befor drawing gui
	{
		lighting = false;
		ToggleLightingState();
	}
	App->gui->RenderGUI();

	lighting = light_state;
	ToggleLightingState();

	SDL_GL_SwapWindow(App->window->window);
	return UPDATE_CONTINUE;
}

void ModuleRenderer3D::SaveConfig(JSONDoc * config)
{
	config->SetBool("renderer.vsync", vsync);
}

// Called before quitting
bool ModuleRenderer3D::CleanUp()
{
	EDITOR_LOG("Destroying 3D Renderer");

	SDL_GL_DeleteContext(context);

	return true;
}

void ModuleRenderer3D::OnResize(int width, int height)
{
	glViewport(0, 0, width, height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	ProjectionMatrix = perspective(60.0f, (float)width / (float)height, 0.125f, 512.0f);
	glLoadMatrixf(&ProjectionMatrix);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void ModuleRenderer3D::ConfigGUI()
{
	if (ImGui::CollapsingHeader("Renderer"))
	{
		//Get hardware capavilities
		ImGui::Text("Vendor: %s", glGetString(GL_VENDOR));
		ImGui::Text("Renderer: %s", glGetString(GL_RENDERER));
		ImGui::Text("OpenGL version supported %s", glGetString(GL_VERSION));
		ImGui::Text("GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

		ImGui::Separator();

		if (ImGui::Checkbox("VSYNC", &vsync))
			ToggleVSYNC();

		ImGui::Separator();

		ImGui::Text("Draw Modes:");

		if (ImGui::Checkbox("Wireframe Mode", &wireframe))
			PolygonModeWireframe();

		ImGui::SameLine();
		if (ImGui::Checkbox("Points Mode", &points))
			PolygonModePoints();

		if (ImGui::Checkbox("Fill Mode", &fill))
			PolygonModeFill();

		ImGui::Separator();

		ImGui::Text("OpenGL Capabilities:");

		if (ImGui::Checkbox("Depth Test", &depth_test))
			ToggleDepthTestState();

		ImGui::SameLine();
		if (ImGui::Checkbox("Cull Face", &cull_face))
			ToggleCullFaceState();

		if (ImGui::Checkbox("Lighting", &lighting))
			ToggleLightingState();

		ImGui::SameLine();
		if (ImGui::Checkbox("Texture 2D", &texture_2d))
			ToggleTexture2DState();

		if (ImGui::Checkbox("Color Material", &color_material))
			ToggleColorMaterialState();

	}
}

uint ModuleRenderer3D::GenBuffer() const
{
	uint ret = 0;
	glGenBuffers(1, (GLuint*)&ret);
	return ret;
}

void ModuleRenderer3D::BindArrayBuffer(uint id) const
{
	glBindBuffer(GL_ARRAY_BUFFER, id);
}

void ModuleRenderer3D::BindElementArrayBuffer(uint id) const
{
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
}

void ModuleRenderer3D::RenderElement(uint num_indices) const
{
	glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);
}

void ModuleRenderer3D::UnbindArraybuffer() const
{
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void ModuleRenderer3D::UnbindElementArrayBuffer() const
{
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void ModuleRenderer3D::EnableState(GLenum type) const
{
	glEnableClientState(type);
}

void ModuleRenderer3D::DisableState(GLenum type) const
{
	glDisableClientState(type);
}

void ModuleRenderer3D::SetVertexPointer() const
{
	glVertexPointer(3, GL_FLOAT, 0, NULL);
}

void ModuleRenderer3D::SetCheckerTexture() const
{
	glBindTexture(GL_TEXTURE_2D, checker_id);
}

void ModuleRenderer3D::BindTexure(uint id) const
{
	glBindTexture(GL_TEXTURE_2D, id);
}

void ModuleRenderer3D::UnbindTexture() const
{
	glBindTexture(GL_TEXTURE_2D, 0);
}

void ModuleRenderer3D::SetTexCoordPointer()
{
	glTexCoordPointer(3, GL_FLOAT, 0, NULL);
}

void ModuleRenderer3D::LoadArrayToVRAM(uint size, float * values, GLenum type) const
{
	glBufferData(GL_ARRAY_BUFFER, size, values, type);
}

void ModuleRenderer3D::LoadArrayToVRAM(uint size, uint * values, GLenum type) const
{
	glBufferData(GL_ARRAY_BUFFER, size, values, type);
}

uint ModuleRenderer3D::LoadTextureToVRAM(uint w, uint h, GLubyte * tex_data, GLint format) const
{
	uint buff_id = 0;

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glGenTextures(1, &buff_id);
	glBindTexture(GL_TEXTURE_2D, buff_id);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, tex_data);

	return buff_id;
}

GLenum ModuleRenderer3D::GetPolyMode() const
{
	return poly_mode;
}

void ModuleRenderer3D::PolygonModePoints()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
	wireframe = false;
	points = true;
	fill = false;
	poly_mode = GL_POINT;
}

void ModuleRenderer3D::PolygonModeWireframe()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	wireframe = true;
	points = false;
	fill = false;
	poly_mode = GL_LINE;
}

void ModuleRenderer3D::PolygonModeFill()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	wireframe = false;
	points = false;
	fill = true;
	poly_mode = GL_FILL;
}

void ModuleRenderer3D::ToggleDepthTestState()
{
	if (depth_test)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);
}

void ModuleRenderer3D::ToggleCullFaceState()
{
	if (cull_face)
		glEnable(GL_CULL_FACE);
	else
		glDisable(GL_CULL_FACE);
}

void ModuleRenderer3D::ToggleLightingState()
{
	if (lighting)
		glEnable(GL_LIGHTING);
	else
		glDisable(GL_LIGHTING);
}

void ModuleRenderer3D::ToggleTexture2DState()
{
	if (texture_2d)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);
}

void ModuleRenderer3D::ToggleColorMaterialState()
{
	if (color_material)
		glEnable(GL_COLOR_MATERIAL);
	else
		glDisable(GL_COLOR_MATERIAL);
}

void ModuleRenderer3D::ToggleVSYNC()
{
	if (vsync)
	{
		if (SDL_GL_SetSwapInterval(1) == 0)
			EDITOR_LOG("VSYNC active");
	}
	else
	{
		if (SDL_GL_SetSwapInterval(0) == 0)
			EDITOR_LOG("VSYNC disabled");
	}
}<commit_msg>gl include<commit_after>#include "Globals.h"
#include "Application.h"
#include "ModuleRenderer3D.h"
#include "ModuleCamera3D.h"
#include "ModuleWindow.h"
#include "SceneManager.h"
#include "ModuleGUI.h"
#include "JSONManager.h"
#include "GLInclude.h"
#include "imgui.h"

#include "MeshImporter.h"

#pragma comment (lib, "engine/glew-2.1.0/libx86/glew32.lib")    /* link Glew lib     */
#pragma comment (lib, "glu32.lib")    /* link OpenGL Utility lib     */
#pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib   */

#define CHECKERS_HEIGHT 256
#define CHECKERS_WIDTH 256

ModuleRenderer3D::ModuleRenderer3D(bool start_enabled) : Module(start_enabled)
{
	SetName("renderer");
}

// Destructor
ModuleRenderer3D::~ModuleRenderer3D()
{}

// Called before render is available
bool ModuleRenderer3D::Awake(JSONDoc* config)
{
	EDITOR_LOG("Creating 3D Renderer context");
	bool ret = true;

	//Create context
	context = SDL_GL_CreateContext(App->window->window);
	if (context == NULL)
	{
		EDITOR_LOG("OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError());
		ret = false;
	}

	if (ret == true)
	{
		//Init Glew lib
		GLenum err = glewInit();
		if (err != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing Glew! %s\n", glewGetErrorString(err));
			ret = false;
		}
		else
			EDITOR_LOG("Using Glew %s.", glewGetString(GLEW_VERSION));

		//Use Vsync
		vsync = config->GetBool("renderer.vsync");
		if (vsync && SDL_GL_SetSwapInterval(1) < 0)
			EDITOR_LOG("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());

		//Initialize Projection Matrix
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();

		//Check for error
		GLenum error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		//Initialize Modelview Matrix
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		//Check for error
		error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
		glClearDepth(1.0f);

		//Initialize clear color
		glClearColor(0.f, 0.f, 0.f, 1.f);

		//Check for error
		error = glGetError();
		if (error != GL_NO_ERROR)
		{
			EDITOR_LOG("Error initializing OpenGL! %s\n", gluErrorString(error));
			ret = false;
		}

		GLfloat LightModelAmbient[] = { 0.4f, 0.4f, 0.4f, 1.0f };
		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightModelAmbient);

		lights[0].ref = GL_LIGHT0;
		lights[0].ambient.Set(0.25f, 0.25f, 0.25f, 1.0f);
		lights[0].diffuse.Set(0.75f, 0.75f, 0.75f, 1.0f);
		lights[0].SetPos(0.0f, 0.0f, 2.5f);
		lights[0].Init();

		GLfloat MaterialAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialAmbient);

		GLfloat MaterialDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialDiffuse);

		glEnable(GL_DEPTH_TEST);
		depth_test = true;
		glEnable(GL_CULL_FACE);
		cull_face = true;
		lights[0].Active(true);
		glEnable(GL_LIGHTING);
		lighting = true;
		glEnable(GL_COLOR_MATERIAL);
		color_material = true;
		glEnable(GL_TEXTURE_2D);
		texture_2d = true;
	}

	// Projection matrix for
	OnResize(App->window->GetWidth(), App->window->GetHeight());

	return ret;
}

bool ModuleRenderer3D::Start()
{
	//create checker texture
	GLubyte checkImage[CHECKERS_HEIGHT][CHECKERS_WIDTH][4];
	for (int i = 0; i < CHECKERS_HEIGHT; i++) {
		for (int j = 0; j < CHECKERS_WIDTH; j++) {
			int c = ((((i & 0x8) == 0) ^ (((j & 0x8)) == 0))) * 255;
			checkImage[i][j][0] = (GLubyte)c;
			checkImage[i][j][1] = (GLubyte)c;
			checkImage[i][j][2] = (GLubyte)c;
			checkImage[i][j][3] = (GLubyte)255;
		}
	}
	checker_id = LoadTextureToVRAM(CHECKERS_WIDTH, CHECKERS_HEIGHT, &checkImage[0][0][0], GL_RGBA);

	return true;
}

// PreUpdate: clear buffer
update_status ModuleRenderer3D::PreUpdate(float dt)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf(App->camera->GetViewMatrix());

	// light 0 on cam pos
	lights[0].SetPos(App->camera->Position.x, App->camera->Position.y, App->camera->Position.z);

	for(uint i = 0; i < MAX_LIGHTS; ++i)
		lights[i].Render();

	return UPDATE_CONTINUE;
}

// PostUpdate present buffer to screen
update_status ModuleRenderer3D::PostUpdate(float dt)
{
	//Rendering pipeline
	App->scene_manager->DrawScenes();
	//Draw debug

	//Draw GUI
	bool light_state = lighting;
	if (lighting == true)		//Disable Lighting befor drawing gui
	{
		lighting = false;
		ToggleLightingState();
	}
	App->gui->RenderGUI();

	lighting = light_state;
	ToggleLightingState();

	SDL_GL_SwapWindow(App->window->window);
	return UPDATE_CONTINUE;
}

void ModuleRenderer3D::SaveConfig(JSONDoc * config)
{
	config->SetBool("renderer.vsync", vsync);
}

// Called before quitting
bool ModuleRenderer3D::CleanUp()
{
	EDITOR_LOG("Destroying 3D Renderer");

	SDL_GL_DeleteContext(context);

	return true;
}

void ModuleRenderer3D::OnResize(int width, int height)
{
	glViewport(0, 0, width, height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	ProjectionMatrix = perspective(60.0f, (float)width / (float)height, 0.125f, 512.0f);
	glLoadMatrixf(&ProjectionMatrix);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void ModuleRenderer3D::ConfigGUI()
{
	if (ImGui::CollapsingHeader("Renderer"))
	{
		//Get hardware capavilities
		ImGui::Text("Vendor: %s", glGetString(GL_VENDOR));
		ImGui::Text("Renderer: %s", glGetString(GL_RENDERER));
		ImGui::Text("OpenGL version supported %s", glGetString(GL_VERSION));
		ImGui::Text("GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

		ImGui::Separator();

		if (ImGui::Checkbox("VSYNC", &vsync))
			ToggleVSYNC();

		ImGui::Separator();

		ImGui::Text("Draw Modes:");

		if (ImGui::Checkbox("Wireframe Mode", &wireframe))
			PolygonModeWireframe();

		ImGui::SameLine();
		if (ImGui::Checkbox("Points Mode", &points))
			PolygonModePoints();

		if (ImGui::Checkbox("Fill Mode", &fill))
			PolygonModeFill();

		ImGui::Separator();

		ImGui::Text("OpenGL Capabilities:");

		if (ImGui::Checkbox("Depth Test", &depth_test))
			ToggleDepthTestState();

		ImGui::SameLine();
		if (ImGui::Checkbox("Cull Face", &cull_face))
			ToggleCullFaceState();

		if (ImGui::Checkbox("Lighting", &lighting))
			ToggleLightingState();

		ImGui::SameLine();
		if (ImGui::Checkbox("Texture 2D", &texture_2d))
			ToggleTexture2DState();

		if (ImGui::Checkbox("Color Material", &color_material))
			ToggleColorMaterialState();

	}
}

uint ModuleRenderer3D::GenBuffer() const
{
	uint ret = 0;
	glGenBuffers(1, (GLuint*)&ret);
	return ret;
}

void ModuleRenderer3D::BindArrayBuffer(uint id) const
{
	glBindBuffer(GL_ARRAY_BUFFER, id);
}

void ModuleRenderer3D::BindElementArrayBuffer(uint id) const
{
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
}

void ModuleRenderer3D::RenderElement(uint num_indices) const
{
	glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);
}

void ModuleRenderer3D::UnbindArraybuffer() const
{
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void ModuleRenderer3D::UnbindElementArrayBuffer() const
{
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void ModuleRenderer3D::EnableState(GLenum type) const
{
	glEnableClientState(type);
}

void ModuleRenderer3D::DisableState(GLenum type) const
{
	glDisableClientState(type);
}

void ModuleRenderer3D::SetVertexPointer() const
{
	glVertexPointer(3, GL_FLOAT, 0, NULL);
}

void ModuleRenderer3D::SetCheckerTexture() const
{
	glBindTexture(GL_TEXTURE_2D, checker_id);
}

void ModuleRenderer3D::BindTexure(uint id) const
{
	glBindTexture(GL_TEXTURE_2D, id);
}

void ModuleRenderer3D::UnbindTexture() const
{
	glBindTexture(GL_TEXTURE_2D, 0);
}

void ModuleRenderer3D::SetTexCoordPointer()
{
	glTexCoordPointer(3, GL_FLOAT, 0, NULL);
}

void ModuleRenderer3D::LoadArrayToVRAM(uint size, float * values, GLenum type) const
{
	glBufferData(GL_ARRAY_BUFFER, size, values, type);
}

void ModuleRenderer3D::LoadArrayToVRAM(uint size, uint * values, GLenum type) const
{
	glBufferData(GL_ARRAY_BUFFER, size, values, type);
}

uint ModuleRenderer3D::LoadTextureToVRAM(uint w, uint h, GLubyte * tex_data, GLint format) const
{
	uint buff_id = 0;

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glGenTextures(1, &buff_id);
	glBindTexture(GL_TEXTURE_2D, buff_id);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, tex_data);

	return buff_id;
}

GLenum ModuleRenderer3D::GetPolyMode() const
{
	return poly_mode;
}

void ModuleRenderer3D::PolygonModePoints()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
	wireframe = false;
	points = true;
	fill = false;
	poly_mode = GL_POINT;
}

void ModuleRenderer3D::PolygonModeWireframe()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	wireframe = true;
	points = false;
	fill = false;
	poly_mode = GL_LINE;
}

void ModuleRenderer3D::PolygonModeFill()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	wireframe = false;
	points = false;
	fill = true;
	poly_mode = GL_FILL;
}

void ModuleRenderer3D::ToggleDepthTestState()
{
	if (depth_test)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);
}

void ModuleRenderer3D::ToggleCullFaceState()
{
	if (cull_face)
		glEnable(GL_CULL_FACE);
	else
		glDisable(GL_CULL_FACE);
}

void ModuleRenderer3D::ToggleLightingState()
{
	if (lighting)
		glEnable(GL_LIGHTING);
	else
		glDisable(GL_LIGHTING);
}

void ModuleRenderer3D::ToggleTexture2DState()
{
	if (texture_2d)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);
}

void ModuleRenderer3D::ToggleColorMaterialState()
{
	if (color_material)
		glEnable(GL_COLOR_MATERIAL);
	else
		glDisable(GL_COLOR_MATERIAL);
}

void ModuleRenderer3D::ToggleVSYNC()
{
	if (vsync)
	{
		if (SDL_GL_SetSwapInterval(1) == 0)
			EDITOR_LOG("VSYNC active");
	}
	else
	{
		if (SDL_GL_SetSwapInterval(0) == 0)
			EDITOR_LOG("VSYNC disabled");
	}
}<|endoftext|>


<commit_before>#include <iostream>
#include <dartpy/BodyNode.h>

// moveTo (BodyNode *_newParent, const typename JointType::Properties &_joint=typename JointType::Properties())

namespace {

template <class T>
boost::python::object get_pytype()
{
  const boost::python::converter::registration* registration
    = boost::python::converter::registry::query(typeid(T));
  if (!registration)
  {
    throw std::runtime_error(
      "Type is not known to Boost.Python.");
  }

  PyTypeObject* class_object = registration->get_class_object();
  return boost::python::object(
    boost::python::handle<>(
      boost::python::borrowed(class_object)));
}

template <template <class> class Factory, class Function, class... Args>
struct create_registry;

template <template <class> class Factory, class Function>
struct create_registry<Factory, Function>
{
  static void execute(std::map<boost::python::object, Function>& registry)
  {
    // do nothing
  }
};

template <template <class> class Factory, class Function, class Arg, class... Args>
struct create_registry<Factory, Function, Arg, Args...>
{
  static void execute(std::map<boost::python::object, Function>& registry)
  {
    // TODO: Add a mechanism for injecting a function here.
    registry[get_pytype<Arg>()] = &Factory<Arg>::execute;
    create_registry<Factory, Function, Args...>::execute(registry);
  }
};

template <class JointType>
struct BodyNode_moveTo2_factory
{
  static dart::dynamics::Joint* execute(
    dart::dynamics::BodyNode* _bodyNode,
    dart::dynamics::BodyNode* _newParent,
    boost::python::object _jointPropertiesPython)
  {
    typename JointType::Properties jointProperties;

    if (!_jointPropertiesPython.is_none())
    {
      jointProperties = boost::python::extract<typename JointType::Properties>(
        _jointPropertiesPython);
    }

    return _bodyNode->moveTo<JointType>(_newParent);
  }
};

template <template <class> class FactoryTemplate, class ReturnType>
struct Multiplexer
{
  template <class... Args>
  static ReturnType execute(boost::python::object _jointType, Args... _args)
  {
    using namespace dart::dynamics;

    std::map<boost::python::object, std::function<ReturnType (Args...)> > registry;
    create_registry<FactoryTemplate, std::function<ReturnType (Args...)>,
        FreeJoint, PrismaticJoint, RevoluteJoint, ScrewJoint, WeldJoint,
        UniversalJoint, BallJoint, EulerJoint, PlanarJoint, TranslationalJoint
      >::execute(registry);

    const auto it = registry.find(_jointType);
    if (it == std::end(registry))
    {
      std::cerr << "Unsupported type for template argument." << std::endl;
      return ReturnType();
    }

    return it->second(_args...);
  }
};

} // namespace

namespace dart {
namespace python {

dart::dynamics::Joint* BodyNode_moveTo2(
  dart::dynamics::BodyNode* _bodyNode,
  boost::python::object _jointType,
  dart::dynamics::BodyNode* _newParent,
  boost::python::object _jointProperties)
{
  return Multiplexer<BodyNode_moveTo2_factory, dart::dynamics::Joint*>::execute(
    _jointType, _bodyNode, _newParent, _jointProperties);
}

} // namespace python {
} // namespace dart {
<commit_msg>Simplified typedefs.<commit_after>#include <iostream>
#include <dartpy/BodyNode.h>

// moveTo (BodyNode *_newParent, const typename JointType::Properties &_joint=typename JointType::Properties())

namespace {

template <class T>
boost::python::object get_pytype()
{
  const boost::python::converter::registration* registration
    = boost::python::converter::registry::query(typeid(T));
  if (!registration)
  {
    throw std::runtime_error(
      "Type is not known to Boost.Python.");
  }

  PyTypeObject* class_object = registration->get_class_object();
  return boost::python::object(
    boost::python::handle<>(
      boost::python::borrowed(class_object)));
}

template <class Function>
using Registry = std::map<boost::python::object, std::function<Function>>;

template <template <class> class Factory, class Function, class... Args>
struct create_registry;

template <template <class> class Factory, class Function>
struct create_registry<Factory, Function>
{
  static void execute(Registry<Function>& registry)
  {
    // do nothing
  }
};

template <template <class> class Factory, class Function, class Arg, class... Args>
struct create_registry<Factory, Function, Arg, Args...>
{
  static void execute(Registry<Function>& registry)
  {
    // TODO: Add a mechanism for injecting a function here.
    registry[get_pytype<Arg>()] = &Factory<Arg>::execute;
    create_registry<Factory, Function, Args...>::execute(registry);
  }
};

template <class JointType>
struct BodyNode_moveTo2_factory
{
  static dart::dynamics::Joint* execute(
    dart::dynamics::BodyNode* _bodyNode,
    dart::dynamics::BodyNode* _newParent,
    boost::python::object _jointPropertiesPython)
  {
    typename JointType::Properties jointProperties;

    if (!_jointPropertiesPython.is_none())
    {
      jointProperties = boost::python::extract<typename JointType::Properties>(
        _jointPropertiesPython);
    }

    return _bodyNode->moveTo<JointType>(_newParent);
  }
};

template <template <class> class Factory, class ReturnType>
struct Multiplexer
{
  template <class... Args>
  static ReturnType execute(boost::python::object _jointType, Args... _args)
  {
    using namespace dart::dynamics;
    using Function = ReturnType (Args...);

    Registry<Function> registry;
    create_registry<Factory, Function,
        FreeJoint, PrismaticJoint, RevoluteJoint, ScrewJoint, WeldJoint,
        UniversalJoint, BallJoint, EulerJoint, PlanarJoint, TranslationalJoint
      >::execute(registry);

    const auto it = registry.find(_jointType);
    if (it == std::end(registry))
    {
      std::cerr << "Unsupported type for template argument." << std::endl;
      return ReturnType();
    }

    return it->second(_args...);
  }
};

} // namespace

namespace dart {
namespace python {

dart::dynamics::Joint* BodyNode_moveTo2(
  dart::dynamics::BodyNode* _bodyNode,
  boost::python::object _jointType,
  dart::dynamics::BodyNode* _newParent,
  boost::python::object _jointProperties)
{
  return Multiplexer<BodyNode_moveTo2_factory, dart::dynamics::Joint*>::execute(
    _jointType, _bodyNode, _newParent, _jointProperties);
}

} // namespace python {
} // namespace dart {
<|endoftext|>