<commit_before>#include "KakuroField.h"
#include "KakuroProblem.h"
#include "../common/MiniVector.hpp"
#include <cstdio>

namespace Penciloid
{
KakuroField::KakuroField() : cells(nullptr), height(0), width(0), field_status(SolverStatus::NORMAL), num_undecided_cells(0)
{
}

KakuroField::~KakuroField()
{
	if (cells) delete[] cells;
}

void KakuroField::Init(int height_t, int width_t)
{
	height = height_t;
	width = width_t;

	if (cells) delete[] cells;

	cells = new KakuroCell[height * width * 2];
	field_status = SolverStatus::NORMAL;
	num_undecided_cells = 0;
}

void KakuroField::Init(KakuroProblem &prob)
{
	Init(prob.GetHeight(), prob.GetWidth());

	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			if (prob.IsNumberCell(y, x)) SetNumberCell(y, x);

			if (prob.IsHintAvailableVertical(y, x)) {
				int y_end = y + 1;
				for (; y_end < height && prob.IsNumberCell(y_end, x); ++y_end);

				for (int y2 = y + 1; y2 < y_end; ++y2) {
					cells[CellId(y2, x)].group_num_cells = y_end - (y + 1);
					cells[CellId(y2, x)].group_sum = prob.GetHintVertical(y, x);
					if (y2 == y_end - 1) cells[CellId(y2, x)].group_next_cell = CellId(y + 1, x);
					else cells[CellId(y2, x)].group_next_cell = CellId(y2 + 1, x);
				}
			}

			if (prob.IsHintAvailableHorizontal(y, x)) {
				int x_end = x + 1;
				for (; x_end < width && prob.IsNumberCell(y, x_end); ++x_end);

				for (int x2 = x + 1; x2 < x_end; ++x2) {
					cells[CellId(y, x2) | 1].group_num_cells = x_end - (x + 1);
					cells[CellId(y, x2) | 1].group_sum = prob.GetHintHorizontal(y, x);
					if (x2 == x_end - 1) cells[CellId(y, x2) | 1].group_next_cell = CellId(y, x + 1) | 1;
					else cells[CellId(y, x2) | 1].group_next_cell = CellId(y, x2 + 1) | 1;
				}
			}
		}
	}
}

int KakuroField::CheckAll()
{
	for (int i = 0; i < height * width * 2; ++i) {
		if (cells[i].group_next_cell != -1) CheckGroup(i);
	}

	return GetStatus();
}

void KakuroField::SetNumberCell(int y, int x)
{
	int id = CellId(y, x);

	if (cells[id].cell_value == CELL_HINT) {
		++num_undecided_cells;
		cells[id].cell_value = cells[id | 1].cell_value = CELL_UNDECIDED;
		cells[id].cell_candidate = cells[id | 1].cell_candidate = (2 << CELL_MAX_VALUE) - 2;
	}
}

int KakuroField::CheckGroup(int id)
{
	if (Next(id) == -1) return GetStatus();

	MiniVector<int, CELL_MAX_VALUE> group_cells;

	for (int current = id;;) {
		group_cells.push_back(current);
		if ((current = Next(current)) == id) break;
	}

	// TODO: desperately naive algorithm
	int already_used_values = 0;

	for (int current : group_cells) {
		if (cells[current].cell_value >= 1) already_used_values |= 1 << cells[current].cell_value;
	}

	int reserved_candidate = 0;
	for (int p : group_cells) {
		int cand = cells[p].cell_candidate;
		if (!IsUniqueCandidate(cand) && IsUniqueCandidate(cand ^ (cand & -cand))) {
			for (int q : group_cells) {
				if (p != q && cand == cells[q].cell_candidate) {
					reserved_candidate |= cand;
					for (int r : group_cells) {
						if (p != r && q != r) {
							UpdateCandidate(r, ~cand);
						}
					}
				}
			}
		}
	}

	int possible_candidate = 0, imperative_candidate = (2 << CELL_MAX_VALUE) - 2;

	for (int bits = 2; bits < (2 << CELL_MAX_VALUE); bits += 2) {
		int sum = 0, num = 0;

		for (int i = 1; i <= CELL_MAX_VALUE; ++i) {
			if (bits & (1 << i)) {
				sum += i;
				++num;
			}
		}

		if ((bits & reserved_candidate) != reserved_candidate || (bits & already_used_values) != already_used_values || sum != cells[id].group_sum || num != cells[id].group_num_cells) continue;

		for (int current : group_cells) {
			if ((cells[current].cell_candidate & bits) == 0) goto nex;
		}

		possible_candidate |= bits ^ already_used_values;
		imperative_candidate &= bits ^ already_used_values;

	nex:
		continue;
	}

	for (int current : group_cells) {
		if (cells[current].cell_value == CELL_UNDECIDED) UpdateCandidate(current, possible_candidate);
	}

	for (int i = 1; i <= CELL_MAX_VALUE; ++i) if (imperative_candidate & (1 << i)) {
		int candidate_loc = -1;

		for (int current : group_cells) {
			if (cells[current].cell_candidate & (1 << i)) {
				if (candidate_loc == -1) candidate_loc = current;
				else {
					candidate_loc = -2;
					break;
				}
			}
		}

		if (candidate_loc == -1) return UpdateStatus(SolverStatus::INCONSISTENT);
		else if (candidate_loc != -2) UpdateCandidate(candidate_loc, 1 << i);
	}

	return GetStatus();
}

int KakuroField::UpdateCandidate(int id, int new_candidate)
{
	id &= ~1;
	new_candidate &= cells[id].cell_candidate;

	if (new_candidate == 0) {
		return UpdateStatus(SolverStatus::INCONSISTENT);
	} if (new_candidate == cells[id].cell_candidate) return UpdateStatus(0);

	cells[id].cell_candidate = cells[id | 1].cell_candidate = new_candidate;

	if (IsUniqueCandidate(new_candidate)) {
		int cand_value = 0;
		for (int i = 1; i <= CELL_MAX_VALUE; ++i) {
			if (new_candidate == 1 << i) {
				cand_value = i;
				break;
			}
		}

		cells[id].cell_value = cells[id | 1].cell_value = cand_value;
		if (--num_undecided_cells == 0) UpdateStatus(SolverStatus::SUCCESS);

		// TODO: purge determined cells?
	}

	CheckGroup(id);
	CheckGroup(id | 1);

	return GetStatus();
}

void KakuroField::Debug()
{
	for (int i_ = 0; i_ <= 2 * height; ++i_) {
		if (i_ % 2 == 0) {
			fprintf(stderr, "+");
			for (int j = 0; j < width; ++j) fprintf(stderr, "---+");
			fprintf(stderr, "\n");
			continue;
		}

		int i = i_ / 2;
		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) fprintf(stderr, "   |");
			else {
				if (j == width - 1 || !IsNumberCell(i, j + 1)) fprintf(stderr, "\\  |");
				else fprintf(stderr, "\\%2d|", cells[CellId(i, j + 1) | 1].group_sum);
			}
		}
		fprintf(stderr, "\n");

		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) {
				if (GetCellValue(i, j) == CELL_UNDECIDED) fprintf(stderr, "   |");
				else fprintf(stderr, " %d |", GetCellValue(i, j));
			} else {
				fprintf(stderr, " \\ |");
			}
		}
		fprintf(stderr, "\n");

		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) fprintf(stderr, "   |");
			else {
				if (i == height - 1 || !IsNumberCell(i + 1, j)) fprintf(stderr, "  \\|");
				else fprintf(stderr, "%2d\\|", cells[CellId(i + 1, j)].group_sum);
			}
		}
		fprintf(stderr, "\n");
	}
	fflush(stderr);
}

}

<commit_msg>Enhance KakuroField<commit_after>#include "KakuroField.h"
#include "KakuroProblem.h"
#include "../common/MiniVector.hpp"
#include <cstdio>

namespace Penciloid
{
KakuroField::KakuroField() : cells(nullptr), height(0), width(0), field_status(SolverStatus::NORMAL), num_undecided_cells(0)
{
}

KakuroField::~KakuroField()
{
	if (cells) delete[] cells;
}

void KakuroField::Init(int height_t, int width_t)
{
	height = height_t;
	width = width_t;

	if (cells) delete[] cells;

	cells = new KakuroCell[height * width * 2];
	field_status = SolverStatus::NORMAL;
	num_undecided_cells = 0;
}

void KakuroField::Init(KakuroProblem &prob)
{
	Init(prob.GetHeight(), prob.GetWidth());

	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			if (prob.IsNumberCell(y, x)) SetNumberCell(y, x);

			if (prob.IsHintAvailableVertical(y, x)) {
				int y_end = y + 1;
				for (; y_end < height && prob.IsNumberCell(y_end, x); ++y_end);

				for (int y2 = y + 1; y2 < y_end; ++y2) {
					cells[CellId(y2, x)].group_num_cells = y_end - (y + 1);
					cells[CellId(y2, x)].group_sum = prob.GetHintVertical(y, x);
					if (y2 == y_end - 1) cells[CellId(y2, x)].group_next_cell = CellId(y + 1, x);
					else cells[CellId(y2, x)].group_next_cell = CellId(y2 + 1, x);
				}
			}

			if (prob.IsHintAvailableHorizontal(y, x)) {
				int x_end = x + 1;
				for (; x_end < width && prob.IsNumberCell(y, x_end); ++x_end);

				for (int x2 = x + 1; x2 < x_end; ++x2) {
					cells[CellId(y, x2) | 1].group_num_cells = x_end - (x + 1);
					cells[CellId(y, x2) | 1].group_sum = prob.GetHintHorizontal(y, x);
					if (x2 == x_end - 1) cells[CellId(y, x2) | 1].group_next_cell = CellId(y, x + 1) | 1;
					else cells[CellId(y, x2) | 1].group_next_cell = CellId(y, x2 + 1) | 1;
				}
			}
		}
	}
}

int KakuroField::CheckAll()
{
	for (int i = 0; i < height * width * 2; ++i) {
		if (cells[i].group_next_cell != -1) CheckGroup(i);
	}

	return GetStatus();
}

void KakuroField::SetNumberCell(int y, int x)
{
	int id = CellId(y, x);

	if (cells[id].cell_value == CELL_HINT) {
		++num_undecided_cells;
		cells[id].cell_value = cells[id | 1].cell_value = CELL_UNDECIDED;
		cells[id].cell_candidate = cells[id | 1].cell_candidate = (2 << CELL_MAX_VALUE) - 2;
	}
}

int KakuroField::CheckGroup(int id)
{
	if (Next(id) == -1) return GetStatus();

	MiniVector<int, CELL_MAX_VALUE> group_cells;

	for (int current = id;;) {
		group_cells.push_back(current);
		if ((current = Next(current)) == id) break;
	}

	// TODO: desperately naive algorithm
	int already_used_values = 0;

	for (int current : group_cells) {
		if (cells[current].cell_value >= 1) already_used_values |= 1 << cells[current].cell_value;
	}

	int reserved_candidate = 0;
	for (int p : group_cells) {
		int cand = cells[p].cell_candidate;
		if (!IsUniqueCandidate(cand) && IsUniqueCandidate(cand ^ (cand & -cand))) {
			for (int q : group_cells) {
				if (p != q && cand == cells[q].cell_candidate) {
					reserved_candidate |= cand;
					for (int r : group_cells) {
						if (p != r && q != r) {
							UpdateCandidate(r, ~cand);
						}
					}
				}
			}
		}
	}

	int possible_candidate = 0, imperative_candidate = (2 << CELL_MAX_VALUE) - 2;
	MiniVector<int, CELL_MAX_VALUE> new_candidates;
	for (int i : group_cells) new_candidates.push_back(0);

	for (int bits = 2; bits < (2 << CELL_MAX_VALUE); bits += 2) {
		int sum = 0, num = 0;

		for (int i = 1; i <= CELL_MAX_VALUE; ++i) {
			if (bits & (1 << i)) {
				sum += i;
				++num;
			}
		}

		if ((bits & reserved_candidate) != reserved_candidate || (bits & already_used_values) != already_used_values || sum != cells[id].group_sum || num != cells[id].group_num_cells) continue;

		for (int current : group_cells) {
			if ((cells[current].cell_candidate & bits) == 0) goto nex;
		}

		possible_candidate |= bits ^ already_used_values;
		imperative_candidate &= bits ^ already_used_values;

		int exclusive = 0, exclusive_remaining = (1 << group_cells.size()) - 1;
		int current_candidate = bits;
		bool updated;
		do {
			updated = false;

			for (int i = 0; i < group_cells.size(); ++i) if (exclusive_remaining & (1 << i)) {
				if (IsUniqueCandidate(current_candidate & cells[group_cells[i]].cell_candidate)) {
					exclusive_remaining ^= 1 << i;
					new_candidates[i] |= current_candidate & cells[group_cells[i]].cell_candidate;
					current_candidate &= ~cells[group_cells[i]].cell_candidate;
					updated = true;
				}
			}

		} while (updated);

		for (int i = 0; i < group_cells.size(); ++i) if (exclusive_remaining & (1 << i)) {
			new_candidates[i] |= current_candidate;
		}
	nex:
		continue;
	}

	for (int i = 0; i < group_cells.size(); ++i) {
		UpdateCandidate(group_cells[i], new_candidates[i]);
	}

	for (int current : group_cells) {
		if (cells[current].cell_value == CELL_UNDECIDED) UpdateCandidate(current, possible_candidate);
	}

	for (int i = 1; i <= CELL_MAX_VALUE; ++i) if (imperative_candidate & (1 << i)) {
		int candidate_loc = -1;

		for (int current : group_cells) {
			if (cells[current].cell_candidate & (1 << i)) {
				if (candidate_loc == -1) candidate_loc = current;
				else {
					candidate_loc = -2;
					break;
				}
			}
		}

		if (candidate_loc == -1) return UpdateStatus(SolverStatus::INCONSISTENT);
		else if (candidate_loc != -2) UpdateCandidate(candidate_loc, 1 << i);
	}

	return GetStatus();
}

int KakuroField::UpdateCandidate(int id, int new_candidate)
{
	id &= ~1;
	new_candidate &= cells[id].cell_candidate;

	if (new_candidate == 0) {
		return UpdateStatus(SolverStatus::INCONSISTENT);
	} if (new_candidate == cells[id].cell_candidate) return UpdateStatus(0);

	cells[id].cell_candidate = cells[id | 1].cell_candidate = new_candidate;

	if (IsUniqueCandidate(new_candidate)) {
		int cand_value = 0;
		for (int i = 1; i <= CELL_MAX_VALUE; ++i) {
			if (new_candidate == 1 << i) {
				cand_value = i;
				break;
			}
		}

		cells[id].cell_value = cells[id | 1].cell_value = cand_value;
		if (--num_undecided_cells == 0) UpdateStatus(SolverStatus::SUCCESS);

		// TODO: purge determined cells?
	}

	CheckGroup(id);
	CheckGroup(id | 1);

	return GetStatus();
}

void KakuroField::Debug()
{
	for (int i_ = 0; i_ <= 2 * height; ++i_) {
		if (i_ % 2 == 0) {
			fprintf(stderr, "+");
			for (int j = 0; j < width; ++j) fprintf(stderr, "---+");
			fprintf(stderr, "\n");
			continue;
		}

		int i = i_ / 2;
		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) fprintf(stderr, "   |");
			else {
				if (j == width - 1 || !IsNumberCell(i, j + 1)) fprintf(stderr, "\\  |");
				else fprintf(stderr, "\\%2d|", cells[CellId(i, j + 1) | 1].group_sum);
			}
		}
		fprintf(stderr, "\n");

		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) {
				if (GetCellValue(i, j) == CELL_UNDECIDED) fprintf(stderr, "   |");
				else fprintf(stderr, " %d |", GetCellValue(i, j));
			} else {
				fprintf(stderr, " \\ |");
			}
		}
		fprintf(stderr, "\n");

		fprintf(stderr, "|");
		for (int j = 0; j < width; ++j) {
			if (IsNumberCell(i, j)) fprintf(stderr, "   |");
			else {
				if (i == height - 1 || !IsNumberCell(i + 1, j)) fprintf(stderr, "  \\|");
				else fprintf(stderr, "%2d\\|", cells[CellId(i + 1, j)].group_sum);
			}
		}
		fprintf(stderr, "\n");
	}
	fflush(stderr);
}

}

<|endoftext|>


<commit_before>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                       Paraver Main Computing Library                      *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

#include <stdexcept>
#include "ktraceeditsequence.h"
#include "traceeditstates.h"
#include "ktraceeditactions.h"

using std::invalid_argument;

class TextOutput;

KTraceEditSequence::KTraceEditSequence( const KernelConnection *whichKernel ) :
  TraceEditSequence( whichKernel )
{
}

KTraceEditSequence::~KTraceEditSequence()
{
  for( map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator it = activeStates.begin();
       it != activeStates.end(); ++it )
    delete it->second;

  for( vector<TraceEditAction *>::iterator it = sequenceActions.begin();
       it != sequenceActions.end(); ++it )
    delete *it;
}

const KernelConnection *KTraceEditSequence::getKernelConnection() const
{
  return myKernel;
}

TraceEditState *KTraceEditSequence::createState( TraceEditSequence::TSequenceStates whichState )
{
  switch( whichState )
  {
    case testState:
      return new TestState( this );
      break;

    case traceOptionsState:
      return new TraceOptionsState( this );
      break;

    case csvWindowState:
      return new CSVWindowState( this );
      break;

    case csvFileNameState:
      return new CSVFileNameState( this );
      break;

    case csvOutputState:
      return new CSVOutputState( this );
      break;

    case outputDirSuffixState:
      return new OutputDirSuffixState( this );
      break;

    case outputTraceFileNameState:
      return new OutputTraceFileNameState( this );
      break;

    case maxTraceTimeState:
      return new MaxTraceTimeState( this );
      break;

    case shiftTimesState:
      return new ShiftTimesState( this );
      break;

    case eofParsedState:
      return new EOFParsedState( this );
      break;

    case shiftLevelState:
      return new ShiftLevelState( this );
      break;

    case onEventCutterState:
      return new OnEventCutter( this );
      break;

    case pcfMergerReferenceState:
      return new PCFMergerReferenceState( this );
      break;

    case copyAdditionalFilesState:
      return new CopyAdditionalFilesState( this );
      break;

    case eventTranslationTableState:
      return new EventTranslationTableState( this );
      break;

    case onlyFilterState:
      return new OnlyFilterState( this );
      break;

    default:
      return NULL;
      break;
  }

  return NULL;
}

void KTraceEditSequence::setCurrentTrace( KTrace *whichTrace )
{
  currentTrace = whichTrace;
}

KTrace *KTraceEditSequence::getCurrentTrace()
{
  return currentTrace;
}

bool KTraceEditSequence::addState( TraceEditSequence::TSequenceStates whichState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;
  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return false;

  TraceEditState *newState = createState( whichState );
  if( newState == NULL )
    throw invalid_argument( "Invalid state for TraceEditSequence" );

  activeStates[ whichState ] = newState;
  return true;
}

bool KTraceEditSequence::addState( TraceEditSequence::TSequenceStates whichState, TraceEditState *newState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;

  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return false;

  activeStates[ whichState ] = newState;
  return true;
}

TraceEditState *KTraceEditSequence::getState( TraceEditSequence::TSequenceStates whichState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;

  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return tmpIt->second;

  return NULL;
}

bool KTraceEditSequence::pushbackAction( TraceEditSequence::TSequenceActions whichAction )
{
  TraceEditAction *newAction;

  switch( whichAction )
  {
    case testAction:
      newAction = new TestAction( this );
      break;

    case traceCutterAction:
      newAction = new TraceCutterAction( this );
      break;

    case traceFilterAction:
      newAction = new TraceFilterAction( this );
      break;

    case csvOutputAction:
      newAction = new CSVOutputAction( this );
      break;

    case traceParserAction:
      newAction = new TraceParserAction( this );
      break;

    case recordTimeShifterAction:
      newAction = new RecordTimeShifterAction( this );
      break;

    case traceWriterAction:
      newAction = new TraceWriterAction( this );
      break;

    case eventDrivenCutterAction:
      newAction = new EventDrivenCutterAction( this );
      break;

    case traceSortAction:
      newAction = new TraceSortAction( this );
      break;

    default:
      return false;
      break;
  }

  if( !pushbackAction( newAction ) )
  {
    delete newAction;
    return false;
  }

  return true;
}

bool KTraceEditSequence::pushbackAction( TraceEditAction *newAction )
{
  TraceEditAction::TTraceEditActionType tmpType = newAction->getType();

  if( sequenceActions.empty() )
  {
    if( tmpType == TraceEditAction::TraceToTrace || tmpType == TraceEditAction::TraceToRecord )
    {
      sequenceActions.push_back( newAction );
      return true;
    }
    else
      return false;
  }

  switch( sequenceActions[ sequenceActions.size() - 1 ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
    case TraceEditAction::RecordToTrace:
      if( tmpType != TraceEditAction::TraceToTrace && tmpType != TraceEditAction::TraceToRecord )
        return false;
      break;

    case TraceEditAction::TraceToRecord:
    case TraceEditAction::RecordToRecord:
      if( tmpType != TraceEditAction::RecordToTrace && tmpType != TraceEditAction::RecordToRecord )
        return false;
      break;

    default:
      return false;
      break;
  }

  sequenceActions.push_back( newAction );
  return true;
}

bool KTraceEditSequence::execute( vector<std::string> traces )
{
  for( vector<TraceEditAction *>::iterator it = sequenceActions.begin();
       it != sequenceActions.end(); ++it )
  {
    vector<TraceEditSequence::TSequenceStates> tmpStates = (*it)->getStateDependencies();
    for( vector<TraceEditSequence::TSequenceStates>::iterator itState = tmpStates.begin();
         itState != tmpStates.end(); ++itState )
      addState( *itState );
  }

  TraceToTraceAction *firstActionTraceToTrace = ( TraceToTraceAction * )sequenceActions[ 0 ];
  TraceToRecordAction *firstActionTraceToRecord = ( TraceToRecordAction * )sequenceActions[ 0 ];

  bool someError = false;

  for( vector<std::string>::iterator it = traces.begin(); it != traces.end(); ++it )
  {
    currentAction = 0;
    currentTraceName = *it;

    for( map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator itState = activeStates.begin();
         itState != activeStates.end(); ++itState )
      itState->second->init();

    switch( sequenceActions[ 0 ]->getType() )
    {
      case TraceEditAction::TraceToTrace:
        sequenceExecError[ *it ] = firstActionTraceToTrace->execute( *it );
        break;

      case TraceEditAction::TraceToRecord:
        sequenceExecError[ *it ] = firstActionTraceToRecord->execute( *it );
        break;

      default:
        sequenceExecError[ *it ] = false;
        break;
    }

    someError = someError || sequenceExecError[ *it ];
  }

// TODO : think, some error in some trace?
  return someError;
}

bool KTraceEditSequence::executeNextAction( std::string whichTrace )
{
  if( sequenceExecError[ whichTrace ] )
    return true; // sequenceExecError[ whichTrace ]

  ++currentAction;
  if( currentAction == sequenceActions.size() )
  {
    --currentAction;
    return false;
  }

  TraceToTraceAction *nextActionToTrace = ( TraceToTraceAction * )sequenceActions[ currentAction ];
  TraceToRecordAction *nextActionToRecord = ( TraceToRecordAction * )sequenceActions[ currentAction ];

  switch( sequenceActions[ currentAction ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
      sequenceExecError[ whichTrace ] = nextActionToTrace->execute( whichTrace );
      break;

    case TraceEditAction::TraceToRecord:
      sequenceExecError[ whichTrace ] = nextActionToRecord->execute( whichTrace );
      break;

    case TraceEditAction::RecordToTrace:

      break;

    case TraceEditAction::RecordToRecord:

      break;

    default:
      break;
  }

  --currentAction;

  return sequenceExecError[ whichTrace ];
}

bool KTraceEditSequence::executeNextAction( MemoryTrace::iterator *whichRecord )
{
  if( sequenceExecError[ currentTraceName ] )
    return true; // sequenceExecError[ whichTrace ]

  ++currentAction;
  if( currentAction == sequenceActions.size() )
  {
    --currentAction;
    return false;
  }

  RecordToTraceAction *nextActionToTrace = ( RecordToTraceAction * )sequenceActions[ currentAction ];
  RecordToRecordAction *nextActionToRecord = ( RecordToRecordAction * )sequenceActions[ currentAction ];

  switch( sequenceActions[ currentAction ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
      break;

    case TraceEditAction::TraceToRecord:
      break;

    case TraceEditAction::RecordToTrace:
      sequenceExecError[ currentTraceName ] = nextActionToTrace->execute( whichRecord );
      break;

    case TraceEditAction::RecordToRecord:
      sequenceExecError[ currentTraceName ] = nextActionToRecord->execute( whichRecord );
      break;

    default:
      break;
  }

  --currentAction;

  return sequenceExecError[ currentTraceName ];
}

bool KTraceEditSequence::isEndOfSequence() const
{
  return ( currentAction == sequenceActions.size() - 1 );
}
<commit_msg>Removed calling TraceEditSequence constructor<commit_after>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                       Paraver Main Computing Library                      *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

#include <stdexcept>
#include "ktraceeditsequence.h"
#include "traceeditstates.h"
#include "ktraceeditactions.h"

using std::invalid_argument;

class TextOutput;

KTraceEditSequence::KTraceEditSequence( const KernelConnection *whichKernel )
{
}

KTraceEditSequence::~KTraceEditSequence()
{
  for( map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator it = activeStates.begin();
       it != activeStates.end(); ++it )
    delete it->second;

  for( vector<TraceEditAction *>::iterator it = sequenceActions.begin();
       it != sequenceActions.end(); ++it )
    delete *it;
}

const KernelConnection *KTraceEditSequence::getKernelConnection() const
{
  return myKernel;
}

TraceEditState *KTraceEditSequence::createState( TraceEditSequence::TSequenceStates whichState )
{
  switch( whichState )
  {
    case testState:
      return new TestState( this );
      break;

    case traceOptionsState:
      return new TraceOptionsState( this );
      break;

    case csvWindowState:
      return new CSVWindowState( this );
      break;

    case csvFileNameState:
      return new CSVFileNameState( this );
      break;

    case csvOutputState:
      return new CSVOutputState( this );
      break;

    case outputDirSuffixState:
      return new OutputDirSuffixState( this );
      break;

    case outputTraceFileNameState:
      return new OutputTraceFileNameState( this );
      break;

    case maxTraceTimeState:
      return new MaxTraceTimeState( this );
      break;

    case shiftTimesState:
      return new ShiftTimesState( this );
      break;

    case eofParsedState:
      return new EOFParsedState( this );
      break;

    case shiftLevelState:
      return new ShiftLevelState( this );
      break;

    case onEventCutterState:
      return new OnEventCutter( this );
      break;

    case pcfMergerReferenceState:
      return new PCFMergerReferenceState( this );
      break;

    case copyAdditionalFilesState:
      return new CopyAdditionalFilesState( this );
      break;

    case eventTranslationTableState:
      return new EventTranslationTableState( this );
      break;

    case onlyFilterState:
      return new OnlyFilterState( this );
      break;

    default:
      return NULL;
      break;
  }

  return NULL;
}

void KTraceEditSequence::setCurrentTrace( KTrace *whichTrace )
{
  currentTrace = whichTrace;
}

KTrace *KTraceEditSequence::getCurrentTrace()
{
  return currentTrace;
}

bool KTraceEditSequence::addState( TraceEditSequence::TSequenceStates whichState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;
  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return false;

  TraceEditState *newState = createState( whichState );
  if( newState == NULL )
    throw invalid_argument( "Invalid state for TraceEditSequence" );

  activeStates[ whichState ] = newState;
  return true;
}

bool KTraceEditSequence::addState( TraceEditSequence::TSequenceStates whichState, TraceEditState *newState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;

  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return false;

  activeStates[ whichState ] = newState;
  return true;
}

TraceEditState *KTraceEditSequence::getState( TraceEditSequence::TSequenceStates whichState )
{
  map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator tmpIt;

  tmpIt = activeStates.find( whichState );
  if( tmpIt != activeStates.end() )
    return tmpIt->second;

  return NULL;
}

bool KTraceEditSequence::pushbackAction( TraceEditSequence::TSequenceActions whichAction )
{
  TraceEditAction *newAction;

  switch( whichAction )
  {
    case testAction:
      newAction = new TestAction( this );
      break;

    case traceCutterAction:
      newAction = new TraceCutterAction( this );
      break;

    case traceFilterAction:
      newAction = new TraceFilterAction( this );
      break;

    case csvOutputAction:
      newAction = new CSVOutputAction( this );
      break;

    case traceParserAction:
      newAction = new TraceParserAction( this );
      break;

    case recordTimeShifterAction:
      newAction = new RecordTimeShifterAction( this );
      break;

    case traceWriterAction:
      newAction = new TraceWriterAction( this );
      break;

    case eventDrivenCutterAction:
      newAction = new EventDrivenCutterAction( this );
      break;

    case traceSortAction:
      newAction = new TraceSortAction( this );
      break;

    default:
      return false;
      break;
  }

  if( !pushbackAction( newAction ) )
  {
    delete newAction;
    return false;
  }

  return true;
}

bool KTraceEditSequence::pushbackAction( TraceEditAction *newAction )
{
  TraceEditAction::TTraceEditActionType tmpType = newAction->getType();

  if( sequenceActions.empty() )
  {
    if( tmpType == TraceEditAction::TraceToTrace || tmpType == TraceEditAction::TraceToRecord )
    {
      sequenceActions.push_back( newAction );
      return true;
    }
    else
      return false;
  }

  switch( sequenceActions[ sequenceActions.size() - 1 ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
    case TraceEditAction::RecordToTrace:
      if( tmpType != TraceEditAction::TraceToTrace && tmpType != TraceEditAction::TraceToRecord )
        return false;
      break;

    case TraceEditAction::TraceToRecord:
    case TraceEditAction::RecordToRecord:
      if( tmpType != TraceEditAction::RecordToTrace && tmpType != TraceEditAction::RecordToRecord )
        return false;
      break;

    default:
      return false;
      break;
  }

  sequenceActions.push_back( newAction );
  return true;
}

bool KTraceEditSequence::execute( vector<std::string> traces )
{
  for( vector<TraceEditAction *>::iterator it = sequenceActions.begin();
       it != sequenceActions.end(); ++it )
  {
    vector<TraceEditSequence::TSequenceStates> tmpStates = (*it)->getStateDependencies();
    for( vector<TraceEditSequence::TSequenceStates>::iterator itState = tmpStates.begin();
         itState != tmpStates.end(); ++itState )
      addState( *itState );
  }

  TraceToTraceAction *firstActionTraceToTrace = ( TraceToTraceAction * )sequenceActions[ 0 ];
  TraceToRecordAction *firstActionTraceToRecord = ( TraceToRecordAction * )sequenceActions[ 0 ];

  bool someError = false;

  for( vector<std::string>::iterator it = traces.begin(); it != traces.end(); ++it )
  {
    currentAction = 0;
    currentTraceName = *it;

    for( map<TraceEditSequence::TSequenceStates, TraceEditState *>::iterator itState = activeStates.begin();
         itState != activeStates.end(); ++itState )
      itState->second->init();

    switch( sequenceActions[ 0 ]->getType() )
    {
      case TraceEditAction::TraceToTrace:
        sequenceExecError[ *it ] = firstActionTraceToTrace->execute( *it );
        break;

      case TraceEditAction::TraceToRecord:
        sequenceExecError[ *it ] = firstActionTraceToRecord->execute( *it );
        break;

      default:
        sequenceExecError[ *it ] = false;
        break;
    }

    someError = someError || sequenceExecError[ *it ];
  }

// TODO : think, some error in some trace?
  return someError;
}

bool KTraceEditSequence::executeNextAction( std::string whichTrace )
{
  if( sequenceExecError[ whichTrace ] )
    return true; // sequenceExecError[ whichTrace ]

  ++currentAction;
  if( currentAction == sequenceActions.size() )
  {
    --currentAction;
    return false;
  }

  TraceToTraceAction *nextActionToTrace = ( TraceToTraceAction * )sequenceActions[ currentAction ];
  TraceToRecordAction *nextActionToRecord = ( TraceToRecordAction * )sequenceActions[ currentAction ];

  switch( sequenceActions[ currentAction ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
      sequenceExecError[ whichTrace ] = nextActionToTrace->execute( whichTrace );
      break;

    case TraceEditAction::TraceToRecord:
      sequenceExecError[ whichTrace ] = nextActionToRecord->execute( whichTrace );
      break;

    case TraceEditAction::RecordToTrace:

      break;

    case TraceEditAction::RecordToRecord:

      break;

    default:
      break;
  }

  --currentAction;

  return sequenceExecError[ whichTrace ];
}

bool KTraceEditSequence::executeNextAction( MemoryTrace::iterator *whichRecord )
{
  if( sequenceExecError[ currentTraceName ] )
    return true; // sequenceExecError[ whichTrace ]

  ++currentAction;
  if( currentAction == sequenceActions.size() )
  {
    --currentAction;
    return false;
  }

  RecordToTraceAction *nextActionToTrace = ( RecordToTraceAction * )sequenceActions[ currentAction ];
  RecordToRecordAction *nextActionToRecord = ( RecordToRecordAction * )sequenceActions[ currentAction ];

  switch( sequenceActions[ currentAction ]->getType() )
  {
    case TraceEditAction::TraceToTrace:
      break;

    case TraceEditAction::TraceToRecord:
      break;

    case TraceEditAction::RecordToTrace:
      sequenceExecError[ currentTraceName ] = nextActionToTrace->execute( whichRecord );
      break;

    case TraceEditAction::RecordToRecord:
      sequenceExecError[ currentTraceName ] = nextActionToRecord->execute( whichRecord );
      break;

    default:
      break;
  }

  --currentAction;

  return sequenceExecError[ currentTraceName ];
}

bool KTraceEditSequence::isEndOfSequence() const
{
  return ( currentAction == sequenceActions.size() - 1 );
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -g -emit-llvm %s -o - | FileCheck %s

struct C {
  ~C();
};
extern bool b;
// CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]]
// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]]
// CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1]
// CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2]
// CHECK: [[DTOR_CALL1_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN1_BLOCK:.*]], null}
// CHECK: [[FUN1_BLOCK]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN1]],
void fun1() { b && (C(), 1); }
// CHECK: [[DTOR_CALL2_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN2_BLOCK1:.*]], null}
// CHECK: [[FUN2_BLOCK1]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN2]],
bool fun2() { return (C(), b) && 0; }
<commit_msg>clang/test/CodeGenCXX/PR20038.cpp: Appease targeting msvc due to incompatibility of dw.<commit_after>// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm  %s -o - | FileCheck %s

struct C {
  ~C();
};
extern bool b;
// CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]]
// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]]
// CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1]
// CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2]
// CHECK: [[DTOR_CALL1_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN1_BLOCK:.*]], null}
// CHECK: [[FUN1_BLOCK]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN1]],
void fun1() { b && (C(), 1); }
// CHECK: [[DTOR_CALL2_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN2_BLOCK1:.*]], null}
// CHECK: [[FUN2_BLOCK1]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN2]],
bool fun2() { return (C(), b) && 0; }
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -std=c++11 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s

// Similar to predefined-expr.cpp, but not as exhaustive, since it's basically
// equivalent to __PRETTY_FUNCTION__.

extern "C" int printf(const char *, ...);

void freeFunc(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"

struct TopLevelClass {
  void topLevelMethod(int *, char);
};
void TopLevelClass::topLevelMethod(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"

namespace NS {
struct NamespacedClass {
  void namespacedMethod(int *, char);
};
void NamespacedClass::namespacedMethod(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
}
<commit_msg>Fix the funcsig test with an explicit triple<commit_after>// RUN: %clang_cc1 -std=c++11 -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s

// Similar to predefined-expr.cpp, but not as exhaustive, since it's basically
// equivalent to __PRETTY_FUNCTION__.

extern "C" int printf(const char *, ...);

void freeFunc(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"

struct TopLevelClass {
  void topLevelMethod(int *, char);
};
void TopLevelClass::topLevelMethod(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"

namespace NS {
struct NamespacedClass {
  void namespacedMethod(int *, char);
};
void NamespacedClass::namespacedMethod(int *, char) {
  printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
}
<|endoftext|>


<commit_before>/*
 * Scope Guard
 * Copyright (C) 2017  offa
 *
 * This file is part of Scope Guard.
 *
 * Scope Guard is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scope Guard 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 Scope Guard.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "unique_resource.h"
#include <catch.hpp>
#include <trompeloeil.hpp>

using namespace trompeloeil;

namespace
{
    using Handle = int;
    using PtrHandle = std::add_pointer_t<Handle>;

    struct CallMock
    {
        MAKE_MOCK1(deleter, void(Handle));
    };

    struct ThrowOnCopyMock
    {
        ThrowOnCopyMock() {  }

        ThrowOnCopyMock(const ThrowOnCopyMock&) noexcept(false)
        {
            throw std::exception{};
        }

        ThrowOnCopyMock(ThrowOnCopyMock&&) = delete;

        MAKE_CONST_MOCK1(deleter, void(ThrowOnCopyMock));

        ThrowOnCopyMock& operator=(const ThrowOnCopyMock&) noexcept(false)
        {
            throw std::exception{};
        }

        ThrowOnCopyMock& operator=(ThrowOnCopyMock&&) = delete;

    };

    struct NotNothrowMoveMock
    {
        NotNothrowMoveMock(CallMock* mo) : m_mock(mo) { }

        NotNothrowMoveMock(const NotNothrowMoveMock& other) : m_mock(other.m_mock)
        {
            throw std::exception{};
        }

        NotNothrowMoveMock(NotNothrowMoveMock&& other) noexcept(false) : m_mock(other.m_mock) { }

        void operator()(Handle h) const
        {
            m_mock->deleter(h);
        }

        NotNothrowMoveMock& operator=(const NotNothrowMoveMock&)
        {
            throw "Not implemented";
        }

        NotNothrowMoveMock& operator=(NotNothrowMoveMock&&)
        {
            throw "Not implemented";
        }

        CallMock* m_mock;
    };

    struct ConditialThrowOnCopyMock
    {
        explicit ConditialThrowOnCopyMock(Handle h, bool shouldThrow) : m_handle(h), m_shouldThrow(shouldThrow)
        {
        }

        ConditialThrowOnCopyMock(const ConditialThrowOnCopyMock& other) : m_handle(other.m_handle), m_shouldThrow(other.m_shouldThrow)
        {
            if( m_shouldThrow == true )
            {
                throw std::exception{};
            }
        }

        ConditialThrowOnCopyMock(ConditialThrowOnCopyMock&&) = default;

        ConditialThrowOnCopyMock& operator=(const ConditialThrowOnCopyMock& other)
        {
            if( &other != this )
            {
                m_handle = other.m_handle;
                m_shouldThrow = other.m_shouldThrow;

                if( m_shouldThrow == true )
                {
                    throw std::exception{};
                }
            }

            return *this;
        }

        ConditialThrowOnCopyMock& operator=(ConditialThrowOnCopyMock&&) = default;

        Handle m_handle;
        bool m_shouldThrow;
    };

    struct CopyMock
    {
        CopyMock() {}
        CopyMock(const CopyMock&) { }
    };

    CallMock m;

    void deleter(Handle h)
    {
        m.deleter(h);
    }

}

TEST_CASE("construction with move", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("construction with copy", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    const Handle h{3};
    const auto d = [](auto v) { m.deleter(v); };
    auto guard = sr::make_unique_resource(h, d);
    static_cast<void>(guard);
}

TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]")
{
    REQUIRE_THROWS([] {
        const ThrowOnCopyMock noMove;
        const auto d = [](const auto&) { m.deleter(3); };
        REQUIRE_CALL(m, deleter(3));

        sr::unique_resource<decltype(noMove), decltype(d)> guard{noMove, d};
        static_cast<void>(guard);
    }());
}

TEST_CASE("move-construction with move", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto movedFrom = sr::make_unique_resource(Handle{3}, deleter);
    auto guard = std::move(movedFrom);
    CHECK(guard.get() == 3);
}

TEST_CASE("move-construction with copy", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(7));
    auto d = [](auto) { deleter(7); };

    const CopyMock copyMock;
    sr::unique_resource<CopyMock, decltype(d)> movedFrom{copyMock, d};
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move assignment calls deleter", "[UniqueResource]")
{
    auto moveFrom = sr::make_unique_resource(Handle{3}, deleter);
    REQUIRE_CALL(m, deleter(4));

    {
        REQUIRE_CALL(m, deleter(3));
        auto guard = sr::make_unique_resource(Handle{4}, deleter);
        guard = std::move(moveFrom);
    }
}

TEST_CASE("deleter called on destruction", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("reset calls deleter", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource(Handle{3}, deleter);

    {
        REQUIRE_CALL(m, deleter(3));
        guard.reset();
    }
}

TEST_CASE("reset does not call deleter if released", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3)).TIMES(0);
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();
    guard.reset();
}

TEST_CASE("reset sets new value and calls deleter on previous", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    REQUIRE_CALL(m, deleter(7));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.reset(Handle{7});
}

TEST_CASE("release disables deleter", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3)).TIMES(0);
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();
}

TEST_CASE("get returns resource", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    CHECK(guard.get() == 3);
}

TEST_CASE("pointer access returns resource" "[UniqueResource]")
{
    const auto p = std::make_pair(3, 4);
    auto guard = sr::make_unique_resource(&p, [](auto*) { });
    REQUIRE(guard->first == 3);
    REQUIRE(guard->second == 4);
}

TEST_CASE("pointer dereference returns resource" "[UniqueResource]")
{
    Handle h{5};
    auto guard = sr::make_unique_resource(PtrHandle{&h}, [](auto*) { });
    REQUIRE(*guard == 5);
}

TEST_CASE("deleter access", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();

    {
        REQUIRE_CALL(m, deleter(8));
        guard.get_deleter()(8);
    }
}

TEST_CASE("make unique resource", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(7));
    auto guard = sr::make_unique_resource(Handle{7}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource with reference wrapper", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    Handle h{3};
    auto guard = sr::make_unique_resource(std::ref(h), deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource checked", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(4));
    auto guard = sr::make_unique_resource_checked(Handle{4}, Handle{-1}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource checked releases if invalid", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource_checked(Handle{-1}, Handle{-1}, deleter);
    static_cast<void>(guard);
}

<commit_msg>Test case added.<commit_after>/*
 * Scope Guard
 * Copyright (C) 2017  offa
 *
 * This file is part of Scope Guard.
 *
 * Scope Guard is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scope Guard 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 Scope Guard.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "unique_resource.h"
#include <catch.hpp>
#include <trompeloeil.hpp>

using namespace trompeloeil;

namespace
{
    using Handle = int;
    using PtrHandle = std::add_pointer_t<Handle>;

    struct CallMock
    {
        MAKE_MOCK1(deleter, void(Handle));
    };

    struct ThrowOnCopyMock
    {
        ThrowOnCopyMock() {  }

        ThrowOnCopyMock(const ThrowOnCopyMock&) noexcept(false)
        {
            throw std::exception{};
        }

        ThrowOnCopyMock(ThrowOnCopyMock&&) = delete;

        MAKE_CONST_MOCK1(deleter, void(ThrowOnCopyMock));

        ThrowOnCopyMock& operator=(const ThrowOnCopyMock&) noexcept(false)
        {
            throw std::exception{};
        }

        ThrowOnCopyMock& operator=(ThrowOnCopyMock&&) = delete;

    };

    struct NotNothrowMoveMock
    {
        NotNothrowMoveMock(CallMock* mo) : m_mock(mo) { }

        NotNothrowMoveMock(const NotNothrowMoveMock& other) : m_mock(other.m_mock)
        {
            throw std::exception{};
        }

        NotNothrowMoveMock(NotNothrowMoveMock&& other) noexcept(false) : m_mock(other.m_mock) { }

        void operator()(Handle h) const
        {
            m_mock->deleter(h);
        }

        NotNothrowMoveMock& operator=(const NotNothrowMoveMock&)
        {
            throw "Not implemented";
        }

        NotNothrowMoveMock& operator=(NotNothrowMoveMock&&)
        {
            throw "Not implemented";
        }

        CallMock* m_mock;
    };

    struct ConditialThrowOnCopyMock
    {
        explicit ConditialThrowOnCopyMock(Handle h, bool shouldThrow) : m_handle(h), m_shouldThrow(shouldThrow)
        {
        }

        ConditialThrowOnCopyMock(const ConditialThrowOnCopyMock& other) : m_handle(other.m_handle), m_shouldThrow(other.m_shouldThrow)
        {
            if( m_shouldThrow == true )
            {
                throw std::exception{};
            }
        }

        ConditialThrowOnCopyMock(ConditialThrowOnCopyMock&&) = default;

        ConditialThrowOnCopyMock& operator=(const ConditialThrowOnCopyMock& other)
        {
            if( &other != this )
            {
                m_handle = other.m_handle;
                m_shouldThrow = other.m_shouldThrow;

                if( m_shouldThrow == true )
                {
                    throw std::exception{};
                }
            }

            return *this;
        }

        ConditialThrowOnCopyMock& operator=(ConditialThrowOnCopyMock&&) = default;

        Handle m_handle;
        bool m_shouldThrow;
    };

    struct CopyMock
    {
        CopyMock() {}
        CopyMock(const CopyMock&) { }
    };

    CallMock m;

    void deleter(Handle h)
    {
        m.deleter(h);
    }

}

TEST_CASE("construction with move", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("construction with copy", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    const Handle h{3};
    const auto d = [](auto v) { m.deleter(v); };
    auto guard = sr::make_unique_resource(h, d);
    static_cast<void>(guard);
}

TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]")
{
    REQUIRE_THROWS([] {
        const ThrowOnCopyMock noMove;
        const auto d = [](const auto&) { m.deleter(3); };
        REQUIRE_CALL(m, deleter(3));

        sr::unique_resource<decltype(noMove), decltype(d)> guard{noMove, d};
        static_cast<void>(guard);
    }());
}

TEST_CASE("move-construction with move", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto movedFrom = sr::make_unique_resource(Handle{3}, deleter);
    auto guard = std::move(movedFrom);
    CHECK(guard.get() == 3);
}

TEST_CASE("move-construction with copy", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(7));
    auto d = [](auto) { deleter(7); };

    const CopyMock copyMock;
    sr::unique_resource<CopyMock, decltype(d)> movedFrom{copyMock, d};
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move assignment calls deleter", "[UniqueResource]")
{
    auto moveFrom = sr::make_unique_resource(Handle{3}, deleter);
    REQUIRE_CALL(m, deleter(4));

    {
        REQUIRE_CALL(m, deleter(3));
        auto guard = sr::make_unique_resource(Handle{4}, deleter);
        guard = std::move(moveFrom);
    }
}

TEST_CASE("deleter called on destruction", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("reset calls deleter", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource(Handle{3}, deleter);

    {
        REQUIRE_CALL(m, deleter(3));
        guard.reset();
    }
}

TEST_CASE("reset does not call deleter if released", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3)).TIMES(0);
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();
    guard.reset();
}

TEST_CASE("reset sets new value and calls deleter on previous", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    REQUIRE_CALL(m, deleter(7));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.reset(Handle{7});
}

TEST_CASE("reset handles exception on assignment", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    REQUIRE_CALL(m, deleter(7));
    auto d = [](const auto& v) { deleter(v.m_handle); };
    auto guard = sr::make_unique_resource(ConditialThrowOnCopyMock{3, false}, d);
    guard.reset(ConditialThrowOnCopyMock{7, true});
}

TEST_CASE("release disables deleter", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3)).TIMES(0);
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();
}

TEST_CASE("get returns resource", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    CHECK(guard.get() == 3);
}

TEST_CASE("pointer access returns resource" "[UniqueResource]")
{
    const auto p = std::make_pair(3, 4);
    auto guard = sr::make_unique_resource(&p, [](auto*) { });
    REQUIRE(guard->first == 3);
    REQUIRE(guard->second == 4);
}

TEST_CASE("pointer dereference returns resource" "[UniqueResource]")
{
    Handle h{5};
    auto guard = sr::make_unique_resource(PtrHandle{&h}, [](auto*) { });
    REQUIRE(*guard == 5);
}

TEST_CASE("deleter access", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource(Handle{3}, deleter);
    guard.release();

    {
        REQUIRE_CALL(m, deleter(8));
        guard.get_deleter()(8);
    }
}

TEST_CASE("make unique resource", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(7));
    auto guard = sr::make_unique_resource(Handle{7}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource with reference wrapper", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(3));
    Handle h{3};
    auto guard = sr::make_unique_resource(std::ref(h), deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource checked", "[UniqueResource]")
{
    REQUIRE_CALL(m, deleter(4));
    auto guard = sr::make_unique_resource_checked(Handle{4}, Handle{-1}, deleter);
    static_cast<void>(guard);
}

TEST_CASE("make unique resource checked releases if invalid", "[UniqueResource]")
{
    auto guard = sr::make_unique_resource_checked(Handle{-1}, Handle{-1}, deleter);
    static_cast<void>(guard);
}

<|endoftext|>


<commit_before>#include "util/file_piece.hh"

#include "util/file.hh"
#include "util/scoped.hh"
#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"
#include "util/murmur_hash.hh"
#include "util/probing_hash_table.hh"
#include "util/usage.hh"

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h> //For finding size of file
#include <boost/functional/hash.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

char * readTable(char * filename, size_t size);

uint64_t getHash(StringPiece text);

uint64_t getHash(StringPiece text) {
	std::size_t len = text.size();
	uint64_t key = util::MurmurHashNative(text.data(), len);
	return key;
}

//Read table from disk, return memory map location
char * readTable(char * filename, size_t size) {
    std::cerr << "Mem map" << std::endl;
	//Initial position of the file is the end of the file, thus we know the size
	int fd;
	//char *map;  // mmapped char array

	//Find the size
	struct stat filestatus;
	stat(filename, &filestatus);
	unsigned long filesize = filestatus.st_size;
	int array_length = filesize/sizeof(char);

	fd = open(filename, O_RDONLY);
	if (fd == -1) {
		perror("Error opening file for reading");
		exit(EXIT_FAILURE);
	}

	return (char *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
}

//Hash table entry
struct Entry {
	uint64_t key;
	typedef unsigned char Key;

	uint64_t GetKey() const {
		return key;
	}

	void SetKey(uint64_t to) {
		key = to;
	}

	uint64_t GetValue() const {
		return value;
	}

	uint64_t value;
};

//Define table
typedef util::ProbingHashTable<Entry, boost::hash<uint64_t> > Table;

int main(int argc, char* argv[]) {
	if (argc != 4) {
		// Tell the user how to run the program
		std::cerr << "Usage: " << argv[0] << " path_to_hashtable path_to_data_bin tablesize" << std::endl;
		return 1;
	}

	int i;
	int fd;
	char *map;  /* mmapped array of int's */

	//Find the size
	struct stat filestatus;
	stat(argv[2], &filestatus);
	unsigned long filesize = filestatus.st_size;
	int array_length = filesize/sizeof(char) - 1; //The end of file has \0, which we don't want to count.
	std::cout << "array_length is " << array_length << std::endl;

	fd = open(argv[2], O_RDONLY);
	if (fd == -1) {
		perror("Error opening file for reading");
		exit(EXIT_FAILURE);
	}

	map = (char *)mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
	if (map == MAP_FAILED) {
		close(fd);
		perror("Error mmapping the file");
		exit(EXIT_FAILURE);
	}

	//End of memory mapping code

	//Init the table
	int tablesize = atoi(argv[3]);
	size_t size = Table::Size(tablesize, 1.2);

	//Read it from file
	char * mem = readTable(argv[1], size);
	Table table(mem, size);

	//For searching
	const Entry * tmp;
	uint64_t key;

	//Interactive search
	std::cout << "Please enter a string to be searched, or exit to exit." << std::endl;
	while (true){
		bool found;
		std::string cinstr = "";
		getline(std::cin, cinstr);
		if (cinstr == "exit"){
			break;
		}else{
			StringPiece tofind = StringPiece(cinstr);
			key = getHash(cinstr);
			found = table.Find(key, tmp);
			if (found) {
				std::string found(&map[tmp -> GetValue()] , &map[tmp -> GetValue()] + 100);
				std::cout << "Phrase corresponding to " << cinstr << " is:"  << std::endl << found << std::endl;
			} else {
				std::cout << "Key not found!" << std::endl;
			}

		}
	}
	//clean up
	munmap(mem, size);
	close(fd);
	util::PrintUsage(std::cout);

	return 0;
}<commit_msg>Add forgotten unmap<commit_after>#include "util/file_piece.hh"

#include "util/file.hh"
#include "util/scoped.hh"
#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"
#include "util/murmur_hash.hh"
#include "util/probing_hash_table.hh"
#include "util/usage.hh"

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h> //For finding size of file
#include <boost/functional/hash.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

char * readTable(char * filename, size_t size);

uint64_t getHash(StringPiece text);

uint64_t getHash(StringPiece text) {
	std::size_t len = text.size();
	uint64_t key = util::MurmurHashNative(text.data(), len);
	return key;
}

//Read table from disk, return memory map location
char * readTable(char * filename, size_t size) {
    std::cerr << "Mem map" << std::endl;
	//Initial position of the file is the end of the file, thus we know the size
	int fd;
	//char *map;  // mmapped char array

	//Find the size
	struct stat filestatus;
	stat(filename, &filestatus);
	unsigned long filesize = filestatus.st_size;
	int array_length = filesize/sizeof(char);

	fd = open(filename, O_RDONLY);
	if (fd == -1) {
		perror("Error opening file for reading");
		exit(EXIT_FAILURE);
	}

	return (char *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
}

//Hash table entry
struct Entry {
	uint64_t key;
	typedef unsigned char Key;

	uint64_t GetKey() const {
		return key;
	}

	void SetKey(uint64_t to) {
		key = to;
	}

	uint64_t GetValue() const {
		return value;
	}

	uint64_t value;
};

//Define table
typedef util::ProbingHashTable<Entry, boost::hash<uint64_t> > Table;

int main(int argc, char* argv[]) {
	if (argc != 4) {
		// Tell the user how to run the program
		std::cerr << "Usage: " << argv[0] << " path_to_hashtable path_to_data_bin tablesize" << std::endl;
		return 1;
	}

	int i;
	int fd;
	char *map;  /* mmapped array of int's */

	//Find the size
	struct stat filestatus;
	stat(argv[2], &filestatus);
	unsigned long filesize = filestatus.st_size;
	int array_length = filesize/sizeof(char) - 1; //The end of file has \0, which we don't want to count.
	std::cout << "array_length is " << array_length << std::endl;

	fd = open(argv[2], O_RDONLY);
	if (fd == -1) {
		perror("Error opening file for reading");
		exit(EXIT_FAILURE);
	}

	map = (char *)mmap(0, filesize, PROT_READ, MAP_SHARED, fd, 0);
	if (map == MAP_FAILED) {
		close(fd);
		perror("Error mmapping the file");
		exit(EXIT_FAILURE);
	}

	//End of memory mapping code

	//Init the table
	int tablesize = atoi(argv[3]);
	size_t size = Table::Size(tablesize, 1.2);

	//Read it from file
	char * mem = readTable(argv[1], size);
	Table table(mem, size);

	//For searching
	const Entry * tmp;
	uint64_t key;

	//Interactive search
	std::cout << "Please enter a string to be searched, or exit to exit." << std::endl;
	while (true){
		bool found;
		std::string cinstr = "";
		getline(std::cin, cinstr);
		if (cinstr == "exit"){
			break;
		}else{
			StringPiece tofind = StringPiece(cinstr);
			key = getHash(cinstr);
			found = table.Find(key, tmp);
			if (found) {
				std::string found(&map[tmp -> GetValue()] , &map[tmp -> GetValue()] + 100);
				std::cout << "Phrase corresponding to " << cinstr << " is:"  << std::endl << found << std::endl;
			} else {
				std::cout << "Key not found!" << std::endl;
			}

		}
	}
	//clean up
	munmap(mem, size);
	munmap(map, filesize);
	close(fd);
	util::PrintUsage(std::cout);

	return 0;
}<|endoftext|>


<commit_before>#include "line_change_watcher.hh"

namespace Kakoune
{

std::vector<LineModification> LineChangeWatcher::compute_modifications()
{
    std::vector<LineModification> res;
    for (auto& change : m_changes)
    {
        auto pos = std::upper_bound(res.begin(), res.end(), change.pos,
                                    [](const LineCount& l, const LineModification& c)
                                    { return l < c.new_line; });

        if (pos != res.begin())
        {
            auto& prev = *(pos-1);
            if (change.pos <= prev.new_line + prev.num_added)
                --pos;
            else
                pos = res.insert(pos, {change.pos - prev.diff(), change.pos, 0, 0});
        }
        else
            pos = res.insert(pos, {change.pos, change.pos, 0, 0});

        auto& modif = *pos;
        auto next = pos + 1;
        if (change.num > 0)
        {
            modif.num_added += change.num;
            for (auto it = next; it != res.end(); ++it)
                it->new_line += change.num;
        }
        if (change.num < 0)
        {
            const LineCount num_removed = -change.num;

            auto delend = std::upper_bound(next, res.end(), change.pos + num_removed,
                                           [](const LineCount& l, const LineModification& c)
                                           { return l < c.new_line; });

            for (auto it = next; it != delend; ++it)
            {
                LineCount removed_from_it = (change.pos + num_removed - it->new_line);
                modif.num_removed += it->num_removed - std::min(removed_from_it, it->num_added);
                modif.num_added += std::max(0_line, it->num_added - removed_from_it);
            }
            next = res.erase(next, delend);

            const LineCount num_removed_from_added = std::min(num_removed, modif.new_line + modif.num_added - change.pos);
            modif.num_added -= num_removed_from_added;
            modif.num_removed += num_removed - num_removed_from_added;

            for (auto it = next; it != res.end(); ++it)
                it->new_line -= num_removed;
        }
    }
    m_changes.clear();
    return res;
}

void LineChangeWatcher::on_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    m_changes.push_back({begin.line, end.line - begin.line});
}

void LineChangeWatcher::on_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    if (begin.line == buffer.line_count())
    {
        kak_assert(begin.column == 0);
        --begin.line;
    }
    m_changes.push_back({begin.line, begin.line - end.line});
}

}
<commit_msg>Fix LineChangeWatcher behaviour when inserting at buffer end<commit_after>#include "line_change_watcher.hh"

namespace Kakoune
{

std::vector<LineModification> LineChangeWatcher::compute_modifications()
{
    std::vector<LineModification> res;
    for (auto& change : m_changes)
    {
        auto pos = std::upper_bound(res.begin(), res.end(), change.pos,
                                    [](const LineCount& l, const LineModification& c)
                                    { return l < c.new_line; });

        if (pos != res.begin())
        {
            auto& prev = *(pos-1);
            if (change.pos <= prev.new_line + prev.num_added)
                --pos;
            else
                pos = res.insert(pos, {change.pos - prev.diff(), change.pos, 0, 0});
        }
        else
            pos = res.insert(pos, {change.pos, change.pos, 0, 0});

        auto& modif = *pos;
        auto next = pos + 1;
        if (change.num > 0)
        {
            modif.num_added += change.num;
            for (auto it = next; it != res.end(); ++it)
                it->new_line += change.num;
        }
        if (change.num < 0)
        {
            const LineCount num_removed = -change.num;

            auto delend = std::upper_bound(next, res.end(), change.pos + num_removed,
                                           [](const LineCount& l, const LineModification& c)
                                           { return l < c.new_line; });

            for (auto it = next; it != delend; ++it)
            {
                LineCount removed_from_it = (change.pos + num_removed - it->new_line);
                modif.num_removed += it->num_removed - std::min(removed_from_it, it->num_added);
                modif.num_added += std::max(0_line, it->num_added - removed_from_it);
            }
            next = res.erase(next, delend);

            const LineCount num_removed_from_added = std::min(num_removed, modif.new_line + modif.num_added - change.pos);
            modif.num_added -= num_removed_from_added;
            modif.num_removed += num_removed - num_removed_from_added;

            for (auto it = next; it != res.end(); ++it)
                it->new_line -= num_removed;
        }
    }
    m_changes.clear();
    return res;
}

void LineChangeWatcher::on_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    if (buffer.is_end(end))
    {
        kak_assert(begin.column == 0);
        --begin.line;
    }
    m_changes.push_back({begin.line, end.line - begin.line});
}

void LineChangeWatcher::on_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    if (begin.line == buffer.line_count())
    {
        kak_assert(begin.column == 0);
        --begin.line;
    }
    m_changes.push_back({begin.line, begin.line - end.line});
}

}
<|endoftext|>


<commit_before>#pragma once

#include "Config.hpp"
#include "Common.hpp"

#include <imgui/imgui.h>
#include <imgui/imgui_impl_glfw.h>

struct GLFWwindow;

/**
 \brief Performs system basic operations, file picking, interface setup and loop.
 \ingroup Helpers
 */
namespace System {

	/**
	 \brief GUI helpers, internally backed by ImGUI.
	 \ingroup Helpers
	 */
	namespace GUI {

		/** Start registering GUI items. */
		void beginFrame();

		/** Finish registering GUI items and render them. */
		void endFrame();

		/** Clean internal resources. */
		void clean();

	}

	/** Create a new window backed by an OpenGL context.
	 \param name the name of the window
	 \param config the configuration to use (additional info will be added to it)
	 \return a pointer to the OS window
	 */
	GLFWwindow* initWindow(const std::string & name, RenderingConfig & config);

	/** System actions that can be executed by the window. */
	enum class Action {
		None, ///< Do nothing.
		Quit, ///< Quit the application.
		Fullscreen, ///< Switch the window from/to fullscreen mode.
		Vsync ///< Switch the v-sync on/off.
	};

	/** Execute an action related to the windowing system.
	 \param window the window
	 \param config the current window configuration
	 \param action the system action to perform
	 */
	void performWindowAction(GLFWwindow * window, RenderingConfig & config, const Action action);

	/** The file picker mode. */
	enum class Picker {
		Load, ///< Load an existing file.
		Directory, ///< open or create a directory.
		Save ///< Save to a new or existing file.
	};

	/** Present a filesystem document picker to the user, using native controls.
	 \param mode the type of item to ask to the user (load, save, directory)
	 \param startDir the initial directory when the picker is opended
	 \param outPath the path to the item selected by the user
	 \param extensions (optional) the extensions allowed, separated by "," or ";"
	 \return true if the user picked an item, false if cancelled.
	 */
	bool showPicker(const Picker mode, const std::string & startDir, std::string & outPath, const std::string & extensions = "");

	/** Create a directory.
	 \param directory the path to the directory to create
	 \return true if the creation is successful.
	 \note If the directory already exists, it will fail.
	 \warning This function will not create intermediate directories.
	 */
	bool createDirectory(const std::string & directory);

}

<commit_msg>System: add a parallel for helper.<commit_after>#pragma once

#include "Config.hpp"
#include "Common.hpp"

#include <imgui/imgui.h>
#include <imgui/imgui_impl_glfw.h>
#include <thread>

struct GLFWwindow;

/**
 \brief Performs system basic operations, file picking, interface setup and loop.
 \ingroup Helpers
 */
namespace System {

	/**
	 \brief GUI helpers, internally backed by ImGUI.
	 \ingroup Helpers
	 */
	namespace GUI {

		/** Start registering GUI items. */
		void beginFrame();

		/** Finish registering GUI items and render them. */
		void endFrame();

		/** Clean internal resources. */
		void clean();

	}

	/** Create a new window backed by an OpenGL context.
	 \param name the name of the window
	 \param config the configuration to use (additional info will be added to it)
	 \return a pointer to the OS window
	 */
	GLFWwindow* initWindow(const std::string & name, RenderingConfig & config);

	/** System actions that can be executed by the window. */
	enum class Action {
		None, ///< Do nothing.
		Quit, ///< Quit the application.
		Fullscreen, ///< Switch the window from/to fullscreen mode.
		Vsync ///< Switch the v-sync on/off.
	};

	/** Execute an action related to the windowing system.
	 \param window the window
	 \param config the current window configuration
	 \param action the system action to perform
	 */
	void performWindowAction(GLFWwindow * window, RenderingConfig & config, const Action action);

	/** The file picker mode. */
	enum class Picker {
		Load, ///< Load an existing file.
		Directory, ///< open or create a directory.
		Save ///< Save to a new or existing file.
	};

	/** Present a filesystem document picker to the user, using native controls.
	 \param mode the type of item to ask to the user (load, save, directory)
	 \param startDir the initial directory when the picker is opended
	 \param outPath the path to the item selected by the user
	 \param extensions (optional) the extensions allowed, separated by "," or ";"
	 \return true if the user picked an item, false if cancelled.
	 */
	bool showPicker(const Picker mode, const std::string & startDir, std::string & outPath, const std::string & extensions = "");

	/** Create a directory.
	 \param directory the path to the directory to create
	 \return true if the creation is successful.
	 \note If the directory already exists, it will fail.
	 \warning This function will not create intermediate directories.
	 */
	bool createDirectory(const std::string & directory);

	/** Multi-threaded for-loop.
	 \param low lower (included) bound
	 \param high higher (excluded) bound
	 \param func the function to execute at each iteration, will receive the index of the
	 element as a unique argument. Signature: void func(size_t i)
	 \note For now only an increment by one is supported.
	 */
	template<typename ThreadFunc>
	void forParallel(size_t low, size_t high, ThreadFunc func){
		// Make sure the loop is increasing.
		if(high < low){
			const size_t temp = low;
			low = high;
			high = temp;
		}
		// Prepare the threads pool.
		const size_t count = size_t(std::max(std::thread::hardware_concurrency(), unsigned(1)));
		std::vector<std::thread> threads;
		threads.reserve(count);

		// Compute the span of each thread.
		size_t span = size_t(std::round((float(high) - float(low))/float(count)));
		span = std::max(size_t(1), span);

		// Helper to execute the function passed on a subset of the total interval.
		auto launchThread = [&func](size_t a, size_t b) {
			for(size_t i = a; i < b; ++i) {
				func(i);
			}
		};

		for(size_t tid = 0; tid < count; ++tid){
			// For each thread, call the same lambda with different bounds as arguments.
			const size_t threadLow = tid * span;
			size_t threadHigh = (tid == count - 1) ? high : ((tid+1) * span);
			threads.emplace_back(launchThread, threadLow, threadHigh);
		}
		// Wait for all threads to finish.
		std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
	}

}

<|endoftext|>


<commit_before>/*
    Persons Model Example
    Copyright (C) 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include <QApplication>
#include <QTreeView>
#include <QHeaderView>
#include <QStyledItemDelegate>
#include <qpainter.h>
#include <../persons-model.h>

class ContactDelegate : public QStyledItemDelegate
{
    virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
        QStyledItemDelegate::paint(painter, option, index);
        if(index.parent().isValid())
            painter->drawText(option.rect.center(), index.data(PersonsModel::IMRole).toString());
    }
};

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

    QTreeView view;
    view.setItemDelegate(new ContactDelegate);
    view.setModel(new PersonsModel(&view));
    view.setSortingEnabled(true);
    view.show();

    app.exec();
}<commit_msg>add information in the lovelypeople delegate<commit_after>/*
    Persons Model Example
    Copyright (C) 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include <QApplication>
#include <QTreeView>
#include <QHeaderView>
#include <QStyledItemDelegate>
#include <qpainter.h>
#include <../persons-model.h>

class ContactDelegate : public QStyledItemDelegate
{
    virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
        QStyledItemDelegate::paint(painter, option, index);
        QRect infoRect(QPoint(option.rect.center().x(), option.rect.top()), option.rect.bottomRight());
        if(index.parent().isValid()) {
            painter->drawText(infoRect, index.data(PersonsModel::IMRole).toString());
        } else {
            painter->drawText(infoRect, QString::number(index.model()->rowCount(index)));
        }
    }
};

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

    QTreeView view;
    view.setItemDelegate(new ContactDelegate);
    view.setModel(new PersonsModel(&view));
    view.setSortingEnabled(true);
    view.show();

    app.exec();
}<|endoftext|>


<commit_before>#include <functional>

#include <gmock/gmock.h>

#include "control_loop.h"

#include "mock_robot_control.h"

using ::testing::InSequence;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::NiceMock;
using ::testing::_;

using franka::RobotState;
using franka::Stop;
using franka::Torques;

using research_interface::ControllerCommand;

class ControlLoop : public franka::ControlLoop {
 public:
  using franka::ControlLoop::ControlLoop;
  using franka::ControlLoop::spinOnce;
};

TEST(ControlLoop, CanConstructWithoutCallback) {
  MockRobotControl robot;
  EXPECT_CALL(robot, startController()).Times(0);
  EXPECT_CALL(robot, stopController()).Times(0);

  ControlLoop loop(robot, ControlLoop::ControlCallback());
}

TEST(ControlLoop, CanConstructWithCallback) {
  MockRobotControl robot;
  {
    InSequence _;
    EXPECT_CALL(robot, startController());
    EXPECT_CALL(robot, stopController());
  }

  ControlLoop loop(robot, [](const franka::RobotState&) { return Torques({0, 1, 2, 3, 4, 5, 6}); });
}

TEST(ControlLoop, SpinOnceWithoutCallback) {
  MockRobotControl robot;

  ControlLoop loop(robot, ControlLoop::ControlCallback());
  EXPECT_TRUE(loop.spinOnce());
}

TEST(ControlLoop, SpinOnceWithCallback) {
  struct MockControlCallback {
    MOCK_METHOD1(invoke, Torques(const RobotState&));
  };

  NiceMock<MockRobotControl> robot;
  MockControlCallback control_callback;

  Torques torques({0, 1, 2, 3, 4, 5, 6});

  RobotState robot_state;
  EXPECT_CALL(robot, robotStateMock()).WillOnce(ReturnRef(robot_state));
  EXPECT_CALL(robot, controllerCommandMock(Field(&research_interface::ControllerCommand::tau_J_d,
                                                 Eq(torques.tau_J))));

  EXPECT_CALL(control_callback, invoke(_)).WillOnce(Return(torques));

  ControlLoop loop(
      robot, std::bind(&MockControlCallback::invoke, &control_callback, std::placeholders::_1));
  EXPECT_TRUE(loop.spinOnce());
}

TEST(ControlLoop, SpinOnceWithStoppingCallback) {
  NiceMock<MockRobotControl> robot;
  RobotState robot_state;
  ON_CALL(robot, robotStateMock()).WillByDefault(ReturnRef(robot_state));
  ON_CALL(robot, update()).WillByDefault(Return(true));

  ControlLoop loop(robot, [](const RobotState&) { return Stop; });

  // Use ASSERT to abort on failure because loop() in next line
  // would block otherwise
  ASSERT_FALSE(loop.spinOnce());
  loop();
}
<commit_msg>test: Update control loop tests.<commit_after>#include <exception>
#include <functional>

#include <gmock/gmock.h>

#include "control_loop.h"

#include "helpers.h"
#include "mock_robot_control.h"

using namespace ::testing;

using franka::RobotState;
using franka::Stop;
using franka::Torques;

using research_interface::ControllerCommand;

class ControlLoop : public franka::ControlLoop {
 public:
  using franka::ControlLoop::ControlLoop;
  using franka::ControlLoopBase::spinOnce;
};

struct MockControlCallback {
  MOCK_METHOD1(invoke, Torques(const RobotState&));
};

TEST(ControlLoop, CanNotConstructWithoutCallback) {
  MockRobotControl robot;
  EXPECT_THROW(ControlLoop(robot, ControlLoop::ControlCallback()), std::invalid_argument);
}

TEST(ControlLoop, CanConstructWithCallback) {
  MockRobotControl robot;
  {
    InSequence _;
    EXPECT_CALL(robot, startController());
    EXPECT_CALL(robot, stopController());
  }

  StrictMock<MockControlCallback> control_callback;

  ControlLoop loop(
      robot, std::bind(&MockControlCallback::invoke, &control_callback, std::placeholders::_1));
}

TEST(ControlLoop, SpinOnce) {
  NiceMock<MockRobotControl> robot;
  MockControlCallback control_callback;

  Torques torques({0, 1, 2, 3, 4, 5, 6});

  RobotState robot_state;

  EXPECT_CALL(control_callback, invoke(Ref(robot_state))).WillOnce(Return(torques));

  ControlLoop loop(
      robot, std::bind(&MockControlCallback::invoke, &control_callback, std::placeholders::_1));

  ControllerCommand command;
  EXPECT_TRUE(loop.spinOnce(robot_state, &command));
  EXPECT_EQ(torques.tau_J, command.tau_J_d);
}

TEST(ControlLoop, SpinWithStoppingCallback) {
  NiceMock<MockRobotControl> robot;
  MockControlCallback control_callback;

  RobotState robot_state;
  EXPECT_CALL(control_callback, invoke(Ref(robot_state))).WillOnce(Return(Stop));

  ControlLoop loop(
      robot, std::bind(&MockControlCallback::invoke, &control_callback, std::placeholders::_1));

  // Use ASSERT to abort on failure because loop() further down
  // would block otherwise
  ASSERT_FALSE(loop.spinOnce(robot_state, nullptr));

  EXPECT_CALL(robot, update(_)).WillOnce(Return(RobotState()));
  EXPECT_CALL(control_callback, invoke(_)).WillOnce(DoAll(SaveArg<0>(&robot_state), Return(Stop)));
  loop();

  testRobotStateIsZero(robot_state);
}
<|endoftext|>