<commit_before>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::localIP;

int FileSystem::Folder::getTotalFiles() {
  int total = files.size();
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total;
}

int FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : files)
    total += kv.second.size;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  return total;
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  system("rm www/files/*");
  FileSystem::localIP = localIP;
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) != allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  if (!atoms.size()) // if no atom was found
    return false;
  auto it = atoms.begin();
  if (!parseName(*it)) // if the first name is invalid
    return false;
  string tmp = *it;
  it++;
  for (int i = 1; i < int(atoms.size()); i++) { // if there's an invalid name
    if (!parseName(*it))
      return false;
    tmp += '/';
    tmp += (*it);
    it++;
  }
  return tmp == path; // if the reassembled path is equals to the parsed
}

bool FileSystem::createFolder(const string& fullPath) {
  if (!parsePath(fullPath)) // if the path is invalid
    return false;
  if (folders.find(fullPath) != folders.end()) // if the folder already exists
    return false;
  pair<string, string> divided = divide(fullPath, '/');
  auto motherFolder = folders.find(divided.first);
  if (motherFolder == folders.end()) // if the mother folder doesn't exist
    return false;
  motherFolder->second.subfolders.insert(divided.second);
  folders[fullPath];
  return true;
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  auto folder = folders.find(fullPath);
  if (folder == folders.end())
    return nullptr;
  return &folder->second;
}

bool FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (fullPath == "root") // if the full path is the root folder
    return false;
  if (!parseName(newName)) // if the new name is invalid
    return false;
  pair<string, string> fullDivided = divide(fullPath, '/');
  if (fullDivided.second == newName) // if the new name is the current name
    return false;
  auto folder = folders.find(fullPath);
  if (folder == folders.end()) // if the folder doesn't exist
    return false;

  // create a new folder
  string newPath = (fullDivided.first + "/") + newName;
  auto& newFolder = folders[newPath];
  newFolder.subfolders = folder->second.subfolders;
  newFolder.files = folder->second.files;

  // erase old folder
  folders.erase(folder);

  for (auto& subfolder : newFolder.subfolders)
    updateFolder((fullPath + "/")

  // rename files stored in this peer
  //TODO

  return true;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return nullptr;//TODO
}

int FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

int FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<commit_msg>Changing variable name<commit_after>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::localIP;

int FileSystem::Folder::getTotalFiles() {
  int total = files.size();
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total;
}

int FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : files)
    total += kv.second.size;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  return total;
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  system("rm www/files/*");
  FileSystem::localIP = localIP;
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) != allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  if (!atoms.size()) // if no atom was found
    return false;
  auto it = atoms.begin();
  if (!parseName(*it)) // if the first name is invalid
    return false;
  string reassembledPath = *it;
  it++;
  for (int i = 1; i < int(atoms.size()); i++) { // if there's an invalid name
    if (!parseName(*it))
      return false;
    reassembledPath += '/';
    reassembledPath += (*it);
    it++;
  }
  return reassembledPath == path;
}

bool FileSystem::createFolder(const string& fullPath) {
  if (!parsePath(fullPath)) // if the path is invalid
    return false;
  if (folders.find(fullPath) != folders.end()) // if the folder already exists
    return false;
  pair<string, string> divided = divide(fullPath, '/');
  auto motherFolder = folders.find(divided.first);
  if (motherFolder == folders.end()) // if the mother folder doesn't exist
    return false;
  motherFolder->second.subfolders.insert(divided.second);
  folders[fullPath];
  return true;
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  auto folder = folders.find(fullPath);
  if (folder == folders.end())
    return nullptr;
  return &folder->second;
}

bool FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (fullPath == "root") // if the full path is the root folder
    return false;
  if (!parseName(newName)) // if the new name is invalid
    return false;
  pair<string, string> fullDivided = divide(fullPath, '/');
  if (fullDivided.second == newName) // if the new name is the current name
    return false;
  auto folder = folders.find(fullPath);
  if (folder == folders.end()) // if the folder doesn't exist
    return false;

  // create a new folder
  string newPath = (fullDivided.first + "/") + newName;
  auto& newFolder = folders[newPath];
  newFolder.subfolders = folder->second.subfolders;
  newFolder.files = folder->second.files;

  // erase old folder
  folders.erase(folder);

  for (auto& subfolder : newFolder.subfolders)
    updateFolder((fullPath + "/")

  // rename files stored in this peer
  //TODO

  return true;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return nullptr;//TODO
}

int FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

int FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016-2017 Kacper Kasper <kacperkasper@gmail.com>
 * All rights reserved. Distributed under the terms of the MIT license.
 */

#include "FindWindow.h"

#include <ScintillaView.h>

#include <Application.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <Message.h>
#include <RadioButton.h>
#include <StringView.h>

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FindWindow"

FindWindow::FindWindow()
	:
	BWindow(BRect(0, 0, 400, 300), B_TRANSLATE("Find/Replace"), B_TITLED_WINDOW,
		B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS, 0),
	fFlagsChanged(false)
{
	_InitInterface();
	CenterOnScreen();
}

FindWindow::~FindWindow()
{
}

void
FindWindow::MessageReceived(BMessage* message)
{
	switch(message->what) {
		case FINDWINDOW_FIND:
		case FINDWINDOW_REPLACE:
		case FINDWINDOW_REPLACEFIND:
		case FINDWINDOW_REPLACEALL: {
			int32 findLength = fFindTC->TextLength() + 1;
			int32 replaceLength = fReplaceTC->TextLength() + 1;
			std::string findText(findLength + 1, '\0');
			std::string replaceText(replaceLength + 1, '\0');
			fFindTC->GetText(0, findLength, &findText[0]);
			fReplaceTC->GetText(0, replaceLength, &replaceText[0]);
			bool newSearch = (fFlagsChanged
				|| fOldFindText != findText
				|| fOldReplaceText != replaceText);
			message->AddBool("newSearch", newSearch);
			message->AddBool("inSelection",
				(fInSelectionCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("matchCase",
				(fMatchCaseCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("matchWord",
				(fMatchWordCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("wrapAround",
				(fWrapAroundCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("regex",
				(fRegexCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("backwards",
				(fDirectionUpRadio->Value() == B_CONTROL_ON ? true : false));
			message->AddString("findText", findText.c_str());
			message->AddString("replaceText", replaceText.c_str());
			be_app->PostMessage(message);
			fOldFindText = findText;
			fOldReplaceText = replaceText;
			if(message->what == FINDWINDOW_REPLACEALL) {
				fFlagsChanged = true;
					// Force scope retargeting on next search
			} else {
				fFlagsChanged = false;
			}
		} break;
		case Actions::MATCH_CASE:
		case Actions::MATCH_WORD:
		case Actions::WRAP_AROUND:
		case Actions::DIRECTION_UP:
		case Actions::DIRECTION_DOWN:
		case Actions::IN_SELECTION: {
			fFlagsChanged = true;
		} break;
		default: {
			BWindow::MessageReceived(message);
		} break;
	}
}

void
FindWindow::WindowActivated(bool active)
{
	fFindTC->MakeFocus();
	fFindTC->SendMessage(SCI_SELECTALL);
}

void
FindWindow::Quit()
{
	be_app->PostMessage(FINDWINDOW_QUITTING);

	BWindow::Quit();
}

void
FindWindow::SetFindText(const std::string text)
{
	fFindTC->SetText(text.c_str());
}

void
FindWindow::_InitInterface()
{
	fFindString = new BStringView("findString", B_TRANSLATE("Find:"));
	fReplaceString = new BStringView("replaceString", B_TRANSLATE("Replace:"));
	fFindTC = new BScintillaView("findText", 0, true, true);
	fFindTC->SetExplicitMinSize(BSize(200, 100));
	fReplaceTC = new BScintillaView("replaceText", 0, true, true);
	fReplaceTC->SetExplicitMinSize(BSize(200, 100));

	fFindButton = new BButton(B_TRANSLATE("Find"), new BMessage((uint32) FINDWINDOW_FIND));
	fFindButton->MakeDefault(true);
	fFindButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceButton = new BButton(B_TRANSLATE("Replace"), new BMessage((uint32) FINDWINDOW_REPLACE));
	fReplaceButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceFindButton = new BButton(B_TRANSLATE("Replace and find"), new BMessage((uint32) FINDWINDOW_REPLACEFIND));
	fReplaceFindButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceAllButton = new BButton(B_TRANSLATE("Replace all"), new BMessage((uint32) FINDWINDOW_REPLACEALL));
	fReplaceAllButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));

	fMatchCaseCB = new BCheckBox("matchCase", B_TRANSLATE("Match case"), new BMessage((uint32) Actions::MATCH_CASE));
	fMatchWordCB = new BCheckBox("matchWord", B_TRANSLATE("Match entire words"), new BMessage((uint32) Actions::MATCH_WORD));
	fWrapAroundCB = new BCheckBox("wrapAround", B_TRANSLATE("Wrap around"), new BMessage((uint32) Actions::WRAP_AROUND));
	fInSelectionCB = new BCheckBox("inSelection", B_TRANSLATE("In selection"), new BMessage((uint32) Actions::IN_SELECTION));
	fRegexCB = new BCheckBox("regex", B_TRANSLATE("Regex"), new BMessage((uint32) Actions::REGEX));

	fDirectionBox = new BBox("direction");
	fDirectionUpRadio = new BRadioButton("directionUp", B_TRANSLATE("Up"), new BMessage((uint32) Actions::DIRECTION_UP));
	fDirectionDownRadio = new BRadioButton("directionDown", B_TRANSLATE("Down"), new BMessage((uint32) Actions::DIRECTION_DOWN));
	fDirectionDownRadio->SetValue(B_CONTROL_ON);

	BLayoutBuilder::Group<>(fDirectionBox, B_VERTICAL, 5)
		.Add(fDirectionUpRadio)
		.Add(fDirectionDownRadio)
		.SetInsets(10, 25, 15, 10);
	fDirectionBox->SetLabel(B_TRANSLATE("Direction"));

	BLayoutBuilder::Group<>(this, B_HORIZONTAL, 5)
		.AddGroup(B_VERTICAL, 5)
			.AddGrid(1, 1)
				.Add(fFindString, 0, 0)
				.Add(fFindTC, 1, 0)
				.Add(fReplaceString, 0, 1)
				.Add(fReplaceTC, 1, 1)
			.End()
			.AddGrid(1, 1)
				.Add(fMatchCaseCB, 0, 0)
				.Add(fWrapAroundCB, 1, 0)
				.Add(fMatchWordCB, 0, 1)
				.Add(fInSelectionCB, 1, 1)
				.Add(fDirectionBox, 0, 2)
				.Add(fRegexCB, 1, 2)
			.End()
		.End()
		.AddGroup(B_VERTICAL, 5)
			.Add(fFindButton)
			.Add(fReplaceButton)
			.Add(fReplaceFindButton)
			.Add(fReplaceAllButton)
			.AddGlue()
		.End()
		.SetInsets(5, 5, 5, 5);
}
<commit_msg>Fix keyboard navigation in Find/Replace.<commit_after>/*
 * Copyright 2016-2017 Kacper Kasper <kacperkasper@gmail.com>
 * All rights reserved. Distributed under the terms of the MIT license.
 */

#include "FindWindow.h"

#include <ScintillaView.h>

#include <Application.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <Message.h>
#include <RadioButton.h>
#include <StringView.h>

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FindWindow"

FindWindow::FindWindow()
	:
	BWindow(BRect(0, 0, 400, 300), B_TRANSLATE("Find/Replace"), B_TITLED_WINDOW,
		B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS, 0),
	fFlagsChanged(false)
{
	_InitInterface();
	CenterOnScreen();
}

FindWindow::~FindWindow()
{
}

void
FindWindow::MessageReceived(BMessage* message)
{
	switch(message->what) {
		case FINDWINDOW_FIND:
		case FINDWINDOW_REPLACE:
		case FINDWINDOW_REPLACEFIND:
		case FINDWINDOW_REPLACEALL: {
			int32 findLength = fFindTC->TextLength() + 1;
			int32 replaceLength = fReplaceTC->TextLength() + 1;
			std::string findText(findLength + 1, '\0');
			std::string replaceText(replaceLength + 1, '\0');
			fFindTC->GetText(0, findLength, &findText[0]);
			fReplaceTC->GetText(0, replaceLength, &replaceText[0]);
			bool newSearch = (fFlagsChanged
				|| fOldFindText != findText
				|| fOldReplaceText != replaceText);
			message->AddBool("newSearch", newSearch);
			message->AddBool("inSelection",
				(fInSelectionCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("matchCase",
				(fMatchCaseCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("matchWord",
				(fMatchWordCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("wrapAround",
				(fWrapAroundCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("regex",
				(fRegexCB->Value() == B_CONTROL_ON ? true : false));
			message->AddBool("backwards",
				(fDirectionUpRadio->Value() == B_CONTROL_ON ? true : false));
			message->AddString("findText", findText.c_str());
			message->AddString("replaceText", replaceText.c_str());
			be_app->PostMessage(message);
			fOldFindText = findText;
			fOldReplaceText = replaceText;
			if(message->what == FINDWINDOW_REPLACEALL) {
				fFlagsChanged = true;
					// Force scope retargeting on next search
			} else {
				fFlagsChanged = false;
			}
		} break;
		case Actions::MATCH_CASE:
		case Actions::MATCH_WORD:
		case Actions::WRAP_AROUND:
		case Actions::DIRECTION_UP:
		case Actions::DIRECTION_DOWN:
		case Actions::IN_SELECTION: {
			fFlagsChanged = true;
		} break;
		default: {
			BWindow::MessageReceived(message);
		} break;
	}
}

void
FindWindow::WindowActivated(bool active)
{
	fFindTC->MakeFocus();
	fFindTC->SendMessage(SCI_SELECTALL);
}

void
FindWindow::Quit()
{
	be_app->PostMessage(FINDWINDOW_QUITTING);

	BWindow::Quit();
}

void
FindWindow::SetFindText(const std::string text)
{
	fFindTC->SetText(text.c_str());
}

void
FindWindow::_InitInterface()
{
	fFindString = new BStringView("findString", B_TRANSLATE("Find:"));
	fReplaceString = new BStringView("replaceString", B_TRANSLATE("Replace:"));
	fFindTC = new BScintillaView("findText", 0, true, true);
	fFindTC->SetExplicitMinSize(BSize(200, 100));
	fFindTC->Target()->SetFlags(fFindTC->Target()->Flags() | B_NAVIGABLE);
	fReplaceTC = new BScintillaView("replaceText", 0, true, true);
	fReplaceTC->SetExplicitMinSize(BSize(200, 100));
	fReplaceTC->Target()->SetFlags(fReplaceTC->Target()->Flags() | B_NAVIGABLE);

	fFindButton = new BButton(B_TRANSLATE("Find"), new BMessage((uint32) FINDWINDOW_FIND));
	fFindButton->MakeDefault(true);
	fFindButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceButton = new BButton(B_TRANSLATE("Replace"), new BMessage((uint32) FINDWINDOW_REPLACE));
	fReplaceButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceFindButton = new BButton(B_TRANSLATE("Replace and find"), new BMessage((uint32) FINDWINDOW_REPLACEFIND));
	fReplaceFindButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
	fReplaceAllButton = new BButton(B_TRANSLATE("Replace all"), new BMessage((uint32) FINDWINDOW_REPLACEALL));
	fReplaceAllButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));

	fMatchCaseCB = new BCheckBox("matchCase", B_TRANSLATE("Match case"), new BMessage((uint32) Actions::MATCH_CASE));
	fMatchWordCB = new BCheckBox("matchWord", B_TRANSLATE("Match entire words"), new BMessage((uint32) Actions::MATCH_WORD));
	fWrapAroundCB = new BCheckBox("wrapAround", B_TRANSLATE("Wrap around"), new BMessage((uint32) Actions::WRAP_AROUND));
	fInSelectionCB = new BCheckBox("inSelection", B_TRANSLATE("In selection"), new BMessage((uint32) Actions::IN_SELECTION));
	fRegexCB = new BCheckBox("regex", B_TRANSLATE("Regex"), new BMessage((uint32) Actions::REGEX));

	fDirectionBox = new BBox("direction");
	fDirectionUpRadio = new BRadioButton("directionUp", B_TRANSLATE("Up"), new BMessage((uint32) Actions::DIRECTION_UP));
	fDirectionDownRadio = new BRadioButton("directionDown", B_TRANSLATE("Down"), new BMessage((uint32) Actions::DIRECTION_DOWN));
	fDirectionDownRadio->SetValue(B_CONTROL_ON);

	BLayoutBuilder::Group<>(fDirectionBox, B_VERTICAL, 5)
		.Add(fDirectionUpRadio)
		.Add(fDirectionDownRadio)
		.SetInsets(10, 25, 15, 10);
	fDirectionBox->SetLabel(B_TRANSLATE("Direction"));

	BLayoutBuilder::Group<>(this, B_HORIZONTAL, 5)
		.AddGroup(B_VERTICAL, 5)
			.AddGrid(1, 1)
				.Add(fFindString, 0, 0)
				.Add(fFindTC, 1, 0)
				.Add(fReplaceString, 0, 1)
				.Add(fReplaceTC, 1, 1)
			.End()
			.AddGrid(1, 1)
				.Add(fMatchCaseCB, 0, 0)
				.Add(fWrapAroundCB, 1, 0)
				.Add(fMatchWordCB, 0, 1)
				.Add(fInSelectionCB, 1, 1)
				.Add(fDirectionBox, 0, 2)
				.Add(fRegexCB, 1, 2)
			.End()
		.End()
		.AddGroup(B_VERTICAL, 5)
			.Add(fFindButton)
			.Add(fReplaceButton)
			.Add(fReplaceFindButton)
			.Add(fReplaceAllButton)
			.AddGlue()
		.End()
		.SetInsets(5, 5, 5, 5);
}
<|endoftext|>


<commit_before>//
// Created by Domagoj Boros on 18/12/2016.
//

#include "OverlapUtils.h"
#include <vector>
#include <algorithm>
#include <map>
#include "GraphUtils.h"
#include <limits.h>

static void popBubble(Graph &g, Vertex &v) {

}

static void isUnitigEnd(GraphEdgeType &graphEdgeType, Vertex &vertexOut, const Graph &graph, const Vertex &vertexIn) {

    const std::vector<Edge> &edges(graph.at(std::make_pair(vertexIn.first, !vertexIn.second)));

    size_t undeletedSize(0);
    size_t i(0);
    size_t undeletedEdgeIdx(0);
    for (const auto &edge : edges) {
        if (!edge.del) {
            ++undeletedSize;
            undeletedEdgeIdx = i;
        }
        ++i;
    }

    if (undeletedSize == 0) {
        graphEdgeType = GraphEdgeType::GRAPH_EDGE_TYPE_TIP;
        return;
    }

    if (undeletedSize > 1) {
        graphEdgeType = GraphEdgeType::GRAPH_EDGE_TYPE_MULTI_OUT;
        return;
    }

    vertexOut = std::make_pair(edges[undeletedEdgeIdx].bId, edges[undeletedEdgeIdx].bIsReversed);

    Vertex vertexOutNeg = std::make_pair(vertexOut.first, !vertexOut.second);

    undeletedSize = 0;
    for (const auto &edge : graph.at(vertexOutNeg)) {
        if (!edge.del) {
            ++undeletedSize;
        }
    }

    graphEdgeType = undeletedSize != 1 ? GRAPH_EDGE_TYPE_MULTI_NEI : GRAPH_EDGE_TYPE_MERGEABLE;

}

static void extend(std::vector<read_id_t> &readIds, GraphEdgeType &graphEdgeType, const Graph &g, const Vertex &v,
            const Params &params) {
    size_t tipExtension(params.maximalTipExtension);

    Vertex vertex = v;

    readIds.push_back(vertex.first);
    while (true) {
        isUnitigEnd(graphEdgeType, vertex, g, std::make_pair(vertex.first, !vertex.second));
//        printf("%d\n",graphEdgeType);
        if (graphEdgeType != GraphEdgeType::GRAPH_EDGE_TYPE_MERGEABLE) break;

        readIds.push_back(vertex.first);
        if (--tipExtension == 0) break;
    }
}

void generateGraph(Graph &g, const Overlaps &overlaps, const ReadTrims &readTrims, Params &params) {

    int edgeCnt = 0;

    for (const auto &o : overlaps) {
        OverlapClassification c;
        Edge e;
        classifyOverlapAndMeasureItsLength(c, e, o, readTrims.at(o.aId()).length(), readTrims.at(o.bId()).length(),
                                           params.maximalOverhangLength, params.mappingLengthRatio,
                                           params.minimalOverlap);
        if (c == OVERLAP_A_TO_B || c == OVERLAP_B_TO_A) {
            g[std::make_pair(e.aId, e.aIsReversed)].push_back(e);
            edgeCnt++;
        }
    }

    for (auto &p : g) {
        std::sort(p.second.begin(), p.second.end(), [](const Edge &a, const Edge &b) {
            return (a.overlapLength < b.overlapLength);
        });
    }

    std::cout << "Generated " << edgeCnt << " edges" << std::endl;
}

void filterTransitiveEdges(Graph &g, read_size_t FUZZ) {

#define VACANT 0
#define INPLAY 1
#define ELIMINATED 2

    std::map<std::pair<read_id_t, bool>, char> mark;
    for (const auto &p : g) {
        mark[p.first] = VACANT;
        for (const Edge &vw : p.second) mark[std::make_pair(vw.bId, vw.bIsReversed)] = VACANT;
    }

    int reduceCnt = 0;
    for (auto &p : g) {
        for (const auto &vw : p.second) mark[std::make_pair(vw.bId, vw.bIsReversed)] = INPLAY;

        if(p.second.size() == 0) continue;

        read_size_t longest = p.second[p.second.size() - 1].overlapLength + FUZZ;
        for (const auto &vw : p.second) {
            std::pair<read_id_t, bool> w(vw.bId, vw.bIsReversed);
            if (mark[w] == INPLAY) {
                for (const auto &wx : g[w]) {
                    if (wx.overlapLength + vw.overlapLength > longest) break;
                    std::pair<read_id_t, bool> x(wx.bId, wx.bIsReversed);
                    if (mark[x] == INPLAY) mark[x] = ELIMINATED;
                }
            }
        }

//        for (const auto& vw : p.second) {
//            read_id_t w = vw.bId;
//            int i = 0;
//            for (const auto& wx : g[w]) {
//                if (wx.overlapLength >= FUZZ && i != 0) break;
//                read_id_t x = wx.bId;
//                if (mark[x] == INPLAY) mark[x] = ELIMINATED;
//                i++;
//            }
//        }

        for (auto &vw : p.second) {
            std::pair<read_id_t, bool> w (vw.bId, vw.bIsReversed);
            if (mark[w] == ELIMINATED) {
                vw.del = 1;
                reduceCnt++;
            }
            mark[w] = VACANT;
        }
    }

    cleanGraph(g);

    std::cout << "Reduced " << reduceCnt << " edges" << std::endl;

#undef VACANT
#undef INPLAY
#undef ELIMINATED
}

void logGraph(const Graph &g) {
    for (const auto &pair : g) {
        auto u(pair.first);
        std::cout << u.first << " !"[u.second] << std::endl;
        const auto &edges(pair.second);

        for (auto const &edge: edges) {
            std::cout << "\t" << edge.aId << " !"[edge.aIsReversed] << " --" << edge.overlapLength << "--> " << edge.bId
                      << " !"[edge.bIsReversed] << " " << " D"[edge.del] << std::endl;
        }
    }
}

void removeAsymetricEdges(Graph &g) {

    size_t cnt(0);

    for (auto& p : g) {
        for (auto& e : p.second) {
            bool found = false;
            for (auto& e2 : g[std::make_pair(e.bId, !e.bIsReversed)]) {
                if (e2.bId == p.first.first && e2.bIsReversed != p.first.second) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                e.del = true;
                ++cnt;
            }
        }
    }

    cleanGraph(g);

    std::cout << "Removing " << cnt << " asymetric edges" << std::endl;
}

void cleanGraph(Graph &g) {
    for (auto & p : g) {
        std::vector<Edge> newEdges;
        for (auto& e : p.second) {
            if (!e.del) newEdges.push_back(e);
        }
        p.second.swap(newEdges);
        newEdges.clear();
    }
}

void cutTips(Graph &g, ReadTrims &readTrims, const Params &params) {

    size_t cnt(0);

//    auto p(std::make_pair(std::make_pair(198,false),g[std::make_pair(198,false)]));
    for (auto &p : g) {
//        std::cout<<p.first.first<<" !"[p.first.second]<<std::endl;
        Vertex vertexOut;
        GraphEdgeType graphEdgeType;
        isUnitigEnd(graphEdgeType, vertexOut, g, p.first);
        if(readTrims[p.first.first].del) continue;
//    printf("Not deleted\n");

        if (graphEdgeType != GRAPH_EDGE_TYPE_TIP) continue; // not a tip
//        printf("Is tip\n");

        std::vector<read_id_t> readIds;

        extend(readIds, graphEdgeType, g, p.first, params);

        if (graphEdgeType == GRAPH_EDGE_TYPE_MERGEABLE) continue;
//        printf("Not unitig\n");

//        if (readIds.size() == 0) continue;
        ++cnt;

        for (read_id_t readId: readIds) {
            readTrims[readId].del = true;

            // delete all outgoing edges from u and u' and all reverse edges (if u->v is deleted delete v'->u')

            for (int i = 0; i < 2; ++i) {
                for (auto &edge: g[std::make_pair(readId, static_cast<bool>(i))]) {
                    edge.del = true;

                    for (auto &edge2: g[std::make_pair(edge.bId, !edge.bIsReversed)]) {
                        if(edge2.bId == readId && edge2.bIsReversed != edge.aIsReversed){
                            edge2.del = true;
                        }
                    }
                }
            }
        }
    }

    cleanGraph(g);

    std::cout << "Cutting " << cnt << " tips" << std::endl;
}

int countIncoming(Graph& g, Vertex& v) {
    int cnt = 0;
    for (const auto& e : g[std::make_pair(v.first, !v.second)]) if (!e.del) cnt++;
    return cnt;
}

void popBubbles(Graph& g , ReadTrims &readTrims) {

    #define D 50000

    std::vector<Vertex> S;
    std::map<Vertex, int> distances;
    std::map<Vertex, int> unvisitedIncoming;

    std::vector<Vertex> visitedV;
    std::map<Vertex, Vertex> optPath;

    for (auto& p : g) {
        if (p.second.size() < 2 || readTrims[p.first.first].del) continue;
        int nonDeleted = 0;

//        distances.clear();
        unvisitedIncoming.clear();
        S.clear();
        visitedV.clear();
        optPath.clear();

        const Vertex& read0 = p.first;

        for (auto& p2 : g) distances[p2.first] = INT_MAX;

        distances[read0] = 0;

        S.push_back(read0);
        int pv = 0;

        while (S.size() > 0) {
            Vertex& read = S.back();
            S.pop_back();

            for (auto& edge: g[read]) {
                if(edge.bId == read0.first) break; // jel se moze napisat ovak il se mora cijeli vertex usporedit
                if (edge.del) continue;

                edge.visited = true;

                Vertex b = std::make_pair(edge.bId, edge.bIsReversed);

                if(distances[read] + edge.overlapLength > D) break;

                if(distances[b] == INT_MAX) { // not visited
                    unvisitedIncoming[b] = countIncoming(g, b);
                    ++pv;
                    visitedV.push_back(b);
                    optPath[b] = read;
                } else { // visited

                }

                if(distances[read] + edge.overlapLength < distances[b]) {
                    distances[b] = distances[read] + edge.overlapLength;
                    optPath[b] = read;

                }

                --unvisitedIncoming[b];
                if(unvisitedIncoming[b] == 0) {
                    if(g[b].size() != 0) S.push_back(b);
                    --pv;
                }
            }

            if (S.size() == 1 && pv == 0) {
                std::cout << "Found bubble " << read0.first << " !"[read0.second] << " -> " <<  S.back().first << " !"[S.back().second] << std::endl;

                // delete visited vertex and edges
                for (auto& vv : visitedV) {
//                    std::cout << "Visiting " << vv.first <<  " !"[vv.second] << std::endl;
                    readTrims[vv.first].del = true;
                }
                for (auto& p2 : g) {
                    for (auto &edge: p2.second) {
                        if (edge.visited) {

//                            std::cout << "Deleting : " << std::endl << edge.aId <<  " !"[edge.aIsReversed] << " -> " << edge.bId <<  " !"[edge.bIsReversed] << std::endl;

                            edge.del = true;
                            for (auto &edge2: g[std::make_pair(edge.bId, !edge.bIsReversed)]) {
                                if (edge2.bId == edge.aId && edge2.bIsReversed != edge.aIsReversed) {
//                                    std::cout <<  edge2.aId <<  " !"[edge2.aIsReversed] << " -> " << edge2.bId <<  " !"[edge2.bIsReversed] << std::endl;
                                    edge2.del = true;
                                }
                            }
                        }
                    }
                }

                Vertex& v = S.back();
//                std::cout << "Visiting " << v.first <<  " !"[v.second] << std::endl;
                while (v != read0) {
                    Vertex& u = optPath[v]; // u -> v
//                    std::cout << "Visiting " << u.first <<  " !"[u.second] << std::endl;
                    readTrims[v.first].del = false;

                    for (auto& edge: g[u]) if (edge.bId == v.first && edge.bIsReversed == v.second) edge.del = false;
                    for (auto& edge: g[std::make_pair(v.first, !v.second)]) if (edge.bId == u.first && edge.bIsReversed == !u.second) edge.del = false;
                    v = u;
                }

                break;
            }
        }

        for (auto& p2 : g) for (auto& e : p2.second) e.visited = false;

    }

    cleanGraph(g);

    #undef D
}
<commit_msg>Good fix<commit_after>//
// Created by Domagoj Boros on 18/12/2016.
//

#include "OverlapUtils.h"
#include <vector>
#include <algorithm>
#include <map>
#include "GraphUtils.h"
#include <limits.h>

static void popBubble(Graph &g, Vertex &v) {

}

static void isUnitigEnd(GraphEdgeType &graphEdgeType, Vertex &vertexOut, const Graph &graph, const Vertex &vertexIn) {

    const std::vector<Edge> &edges(graph.at(std::make_pair(vertexIn.first, !vertexIn.second)));

    size_t undeletedSize(0);
    size_t i(0);
    size_t undeletedEdgeIdx(0);
    for (const auto &edge : edges) {
        if (!edge.del) {
            ++undeletedSize;
            undeletedEdgeIdx = i;
        }
        ++i;
    }

    if (undeletedSize == 0) {
        graphEdgeType = GraphEdgeType::GRAPH_EDGE_TYPE_TIP;
        return;
    }

    if (undeletedSize > 1) {
        graphEdgeType = GraphEdgeType::GRAPH_EDGE_TYPE_MULTI_OUT;
        return;
    }

    vertexOut = std::make_pair(edges[undeletedEdgeIdx].bId, edges[undeletedEdgeIdx].bIsReversed);

    Vertex vertexOutNeg = std::make_pair(vertexOut.first, !vertexOut.second);

    undeletedSize = 0;
    for (const auto &edge : graph.at(vertexOutNeg)) {
        if (!edge.del) {
            ++undeletedSize;
        }
    }

    graphEdgeType = undeletedSize != 1 ? GRAPH_EDGE_TYPE_MULTI_NEI : GRAPH_EDGE_TYPE_MERGEABLE;

}

static void extend(std::vector<read_id_t> &readIds, GraphEdgeType &graphEdgeType, const Graph &g, const Vertex &v,
            const Params &params) {
    size_t tipExtension(params.maximalTipExtension);

    Vertex vertex = v;

    readIds.push_back(vertex.first);
    while (true) {
        isUnitigEnd(graphEdgeType, vertex, g, std::make_pair(vertex.first, !vertex.second));
//        printf("%d\n",graphEdgeType);
        if (graphEdgeType != GraphEdgeType::GRAPH_EDGE_TYPE_MERGEABLE) break;

        readIds.push_back(vertex.first);
        if (--tipExtension == 0) break;
    }
}

void generateGraph(Graph &g, const Overlaps &overlaps, const ReadTrims &readTrims, Params &params) {

    int edgeCnt = 0;

    for (const auto &o : overlaps) {
        OverlapClassification c;
        Edge e;
        classifyOverlapAndMeasureItsLength(c, e, o, readTrims.at(o.aId()).length(), readTrims.at(o.bId()).length(),
                                           params.maximalOverhangLength, params.mappingLengthRatio,
                                           params.minimalOverlap);
        if (c == OVERLAP_A_TO_B || c == OVERLAP_B_TO_A) {
            g[std::make_pair(e.aId, e.aIsReversed)].push_back(e);
            edgeCnt++;
        }
    }

    for (auto &p : g) {
        std::sort(p.second.begin(), p.second.end(), [](const Edge &a, const Edge &b) {
            return (a.overlapLength < b.overlapLength);
        });
    }

    std::cout << "Generated " << edgeCnt << " edges" << std::endl;
}

void filterTransitiveEdges(Graph &g, read_size_t FUZZ) {

#define VACANT 0
#define INPLAY 1
#define ELIMINATED 2

    std::map<std::pair<read_id_t, bool>, char> mark;
    for (const auto &p : g) {
        mark[p.first] = VACANT;
        for (const Edge &vw : p.second) mark[std::make_pair(vw.bId, vw.bIsReversed)] = VACANT;
    }

    int reduceCnt = 0;
    for (auto &p : g) {
        for (const auto &vw : p.second) mark[std::make_pair(vw.bId, vw.bIsReversed)] = INPLAY;

        if(p.second.size() == 0) continue;

        read_size_t longest = p.second[p.second.size() - 1].overlapLength + FUZZ;
        for (const auto &vw : p.second) {
            std::pair<read_id_t, bool> w(vw.bId, vw.bIsReversed);
            if (mark[w] == INPLAY) {
                for (const auto &wx : g[w]) {
                    if (wx.overlapLength + vw.overlapLength > longest) break;
                    std::pair<read_id_t, bool> x(wx.bId, wx.bIsReversed);
                    if (mark[x] == INPLAY) mark[x] = ELIMINATED;
                }
            }
        }

//        for (const auto& vw : p.second) {
//            read_id_t w = vw.bId;
//            int i = 0;
//            for (const auto& wx : g[w]) {
//                if (wx.overlapLength >= FUZZ && i != 0) break;
//                read_id_t x = wx.bId;
//                if (mark[x] == INPLAY) mark[x] = ELIMINATED;
//                i++;
//            }
//        }

        for (auto &vw : p.second) {
            std::pair<read_id_t, bool> w (vw.bId, vw.bIsReversed);
            if (mark[w] == ELIMINATED) {
                vw.del = 1;
                reduceCnt++;
            }
            mark[w] = VACANT;
        }
    }

    cleanGraph(g);

    std::cout << "Reduced " << reduceCnt << " edges" << std::endl;

#undef VACANT
#undef INPLAY
#undef ELIMINATED
}

void logGraph(const Graph &g) {
    for (const auto &pair : g) {
        auto u(pair.first);
        std::cout << u.first << " !"[u.second] << std::endl;
        const auto &edges(pair.second);

        for (auto const &edge: edges) {
            std::cout << "\t" << edge.aId << " !"[edge.aIsReversed] << " --" << edge.overlapLength << "--> " << edge.bId
                      << " !"[edge.bIsReversed] << " " << " D"[edge.del] << std::endl;
        }
    }
}

void removeAsymetricEdges(Graph &g) {

    size_t cnt(0);

    for (auto& p : g) {
        for (auto& e : p.second) {
            bool found = false;
            for (auto& e2 : g[std::make_pair(e.bId, !e.bIsReversed)]) {
                if (e2.bId == p.first.first && e2.bIsReversed != p.first.second) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                e.del = true;
                ++cnt;
            }
        }
    }

    cleanGraph(g);

    std::cout << "Removing " << cnt << " asymetric edges" << std::endl;
}

void cleanGraph(Graph &g) {
    for (auto & p : g) {
        std::vector<Edge> newEdges;
        for (auto& e : p.second) {
            if (!e.del) newEdges.push_back(e);
        }
        p.second.swap(newEdges);
        newEdges.clear();
    }
}

void cutTips(Graph &g, ReadTrims &readTrims, const Params &params) {

    size_t cnt(0);

//    auto p(std::make_pair(std::make_pair(198,false),g[std::make_pair(198,false)]));
    for (auto &p : g) {
//        std::cout<<p.first.first<<" !"[p.first.second]<<std::endl;
        Vertex vertexOut;
        GraphEdgeType graphEdgeType;
        isUnitigEnd(graphEdgeType, vertexOut, g, p.first);
        if(readTrims[p.first.first].del) continue;
//    printf("Not deleted\n");

        if (graphEdgeType != GRAPH_EDGE_TYPE_TIP) continue; // not a tip
//        printf("Is tip\n");

        std::vector<read_id_t> readIds;

        extend(readIds, graphEdgeType, g, p.first, params);

        if (graphEdgeType == GRAPH_EDGE_TYPE_MERGEABLE) continue;
//        printf("Not unitig\n");

//        if (readIds.size() == 0) continue;
        ++cnt;

        for (read_id_t readId: readIds) {
            readTrims[readId].del = true;

            // delete all outgoing edges from u and u' and all reverse edges (if u->v is deleted delete v'->u')

            for (int i = 0; i < 2; ++i) {
                for (auto &edge: g[std::make_pair(readId, static_cast<bool>(i))]) {
                    edge.del = true;

                    for (auto &edge2: g[std::make_pair(edge.bId, !edge.bIsReversed)]) {
                        if(edge2.bId == readId && edge2.bIsReversed != edge.aIsReversed){
                            edge2.del = true;
                        }
                    }
                }
            }
        }
    }

    cleanGraph(g);

    std::cout << "Cutting " << cnt << " tips" << std::endl;
}

int countIncoming(Graph& g, Vertex& v) {
    int cnt = 0;
    for (const auto& e : g[std::make_pair(v.first, !v.second)]) if (!e.del) cnt++;
    return cnt;
}

void popBubbles(Graph& g , ReadTrims &readTrims) {

    #define D 50000

    std::vector<Vertex> S;
    std::map<Vertex, int> distances;
    std::map<Vertex, int> unvisitedIncoming;

    std::vector<Vertex> visitedV;
    std::map<Vertex, Vertex> optPath;

    for (auto& p : g) {
        if (p.second.size() < 2 || readTrims[p.first.first].del) continue;
        int nonDeleted = 0;

//        distances.clear();
        unvisitedIncoming.clear();
        S.clear();
        visitedV.clear();
        optPath.clear();

        const Vertex& read0 = p.first;

        for (auto& p2 : g) distances[p2.first] = INT_MAX;

        distances[read0] = 0;

        S.push_back(read0);
        int pv = 0;

        while (S.size() > 0) {
            Vertex& read = S.back();
            S.pop_back();

            for (auto& edge: g[read]) {
                if(edge.bId == read0.first) break; // jel se moze napisat ovak il se mora cijeli vertex usporedit
                if (edge.del) continue;

                edge.visited = true;

                Vertex b = std::make_pair(edge.bId, edge.bIsReversed);

                if(distances[read] + edge.overlapLength > D) break;

                if(distances[b] == INT_MAX) { // not visited
                    unvisitedIncoming[b] = countIncoming(g, b);
                    ++pv;
                    visitedV.push_back(b);
                    optPath[b] = read;
                } else { // visited

                }

                if(distances[read] + edge.overlapLength < distances[b]) {
                    distances[b] = distances[read] + edge.overlapLength;
                    optPath[b] = read;

                }

                --unvisitedIncoming[b];
                if(unvisitedIncoming[b] == 0) {
                    if(g[b].size() != 0) S.push_back(b);
                    --pv;
                }
            }

            if (S.size() == 1 && pv == 0) {
                std::cout << "Found bubble " << read0.first << " !"[read0.second] << " -> " <<  S.back().first << " !"[S.back().second] << std::endl;

                // delete visited vertex and edges
                for (auto& vv : visitedV) {
//                    std::cout << "Visiting " << vv.first <<  " !"[vv.second] << std::endl;
                    readTrims[vv.first].del = true;
                }
                for (auto& p2 : g) {
                    for (auto &edge: p2.second) {
                        if (edge.visited) {

//                            std::cout << "Deleting : " << std::endl << edge.aId <<  " !"[edge.aIsReversed] << " -> " << edge.bId <<  " !"[edge.bIsReversed] << std::endl;

                            edge.del = true;
                            for (auto &edge2: g[std::make_pair(edge.bId, !edge.bIsReversed)]) {
                                if (edge2.bId == edge.aId && edge2.bIsReversed != edge.aIsReversed) {
//                                    std::cout <<  edge2.aId <<  " !"[edge2.aIsReversed] << " -> " << edge2.bId <<  " !"[edge2.bIsReversed] << std::endl;
                                    edge2.del = true;
                                }
                            }
                        }
                    }
                }

                Vertex& v = S.back();
//                std::cout << "Visiting " << v.first <<  " !"[v.second] << std::endl;
                while (v != read0) {
                    Vertex& u = optPath[v]; // u -> v
//                    std::cout << "Visiting " << u.first <<  " !"[u.second] << std::endl;
                    readTrims[v.first].del = false;

                    for (auto& edge: g[u]) if (edge.bId == v.first && edge.bIsReversed == v.second) edge.del = false;
                    for (auto& edge: g[std::make_pair(v.first, !v.second)]) if (edge.bId == u.first && edge.bIsReversed == !u.second) edge.del = false;
                    v = u;
                }

                cleanGraph(g);

                break;
            }
        }

        for (auto& p2 : g) for (auto& e : p2.second) e.visited = false;

    }

    #undef D
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "projectwindow.h"

#include "doubletabwidget.h"
#include "panelswidget.h"
#include "kitmanager.h"
#include "project.h"
#include "projectexplorer.h"
#include "projectpanelfactory.h"
#include "session.h"
#include "target.h"

#include <coreplugin/idocument.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>

#include <QStackedWidget>
#include <QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
///
// ProjectWindow
///

ProjectWindow::ProjectWindow(QWidget *parent)
    : QWidget(parent),
      m_ignoreChange(false),
      m_currentWidget(0)
{
    // Setup overall layout:
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);

    m_tabWidget = new DoubleTabWidget(this);
    viewLayout->addWidget(m_tabWidget);

    // Setup our container for the contents:
    m_centralWidget = new QStackedWidget(this);
    viewLayout->addWidget(m_centralWidget);

    // Connections
    connect(m_tabWidget, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(showProperties(int,int)));

    QObject *sessionManager = SessionManager::instance();
    connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
            this, SLOT(registerProject(ProjectExplorer::Project*)));
    connect(sessionManager, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
            this, SLOT(deregisterProject(ProjectExplorer::Project*)));

    connect(sessionManager, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project*)));

    connect(sessionManager, SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)),
            this, SLOT(projectDisplayNameChanged(ProjectExplorer::Project*)));

    // Update properties to empty project for now:
    showProperties(-1, -1);
}

ProjectWindow::~ProjectWindow()
{
}

void ProjectWindow::aboutToShutdown()
{
    showProperties(-1, -1); // that's a bit stupid, but otherwise stuff is still
                            // connected to the session
    m_cache.clear();
    disconnect(KitManager::instance(), 0, this, 0);
    disconnect(SessionManager::instance(), 0, this, 0);
}

void ProjectWindow::removedTarget(Target *)
{
    Project *p = qobject_cast<Project *>(sender());
    QTC_ASSERT(p, return);
    if (p->targets().isEmpty())
        projectUpdated(p);
}

void ProjectWindow::projectUpdated(Project *project)
{
    // Called after a project was configured
    int currentIndex = m_tabWidget->currentIndex();
    int oldSubIndex = m_tabWidget->currentSubIndex();

    removeCurrentWidget();

    int newSubIndex = m_cache.recheckFactories(project, oldSubIndex);
    if (newSubIndex == -1)
        newSubIndex = 0;
    m_tabWidget->setSubTabs(currentIndex, m_cache.tabNames(project));
    m_ignoreChange = true;
    m_tabWidget->setCurrentIndex(currentIndex, newSubIndex);
    m_ignoreChange = false;

    QWidget *widget = m_cache.widgetFor(project, newSubIndex);
    if (widget) {
        m_currentWidget = widget;
        m_centralWidget->addWidget(m_currentWidget);
        m_centralWidget->setCurrentWidget(m_currentWidget);
        m_currentWidget->show();
    }
}

void ProjectWindow::projectDisplayNameChanged(Project *project)
{
    int index = m_cache.indexForProject(project);
    if (index < 0)
        return;

    m_ignoreChange = true;
    bool isCurrentIndex = m_tabWidget->currentIndex() == index;
    int subIndex = m_tabWidget->currentSubIndex();
    QStringList subTabs = m_tabWidget->subTabs(index);
    m_tabWidget->removeTab(index);

    m_cache.sort();

    int newIndex = m_cache.indexForProject(project);
    m_tabWidget->insertTab(newIndex, project->displayName(), project->projectFilePath().toString(), subTabs);

    if (isCurrentIndex)
        m_tabWidget->setCurrentIndex(newIndex, subIndex);
    m_ignoreChange = false;
}

void ProjectWindow::registerProject(ProjectExplorer::Project *project)
{
    if (m_cache.isRegistered(project))
        return;

    m_cache.registerProject(project);
    m_tabWidget->insertTab(m_cache.indexForProject(project),
                           project->displayName(),
                           project->projectFilePath().toString(),
                           m_cache.tabNames(project));

    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            this, SLOT(removedTarget(ProjectExplorer::Target*)));
}

bool ProjectWindow::deregisterProject(ProjectExplorer::Project *project)
{
    int index = m_cache.indexForProject(project);
    if (index == -1)
        return false;

    QVector<QWidget *> deletedWidgets = m_cache.deregisterProject(project);
    if (deletedWidgets.contains(m_currentWidget))
        m_currentWidget = 0;

    m_tabWidget->removeTab(index);
    disconnect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            this, SLOT(removedTarget(ProjectExplorer::Target*)));
    return true;
}

void ProjectWindow::startupProjectChanged(ProjectExplorer::Project *p)
{
    int index = m_cache.indexForProject(p);
    if (index != -1)
        m_tabWidget->setCurrentIndex(index);
}

void ProjectWindow::showProperties(int index, int subIndex)
{
    if (m_ignoreChange)
        return;

    removeCurrentWidget();
    Project *project = m_cache.projectFor(index);
    if (!project) {
        return;
    }

    QWidget *widget = m_cache.widgetFor(project, subIndex);
    if (widget) {
        m_currentWidget = widget;
        m_centralWidget->addWidget(m_currentWidget);
        m_centralWidget->setCurrentWidget(m_currentWidget);
        m_currentWidget->show();
        if (hasFocus()) // we get assigned focus from setFocusToCurrentMode, pass that on
            m_currentWidget->setFocus();
    }

    SessionManager::setStartupProject(project);
}

void ProjectWindow::removeCurrentWidget()
{
    if (m_currentWidget) {
        m_centralWidget->removeWidget(m_currentWidget);
        m_currentWidget->hide();
        m_currentWidget = 0;
    }
}

// WidgetCache
void WidgetCache::registerProject(Project *project)
{
    QTC_ASSERT(!isRegistered(project), return);

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int factorySize = fac.size();

    ProjectInfo info;
    info.project = project;
    info.widgets.resize(factorySize);
    info.supports.resize(factorySize);

    for (int i = 0; i < factorySize; ++i)
        info.supports[i] = fac.at(i)->supports(project);

    m_projects.append(info);
    sort();
}

QVector<QWidget *> WidgetCache::deregisterProject(Project *project)
{
    QTC_ASSERT(isRegistered(project), return QVector<QWidget *>());

    int index = indexForProject(project);
    ProjectInfo info = m_projects.at(index);
    QVector<QWidget *> deletedWidgets = info.widgets;
    qDeleteAll(info.widgets);
    m_projects.removeAt(index);
    return deletedWidgets;
}

QStringList WidgetCache::tabNames(Project *project) const
{
    int index = indexForProject(project);
    if (index == -1)
        return QStringList();

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();

    ProjectInfo info = m_projects.at(index);
    int end = info.supports.size();
    QStringList names;
    for (int i = 0; i < end; ++i)
        if (info.supports.at(i))
            names << fac.at(i)->displayName();
    return names;
}

int WidgetCache::factoryIndex(int projectIndex, int supportsIndex) const
{
    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int end = fac.size();
    const ProjectInfo &info = m_projects.at(projectIndex);
    for (int i = 0; i < end; ++i) {
        if (info.supports.at(i)) {
            if (supportsIndex == 0)
                return i;
            else
                --supportsIndex;
        }
    }
    return -1;
}

QWidget *WidgetCache::widgetFor(Project *project, int supportsIndex)
{
    int projectIndex = indexForProject(project);
    if (projectIndex == -1)
        return 0;

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();

    int factoryIndex = factoryIndex(projectIndex, supportsIndex);
    if (factoryIndex < 0 ||factoryIndex >= m_projects.at(projectIndex).widgets.size())
        return 0;
    if (!m_projects.at(projectIndex).widgets.at(factoryIndex))
        m_projects[projectIndex].widgets[factoryIndex] = fac.at(factoryIndex)->createWidget(project);
    return m_projects.at(projectIndex).widgets.at(factoryIndex);
}

bool WidgetCache::isRegistered(Project *project) const
{
    return Utils::anyOf(m_projects, [&project](ProjectInfo pinfo) {
        return pinfo.project == project;
    });
}

int WidgetCache::indexForProject(Project *project) const
{
    return Utils::indexOf(m_projects, [&project](ProjectInfo pinfo) {
        return pinfo.project == project;
    });
}

Project *WidgetCache::projectFor(int projectIndex) const
{
    if (projectIndex < 0)
        return 0;
    if (projectIndex >= m_projects.size())
        return 0;
    return m_projects.at(projectIndex).project;
}

void WidgetCache::sort()
{
    Utils::sort(m_projects, [](const ProjectInfo &a, const ProjectInfo &b) -> bool {
        QString aName = a.project->displayName();
        QString bName = b.project->displayName();
        if (aName == bName) {
            Utils::FileName aPath = a.project->projectFilePath();
            Utils::FileName bPath = b.project->projectFilePath();
            if (aPath == bPath)
                return a.project < b.project;
            else
                return aPath < bPath;
        } else {
            return aName < bName;
        }

    });
}

int WidgetCache::recheckFactories(Project *project, int oldSupportsIndex)
{
    int projectIndex = indexForProject(project);
    int factoryIndex = factoryIndex(projectIndex, oldSupportsIndex);

    ProjectInfo &info = m_projects[projectIndex];
    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int end = fac.size();

    for (int i = 0; i < end; ++i) {
        info.supports[i] = fac.at(i)->supports(project);
        if (!info.supports.at(i)) {
            delete info.widgets.at(i);
            info.widgets[i] = 0;
        }
    }

    if (factoryIndex < 0)
        return -1;

    if (!info.supports.at(factoryIndex))
        return -1;

    int newIndex = 0;
    for (int i = 0; i < factoryIndex; ++i) {
        if (info.supports.at(i))
            ++newIndex;
    }
    return newIndex;
}

void WidgetCache::clear()
{
    while (!m_projects.isEmpty())
        deregisterProject(m_projects.first().project);
}
<commit_msg>Fix compile<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "projectwindow.h"

#include "doubletabwidget.h"
#include "panelswidget.h"
#include "kitmanager.h"
#include "project.h"
#include "projectexplorer.h"
#include "projectpanelfactory.h"
#include "session.h"
#include "target.h"

#include <coreplugin/idocument.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>

#include <QStackedWidget>
#include <QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
///
// ProjectWindow
///

ProjectWindow::ProjectWindow(QWidget *parent)
    : QWidget(parent),
      m_ignoreChange(false),
      m_currentWidget(0)
{
    // Setup overall layout:
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);

    m_tabWidget = new DoubleTabWidget(this);
    viewLayout->addWidget(m_tabWidget);

    // Setup our container for the contents:
    m_centralWidget = new QStackedWidget(this);
    viewLayout->addWidget(m_centralWidget);

    // Connections
    connect(m_tabWidget, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(showProperties(int,int)));

    QObject *sessionManager = SessionManager::instance();
    connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
            this, SLOT(registerProject(ProjectExplorer::Project*)));
    connect(sessionManager, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
            this, SLOT(deregisterProject(ProjectExplorer::Project*)));

    connect(sessionManager, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project*)));

    connect(sessionManager, SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)),
            this, SLOT(projectDisplayNameChanged(ProjectExplorer::Project*)));

    // Update properties to empty project for now:
    showProperties(-1, -1);
}

ProjectWindow::~ProjectWindow()
{
}

void ProjectWindow::aboutToShutdown()
{
    showProperties(-1, -1); // that's a bit stupid, but otherwise stuff is still
                            // connected to the session
    m_cache.clear();
    disconnect(KitManager::instance(), 0, this, 0);
    disconnect(SessionManager::instance(), 0, this, 0);
}

void ProjectWindow::removedTarget(Target *)
{
    Project *p = qobject_cast<Project *>(sender());
    QTC_ASSERT(p, return);
    if (p->targets().isEmpty())
        projectUpdated(p);
}

void ProjectWindow::projectUpdated(Project *project)
{
    // Called after a project was configured
    int currentIndex = m_tabWidget->currentIndex();
    int oldSubIndex = m_tabWidget->currentSubIndex();

    removeCurrentWidget();

    int newSubIndex = m_cache.recheckFactories(project, oldSubIndex);
    if (newSubIndex == -1)
        newSubIndex = 0;
    m_tabWidget->setSubTabs(currentIndex, m_cache.tabNames(project));
    m_ignoreChange = true;
    m_tabWidget->setCurrentIndex(currentIndex, newSubIndex);
    m_ignoreChange = false;

    QWidget *widget = m_cache.widgetFor(project, newSubIndex);
    if (widget) {
        m_currentWidget = widget;
        m_centralWidget->addWidget(m_currentWidget);
        m_centralWidget->setCurrentWidget(m_currentWidget);
        m_currentWidget->show();
    }
}

void ProjectWindow::projectDisplayNameChanged(Project *project)
{
    int index = m_cache.indexForProject(project);
    if (index < 0)
        return;

    m_ignoreChange = true;
    bool isCurrentIndex = m_tabWidget->currentIndex() == index;
    int subIndex = m_tabWidget->currentSubIndex();
    QStringList subTabs = m_tabWidget->subTabs(index);
    m_tabWidget->removeTab(index);

    m_cache.sort();

    int newIndex = m_cache.indexForProject(project);
    m_tabWidget->insertTab(newIndex, project->displayName(), project->projectFilePath().toString(), subTabs);

    if (isCurrentIndex)
        m_tabWidget->setCurrentIndex(newIndex, subIndex);
    m_ignoreChange = false;
}

void ProjectWindow::registerProject(ProjectExplorer::Project *project)
{
    if (m_cache.isRegistered(project))
        return;

    m_cache.registerProject(project);
    m_tabWidget->insertTab(m_cache.indexForProject(project),
                           project->displayName(),
                           project->projectFilePath().toString(),
                           m_cache.tabNames(project));

    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            this, SLOT(removedTarget(ProjectExplorer::Target*)));
}

bool ProjectWindow::deregisterProject(ProjectExplorer::Project *project)
{
    int index = m_cache.indexForProject(project);
    if (index == -1)
        return false;

    QVector<QWidget *> deletedWidgets = m_cache.deregisterProject(project);
    if (deletedWidgets.contains(m_currentWidget))
        m_currentWidget = 0;

    m_tabWidget->removeTab(index);
    disconnect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            this, SLOT(removedTarget(ProjectExplorer::Target*)));
    return true;
}

void ProjectWindow::startupProjectChanged(ProjectExplorer::Project *p)
{
    int index = m_cache.indexForProject(p);
    if (index != -1)
        m_tabWidget->setCurrentIndex(index);
}

void ProjectWindow::showProperties(int index, int subIndex)
{
    if (m_ignoreChange)
        return;

    removeCurrentWidget();
    Project *project = m_cache.projectFor(index);
    if (!project) {
        return;
    }

    QWidget *widget = m_cache.widgetFor(project, subIndex);
    if (widget) {
        m_currentWidget = widget;
        m_centralWidget->addWidget(m_currentWidget);
        m_centralWidget->setCurrentWidget(m_currentWidget);
        m_currentWidget->show();
        if (hasFocus()) // we get assigned focus from setFocusToCurrentMode, pass that on
            m_currentWidget->setFocus();
    }

    SessionManager::setStartupProject(project);
}

void ProjectWindow::removeCurrentWidget()
{
    if (m_currentWidget) {
        m_centralWidget->removeWidget(m_currentWidget);
        m_currentWidget->hide();
        m_currentWidget = 0;
    }
}

// WidgetCache
void WidgetCache::registerProject(Project *project)
{
    QTC_ASSERT(!isRegistered(project), return);

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int factorySize = fac.size();

    ProjectInfo info;
    info.project = project;
    info.widgets.resize(factorySize);
    info.supports.resize(factorySize);

    for (int i = 0; i < factorySize; ++i)
        info.supports[i] = fac.at(i)->supports(project);

    m_projects.append(info);
    sort();
}

QVector<QWidget *> WidgetCache::deregisterProject(Project *project)
{
    QTC_ASSERT(isRegistered(project), return QVector<QWidget *>());

    int index = indexForProject(project);
    ProjectInfo info = m_projects.at(index);
    QVector<QWidget *> deletedWidgets = info.widgets;
    qDeleteAll(info.widgets);
    m_projects.removeAt(index);
    return deletedWidgets;
}

QStringList WidgetCache::tabNames(Project *project) const
{
    int index = indexForProject(project);
    if (index == -1)
        return QStringList();

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();

    ProjectInfo info = m_projects.at(index);
    int end = info.supports.size();
    QStringList names;
    for (int i = 0; i < end; ++i)
        if (info.supports.at(i))
            names << fac.at(i)->displayName();
    return names;
}

int WidgetCache::factoryIndex(int projectIndex, int supportsIndex) const
{
    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int end = fac.size();
    const ProjectInfo &info = m_projects.at(projectIndex);
    for (int i = 0; i < end; ++i) {
        if (info.supports.at(i)) {
            if (supportsIndex == 0)
                return i;
            else
                --supportsIndex;
        }
    }
    return -1;
}

QWidget *WidgetCache::widgetFor(Project *project, int supportsIndex)
{
    int projectIndex = indexForProject(project);
    if (projectIndex == -1)
        return 0;

    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();

    int factoryIdx = factoryIndex(projectIndex, supportsIndex);
    if (factoryIdx < 0 ||factoryIdx >= m_projects.at(projectIndex).widgets.size())
        return 0;
    if (!m_projects.at(projectIndex).widgets.at(factoryIdx))
        m_projects[projectIndex].widgets[factoryIdx] = fac.at(factoryIdx)->createWidget(project);
    return m_projects.at(projectIndex).widgets.at(factoryIdx);
}

bool WidgetCache::isRegistered(Project *project) const
{
    return Utils::anyOf(m_projects, [&project](ProjectInfo pinfo) {
        return pinfo.project == project;
    });
}

int WidgetCache::indexForProject(Project *project) const
{
    return Utils::indexOf(m_projects, [&project](ProjectInfo pinfo) {
        return pinfo.project == project;
    });
}

Project *WidgetCache::projectFor(int projectIndex) const
{
    if (projectIndex < 0)
        return 0;
    if (projectIndex >= m_projects.size())
        return 0;
    return m_projects.at(projectIndex).project;
}

void WidgetCache::sort()
{
    Utils::sort(m_projects, [](const ProjectInfo &a, const ProjectInfo &b) -> bool {
        QString aName = a.project->displayName();
        QString bName = b.project->displayName();
        if (aName == bName) {
            Utils::FileName aPath = a.project->projectFilePath();
            Utils::FileName bPath = b.project->projectFilePath();
            if (aPath == bPath)
                return a.project < b.project;
            else
                return aPath < bPath;
        } else {
            return aName < bName;
        }

    });
}

int WidgetCache::recheckFactories(Project *project, int oldSupportsIndex)
{
    int projectIndex = indexForProject(project);
    int factoryIdx = factoryIndex(projectIndex, oldSupportsIndex);

    ProjectInfo &info = m_projects[projectIndex];
    QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
    int end = fac.size();

    for (int i = 0; i < end; ++i) {
        info.supports[i] = fac.at(i)->supports(project);
        if (!info.supports.at(i)) {
            delete info.widgets.at(i);
            info.widgets[i] = 0;
        }
    }

    if (factoryIdx < 0)
        return -1;

    if (!info.supports.at(factoryIdx))
        return -1;

    int newIndex = 0;
    for (int i = 0; i < factoryIdx; ++i) {
        if (info.supports.at(i))
            ++newIndex;
    }
    return newIndex;
}

void WidgetCache::clear()
{
    while (!m_projects.isEmpty())
        deregisterProject(m_projects.first().project);
}
<|endoftext|>


<commit_before>//
//
//

#include "MicroTasksTask.h"
#include "MicroTasksEvent.h"
#include "MicroTasksAlarm.h"
#include "MicroTasks.h"

#include "debug.h"

using namespace MicroTasks;

uint32_t MicroTasksClass::WaitForEvent = (1 << 31);
uint32_t MicroTasksClass::WaitForMessage = (1 << 30);

uint32_t MicroTasksClass::WaitForMask = MicroTasksClass::WaitForEvent | WaitForMessage;

uint32_t MicroTasksClass::Infinate = ~MicroTasksClass::WaitForMask;

MicroTasksClass::MicroTasksClass()
{
}

void MicroTasksClass::init()
{
}

uint32_t MicroTasksClass::update()
{
  uint32_t uiNextEvent = 0xFFFFFFFF;

  // Any events triggered?
  Event *oNextEvent;
  for (Event *oEvent = (Event *)Event::oEvents.GetFirst(); oEvent; oEvent = oNextEvent)
  {
    oNextEvent = (Event *)oEvent->GetNext();

    if (oEvent->triggered)
    {
      EventListener *oNextEventListener;
      for (EventListener *oEventListener = (EventListener *)(oEvent->oClients.GetFirst()); oEventListener; oEventListener = oNextEventListener)
      {
        // Keep a pointer to the next task in case this on is stopped
        oNextEventListener = (EventListener *)(oEventListener->GetNext());
        oEventListener->triggered = 1;
        wakeTask(oEventListener->GetTask(), WakeReason_Event);
        oEventListener->triggered = 0;
      }

      oEvent->triggered = 0;
    }
  }

  // Any alarms triggered?
  Alarm *oNextAlarm;
  for (Alarm *oAlarm = (Alarm *)Alarm::oAlarms.GetFirst(); oAlarm; oAlarm = oNextAlarm)
  {
    oNextAlarm = (Alarm *)oAlarm->GetNext();
    if(millis() >= oAlarm->uiTime)
    {
      oAlarm->Trigger();
      if(oAlarm->bRepeat) {
        oAlarm->Reset();
      } else {
        oAlarm->Clear();
      }
    }

    if(oAlarm->IsValid() && oAlarm->uiTime < uiNextEvent) {
      uiNextEvent = oAlarm->uiTime;
    }
  }

  // Any tasks waiting to be woken
  Task *oNextTask;
  for (Task *oTask = (Task *)oTasks.GetFirst(); oTask; oTask = oNextTask)
  {
    // Keep a pointer to the next task in case this one is stopped
    oNextTask = (Task *)oTask->GetNext();
    if (oTask->ulNextLoop <= millis()) {
      wakeTask(oTask, WakeReason_Scheduled);
    }
    if(oTask->IsValid() && oTask->ulNextLoop < uiNextEvent) {
      uiNextEvent = oTask->ulNextLoop;
    }
  }

  DEBUG_PORT.flush();
  return uiNextEvent;
}

void MicroTasksClass::wakeTask(Task *oTask, WakeReason eReason)
{
  DBUG(millis());
  DBUG(": W ");
  DBUG((unsigned int)oTask);
  DBUG(" [");
  DBUG((int)eReason);
  DBUG("] -> ");

#ifdef ENABLE_DEBUG_MICROTASKS
  uint32_t ulStart = micros();
#endif
  uint32_t ulDelay = oTask->loop(eReason);
  DBUG(micros() - ulStart);
  DBUG(":");
  uint32_t ulNext = ulDelay & ~MicroTask.WaitForMask;

  oTask->uiFlags = ulDelay & MicroTask.WaitForMask;
  if (MicroTask.Infinate == ulNext) {
    oTask->ulNextLoop = 0xFFFFFFFF;
    DBUGLN("Forever");
  } else {
    oTask->ulNextLoop = millis() + ulNext;
    DBUG(ulNext);
    DBUG(":");
    DBUGLN(oTask->ulNextLoop);
  }
}

void MicroTasksClass::startTask(Task *oTask)
{
  oTasks.Add(oTask);
  oTask->setup();
}

void MicroTasksClass::stopTask(Task *oTask)
{
  oTasks.Remove(oTask);
  oTask->ulNextLoop = 0xFFFFFFFF;
}

MicroTasksClass MicroTask;
<commit_msg>In some Arduino cores (<1.0?) flush clears the Rx buffer this change attempts to limit the impact of this by only calling flush if debug is enabed.<commit_after>//
//
//

#include "MicroTasksTask.h"
#include "MicroTasksEvent.h"
#include "MicroTasksAlarm.h"
#include "MicroTasks.h"

#include "debug.h"

using namespace MicroTasks;

uint32_t MicroTasksClass::WaitForEvent = (1 << 31);
uint32_t MicroTasksClass::WaitForMessage = (1 << 30);

uint32_t MicroTasksClass::WaitForMask = MicroTasksClass::WaitForEvent | WaitForMessage;

uint32_t MicroTasksClass::Infinate = ~MicroTasksClass::WaitForMask;

MicroTasksClass::MicroTasksClass()
{
}

void MicroTasksClass::init()
{
}

uint32_t MicroTasksClass::update()
{
  uint32_t uiNextEvent = 0xFFFFFFFF;

  // Any events triggered?
  Event *oNextEvent;
  for (Event *oEvent = (Event *)Event::oEvents.GetFirst(); oEvent; oEvent = oNextEvent)
  {
    oNextEvent = (Event *)oEvent->GetNext();

    if (oEvent->triggered)
    {
      EventListener *oNextEventListener;
      for (EventListener *oEventListener = (EventListener *)(oEvent->oClients.GetFirst()); oEventListener; oEventListener = oNextEventListener)
      {
        // Keep a pointer to the next task in case this on is stopped
        oNextEventListener = (EventListener *)(oEventListener->GetNext());
        oEventListener->triggered = 1;
        wakeTask(oEventListener->GetTask(), WakeReason_Event);
        oEventListener->triggered = 0;
      }

      oEvent->triggered = 0;
    }
  }

  // Any alarms triggered?
  Alarm *oNextAlarm;
  for (Alarm *oAlarm = (Alarm *)Alarm::oAlarms.GetFirst(); oAlarm; oAlarm = oNextAlarm)
  {
    oNextAlarm = (Alarm *)oAlarm->GetNext();
    if(millis() >= oAlarm->uiTime)
    {
      oAlarm->Trigger();
      if(oAlarm->bRepeat) {
        oAlarm->Reset();
      } else {
        oAlarm->Clear();
      }
    }

    if(oAlarm->IsValid() && oAlarm->uiTime < uiNextEvent) {
      uiNextEvent = oAlarm->uiTime;
    }
  }

  // Any tasks waiting to be woken
  Task *oNextTask;
  for (Task *oTask = (Task *)oTasks.GetFirst(); oTask; oTask = oNextTask)
  {
    // Keep a pointer to the next task in case this one is stopped
    oNextTask = (Task *)oTask->GetNext();
    if (oTask->ulNextLoop <= millis()) {
      wakeTask(oTask, WakeReason_Scheduled);
    }
    if(oTask->IsValid() && oTask->ulNextLoop < uiNextEvent) {
      uiNextEvent = oTask->ulNextLoop;
    }
  }

#ifdef ENABLE_DEBUG_MICROTASKS
  DEBUG_PORT.flush();
#endif
  return uiNextEvent;
}

void MicroTasksClass::wakeTask(Task *oTask, WakeReason eReason)
{
  DBUG(millis());
  DBUG(": W ");
  DBUG((unsigned int)oTask);
  DBUG(" [");
  DBUG((int)eReason);
  DBUG("] -> ");

#ifdef ENABLE_DEBUG_MICROTASKS
  uint32_t ulStart = micros();
#endif
  uint32_t ulDelay = oTask->loop(eReason);
  DBUG(micros() - ulStart);
  DBUG(":");
  uint32_t ulNext = ulDelay & ~MicroTask.WaitForMask;

  oTask->uiFlags = ulDelay & MicroTask.WaitForMask;
  if (MicroTask.Infinate == ulNext) {
    oTask->ulNextLoop = 0xFFFFFFFF;
    DBUGLN("Forever");
  } else {
    oTask->ulNextLoop = millis() + ulNext;
    DBUG(ulNext);
    DBUG(":");
    DBUGLN(oTask->ulNextLoop);
  }
}

void MicroTasksClass::startTask(Task *oTask)
{
  oTasks.Add(oTask);
  oTask->setup();
}

void MicroTasksClass::stopTask(Task *oTask)
{
  oTasks.Remove(oTask);
  oTask->ulNextLoop = 0xFFFFFFFF;
}

MicroTasksClass MicroTask;
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * 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
 */

#define _PCREPOSIX_H // avoid pcreposix.h conflict with regex.h used by gtest
#include <gtest/gtest.h>

#include "se_handler.h"
#include "query_context.h"
#include "websearch.h"
#include "websearch_configuration.h"
#include "miscutil.h"
#include "errlog.h"

using namespace seeks_plugins;
using sp::miscutil;
using sp::errlog;

class SEHandlerTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
      errlog::init_log_module();
      errlog::set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO | LOG_LEVEL_DEBUG);
    }
};

TEST_F(SEHandlerTest,query_to_ses_fail_no_engine)
{
  feeds engines;
  hash_map<const char*,const char*,hash<const char*>,eqstr> parameters;
  int nresults = 0;
  query_context *qc = NULL;
  std::string **output = NULL;
  int code = SP_ERR_OK;
  try
    {
      output = se_handler::query_to_ses(&parameters,nresults,qc,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
  parameters.clear();
}

TEST_F(SEHandlerTest,query_to_ses_fail_connect)
{
  feeds engines("dummy","url1");
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>(2);
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"",1);
  websearch::_wconfig = new websearch_configuration("");
  websearch::_wconfig->_se_connect_timeout = 1;
  websearch::_wconfig->_se_transfer_timeout = 1;
  ASSERT_TRUE(NULL!=websearch::_wconfig);
  int nresults = 0;
  query_context qc;
  std::string **output = NULL;
  int code = SP_ERR_OK;
  try
    {
      output = se_handler::query_to_ses(parameters,nresults,&qc,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
  delete websearch::_wconfig;
  miscutil::free_map(parameters);
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>fixed cleanup of curl handlers in se_handler unit test<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * 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
 */

#define _PCREPOSIX_H // avoid pcreposix.h conflict with regex.h used by gtest
#include <gtest/gtest.h>

#include "se_handler.h"
#include "query_context.h"
#include "websearch.h"
#include "websearch_configuration.h"
#include "miscutil.h"
#include "errlog.h"

using namespace seeks_plugins;
using sp::miscutil;
using sp::errlog;

class SEHandlerTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
      errlog::init_log_module();
      errlog::set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO | LOG_LEVEL_DEBUG);
    }
};

TEST_F(SEHandlerTest,query_to_ses_fail_no_engine)
{
  feeds engines;
  hash_map<const char*,const char*,hash<const char*>,eqstr> parameters;
  int nresults = 0;
  query_context *qc = NULL;
  std::string **output = NULL;
  int code = SP_ERR_OK;
  try
    {
      output = se_handler::query_to_ses(&parameters,nresults,qc,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
  parameters.clear();
  se_handler::cleanup_handlers();
}

TEST_F(SEHandlerTest,query_to_ses_fail_connect)
{
  feeds engines("dummy","url1");
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>(2);
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"",1);
  websearch::_wconfig = new websearch_configuration("");
  websearch::_wconfig->_se_connect_timeout = 1;
  websearch::_wconfig->_se_transfer_timeout = 1;
  ASSERT_TRUE(NULL!=websearch::_wconfig);
  int nresults = 0;
  query_context qc;
  std::string **output = NULL;
  int code = SP_ERR_OK;
  try
    {
      output = se_handler::query_to_ses(parameters,nresults,&qc,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
  delete websearch::_wconfig;
  miscutil::free_map(parameters);
  se_handler::cleanup_handlers();
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>