<commit_before>// Copyright 2008-2010 Sergiu Dotenco. The License.txt file describes the
// conditions under which this software may be distributed.

/**
 * @file LexBibTeX.cxx
 * @brief General BibTeX coloring scheme.
 * @author Sergiu Dotenco
 * @date April 18, 2009
 */

#include <stdlib.h>
#include <string.h>

#include <cassert>
#include <cctype>

#include <string>
#include <algorithm>
#include <functional>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

namespace {
	bool IsAlphabetic(unsigned int ch)
	{
		return IsASCII(ch) && std::isalpha(ch) != 0;
	}
	bool IsAlphaNumeric(char ch)
	{
	    return IsASCII(ch) && std::isalnum(ch);
	}

	bool EqualCaseInsensitive(const char* a, const char* b)
	{
		return CompareCaseInsensitive(a, b) == 0;
	}

	bool EntryWithoutKey(const char* name)
	{
		return EqualCaseInsensitive(name,"string");
	}

	char GetClosingBrace(char openbrace)
	{
		char result = openbrace;

		switch (openbrace) {
			case '(': result = ')'; break;
			case '{': result = '}'; break;
		}

		return result;
	}

	bool IsEntryStart(char prev, char ch)
	{
		return prev != '\\' && ch == '@';
	}

	bool IsEntryStart(const StyleContext& sc)
	{
		return IsEntryStart(sc.chPrev, sc.ch);
	}

	bool IsNextEntryStart(const StyleContext& sc)
	{
		return IsEntryStart(sc.ch, sc.chNext);
	}

	void ColorizeBibTeX(unsigned start_pos, int length, int /*init_style*/, WordList* keywordlists[], Accessor& styler)
	{
	    WordList &EntryNames = *keywordlists[0];
		bool fold_compact = styler.GetPropertyInt("fold.compact", 1) != 0;

		std::string buffer;
		buffer.reserve(25);

		// We always colorize a section from the beginning, so let's
		// search for the @ character which isn't escaped, i.e. \@
		while (start_pos > 0 && !IsEntryStart(styler.SafeGetCharAt(start_pos - 1),
			styler.SafeGetCharAt(start_pos))) {
			--start_pos; ++length;
		}

		styler.StartAt(start_pos);
		styler.StartSegment(start_pos);

		int current_line = styler.GetLine(start_pos);
		int prev_level = styler.LevelAt(current_line) & SC_FOLDLEVELNUMBERMASK;
		int current_level = prev_level;
		int visible_chars = 0;

		bool in_comment = false ;
		StyleContext sc(start_pos, length, SCE_BIBTEX_DEFAULT, styler);

		bool going = sc.More(); // needed because of a fuzzy end of file state
		char closing_brace = 0;
		bool collect_entry_name = false;

		for (; going; sc.Forward()) {
			if (!sc.More())
				going = false; // we need to go one behind the end of text

			if (in_comment) {
				if (sc.atLineEnd) {
					sc.SetState(SCE_BIBTEX_DEFAULT);
					in_comment = false;
				}
			}
			else {
				// Found @entry
				if (IsEntryStart(sc)) {
					sc.SetState(SCE_BIBTEX_UNKNOWN_ENTRY);
					sc.Forward();
					++current_level;

					buffer.clear();
					collect_entry_name = true;
				}
				else if ((sc.state == SCE_BIBTEX_ENTRY || sc.state == SCE_BIBTEX_UNKNOWN_ENTRY)
					&& (sc.ch == '{' || sc.ch == '(')) {
					// Entry name colorization done
					// Found either a { or a ( after entry's name, e.g. @entry(...) @entry{...}
					// Closing counterpart needs to be stored.
					closing_brace = GetClosingBrace(sc.ch);

					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize { (

					// @string doesn't have any key
					if (EntryWithoutKey(buffer.c_str()))
						sc.ForwardSetState(SCE_BIBTEX_PARAMETER);
					else
						sc.ForwardSetState(SCE_BIBTEX_KEY); // Key/label colorization
				}

				// Need to handle the case where entry's key is empty
				// e.g. @book{,...}
				if (sc.state == SCE_BIBTEX_KEY && sc.ch == ',') {
					// Key/label colorization done
					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the ,
					sc.ForwardSetState(SCE_BIBTEX_PARAMETER); // Parameter colorization
				}
				else if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == '=') {
					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the =
					sc.ForwardSetState(SCE_BIBTEX_VALUE); // Parameter value colorization

					int start = sc.currentPos;

					// We need to handle multiple situations:
					// 1. name"one two {three}"
					// 2. name={one {one two {two}} three}
					// 3. year=2005

					// Skip ", { until we encounter the first alphanumerical character
					while (sc.More() && !(IsAlphaNumeric(sc.ch) || sc.ch == '"' || sc.ch == '{'))
						sc.Forward();

					if (sc.More()) {
						// Store " or {
						char ch = sc.ch;

						// Not interested in alphanumerical characters
						if (IsAlphaNumeric(ch))
							ch = 0;

						int skipped = 0;

						if (ch) {
							// Skip preceding " or { such as in name={{test}}.
							// Remember how many characters have been skipped
							// Make sure that empty values, i.e. "" are also handled correctly
							while (sc.More() && (sc.ch == ch && (ch != '"' || skipped < 1))) {
								sc.Forward();
								++skipped;
							}
						}

						// Closing counterpart for " is the same character
						if (ch == '{')
							ch = '}';

						// We have reached the parameter value
						// In case the open character was a alnum char, skip until , is found
						// otherwise until skipped == 0
						while (sc.More() && (skipped > 0 || (!ch && !(sc.ch == ',' || sc.ch == closing_brace)))) {
							// Make sure the character isn't escaped
							if (sc.chPrev != '\\') {
								// Parameter value contains a { which is the 2nd case described above
								if (sc.ch == '{')
									++skipped; // Remember it
								else if (sc.ch == '}')
									--skipped;
								else if (skipped == 1 && sc.ch == ch && ch == '"') // Don't ignore cases like {"o}
									skipped = 0;
							}

							sc.Forward();
						}
					}

					// Don't colorize the ,
					sc.SetState(SCE_BIBTEX_DEFAULT);

					// Skip until the , or entry's closing closing_brace is found
					// since this parameter might be the last one
					while (sc.More() && !(sc.ch == ',' || sc.ch == closing_brace))
						sc.Forward();

					int state = SCE_BIBTEX_PARAMETER; // The might be more parameters

					// We've reached the closing closing_brace for the bib entry
					// in case no " or {} has been used to enclose the value,
					// as in 3rd case described above
					if (sc.ch == closing_brace) {
						--current_level;
						// Make sure the text between entries is not colored
						// using parameter's style
						state = SCE_BIBTEX_DEFAULT;
					}

					int end = sc.currentPos;
					current_line = styler.GetLine(end);

					// We have possibly skipped some lines, so the folding levels
					// have to be adjusted separately
					for (int i = styler.GetLine(start); i <= styler.GetLine(end); ++i)
						styler.SetLevel(i, prev_level);

					sc.ForwardSetState(state);
				}

				if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == closing_brace) {
					sc.SetState(SCE_BIBTEX_DEFAULT);
					--current_level;
				}

				// Non escaped % found which represents a comment until the end of the line
				if (sc.chPrev != '\\' && sc.ch == '%') {
					in_comment = true;
					sc.SetState(SCE_BIBTEX_COMMENT);
				}
			}

			if (sc.state == SCE_BIBTEX_UNKNOWN_ENTRY || sc.state == SCE_BIBTEX_ENTRY) {
				if (!IsAlphabetic(sc.ch) && collect_entry_name)
					collect_entry_name = false;

				if (collect_entry_name) {
					buffer += static_cast<char>(tolower(sc.ch));
                    if (EntryNames.InList(buffer.c_str()))
                        sc.ChangeState(SCE_BIBTEX_ENTRY);
                    else
                        sc.ChangeState(SCE_BIBTEX_UNKNOWN_ENTRY);
				}
			}

			if (sc.atLineEnd) {
				int level = prev_level;

				if (visible_chars == 0 && fold_compact)
					level |= SC_FOLDLEVELWHITEFLAG;

				if ((current_level > prev_level))
					level |= SC_FOLDLEVELHEADERFLAG;
				// else if (current_level < prev_level)
				//	level |= SC_FOLDLEVELBOXFOOTERFLAG; // Deprecated

				if (level != styler.LevelAt(current_line)) {
					styler.SetLevel(current_line, level);
				}

				++current_line;
				prev_level = current_level;
				visible_chars = 0;
			}

			if (!isspacechar(sc.ch))
				++visible_chars;
		}

		sc.Complete();

		// Fill in the real level of the next line, keeping the current flags as they will be filled in later
		int flagsNext = styler.LevelAt(current_line) & ~SC_FOLDLEVELNUMBERMASK;
		styler.SetLevel(current_line, prev_level | flagsNext);
	}
}
static const char * const BibTeXWordLists[] = {
            "Entry Names",
            0,
};

LexerModule lmBibTeX(SCLEX_BIBTEX, ColorizeBibTeX, "bib", 0, BibTeXWordLists);

// Entry Names
//    article, book, booklet, conference, inbook,
//    incollection, inproceedings, manual, mastersthesis,
//    misc, phdthesis, proceedings, techreport, unpublished,
//    string, url

<commit_msg>Remove unused function.<commit_after>// Copyright 2008-2010 Sergiu Dotenco. The License.txt file describes the
// conditions under which this software may be distributed.

/**
 * @file LexBibTeX.cxx
 * @brief General BibTeX coloring scheme.
 * @author Sergiu Dotenco
 * @date April 18, 2009
 */

#include <stdlib.h>
#include <string.h>

#include <cassert>
#include <cctype>

#include <string>
#include <algorithm>
#include <functional>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

namespace {
	bool IsAlphabetic(unsigned int ch)
	{
		return IsASCII(ch) && std::isalpha(ch) != 0;
	}
	bool IsAlphaNumeric(char ch)
	{
	    return IsASCII(ch) && std::isalnum(ch);
	}

	bool EqualCaseInsensitive(const char* a, const char* b)
	{
		return CompareCaseInsensitive(a, b) == 0;
	}

	bool EntryWithoutKey(const char* name)
	{
		return EqualCaseInsensitive(name,"string");
	}

	char GetClosingBrace(char openbrace)
	{
		char result = openbrace;

		switch (openbrace) {
			case '(': result = ')'; break;
			case '{': result = '}'; break;
		}

		return result;
	}

	bool IsEntryStart(char prev, char ch)
	{
		return prev != '\\' && ch == '@';
	}

	bool IsEntryStart(const StyleContext& sc)
	{
		return IsEntryStart(sc.chPrev, sc.ch);
	}

	void ColorizeBibTeX(unsigned start_pos, int length, int /*init_style*/, WordList* keywordlists[], Accessor& styler)
	{
	    WordList &EntryNames = *keywordlists[0];
		bool fold_compact = styler.GetPropertyInt("fold.compact", 1) != 0;

		std::string buffer;
		buffer.reserve(25);

		// We always colorize a section from the beginning, so let's
		// search for the @ character which isn't escaped, i.e. \@
		while (start_pos > 0 && !IsEntryStart(styler.SafeGetCharAt(start_pos - 1),
			styler.SafeGetCharAt(start_pos))) {
			--start_pos; ++length;
		}

		styler.StartAt(start_pos);
		styler.StartSegment(start_pos);

		int current_line = styler.GetLine(start_pos);
		int prev_level = styler.LevelAt(current_line) & SC_FOLDLEVELNUMBERMASK;
		int current_level = prev_level;
		int visible_chars = 0;

		bool in_comment = false ;
		StyleContext sc(start_pos, length, SCE_BIBTEX_DEFAULT, styler);

		bool going = sc.More(); // needed because of a fuzzy end of file state
		char closing_brace = 0;
		bool collect_entry_name = false;

		for (; going; sc.Forward()) {
			if (!sc.More())
				going = false; // we need to go one behind the end of text

			if (in_comment) {
				if (sc.atLineEnd) {
					sc.SetState(SCE_BIBTEX_DEFAULT);
					in_comment = false;
				}
			}
			else {
				// Found @entry
				if (IsEntryStart(sc)) {
					sc.SetState(SCE_BIBTEX_UNKNOWN_ENTRY);
					sc.Forward();
					++current_level;

					buffer.clear();
					collect_entry_name = true;
				}
				else if ((sc.state == SCE_BIBTEX_ENTRY || sc.state == SCE_BIBTEX_UNKNOWN_ENTRY)
					&& (sc.ch == '{' || sc.ch == '(')) {
					// Entry name colorization done
					// Found either a { or a ( after entry's name, e.g. @entry(...) @entry{...}
					// Closing counterpart needs to be stored.
					closing_brace = GetClosingBrace(sc.ch);

					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize { (

					// @string doesn't have any key
					if (EntryWithoutKey(buffer.c_str()))
						sc.ForwardSetState(SCE_BIBTEX_PARAMETER);
					else
						sc.ForwardSetState(SCE_BIBTEX_KEY); // Key/label colorization
				}

				// Need to handle the case where entry's key is empty
				// e.g. @book{,...}
				if (sc.state == SCE_BIBTEX_KEY && sc.ch == ',') {
					// Key/label colorization done
					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the ,
					sc.ForwardSetState(SCE_BIBTEX_PARAMETER); // Parameter colorization
				}
				else if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == '=') {
					sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the =
					sc.ForwardSetState(SCE_BIBTEX_VALUE); // Parameter value colorization

					int start = sc.currentPos;

					// We need to handle multiple situations:
					// 1. name"one two {three}"
					// 2. name={one {one two {two}} three}
					// 3. year=2005

					// Skip ", { until we encounter the first alphanumerical character
					while (sc.More() && !(IsAlphaNumeric(sc.ch) || sc.ch == '"' || sc.ch == '{'))
						sc.Forward();

					if (sc.More()) {
						// Store " or {
						char ch = sc.ch;

						// Not interested in alphanumerical characters
						if (IsAlphaNumeric(ch))
							ch = 0;

						int skipped = 0;

						if (ch) {
							// Skip preceding " or { such as in name={{test}}.
							// Remember how many characters have been skipped
							// Make sure that empty values, i.e. "" are also handled correctly
							while (sc.More() && (sc.ch == ch && (ch != '"' || skipped < 1))) {
								sc.Forward();
								++skipped;
							}
						}

						// Closing counterpart for " is the same character
						if (ch == '{')
							ch = '}';

						// We have reached the parameter value
						// In case the open character was a alnum char, skip until , is found
						// otherwise until skipped == 0
						while (sc.More() && (skipped > 0 || (!ch && !(sc.ch == ',' || sc.ch == closing_brace)))) {
							// Make sure the character isn't escaped
							if (sc.chPrev != '\\') {
								// Parameter value contains a { which is the 2nd case described above
								if (sc.ch == '{')
									++skipped; // Remember it
								else if (sc.ch == '}')
									--skipped;
								else if (skipped == 1 && sc.ch == ch && ch == '"') // Don't ignore cases like {"o}
									skipped = 0;
							}

							sc.Forward();
						}
					}

					// Don't colorize the ,
					sc.SetState(SCE_BIBTEX_DEFAULT);

					// Skip until the , or entry's closing closing_brace is found
					// since this parameter might be the last one
					while (sc.More() && !(sc.ch == ',' || sc.ch == closing_brace))
						sc.Forward();

					int state = SCE_BIBTEX_PARAMETER; // The might be more parameters

					// We've reached the closing closing_brace for the bib entry
					// in case no " or {} has been used to enclose the value,
					// as in 3rd case described above
					if (sc.ch == closing_brace) {
						--current_level;
						// Make sure the text between entries is not colored
						// using parameter's style
						state = SCE_BIBTEX_DEFAULT;
					}

					int end = sc.currentPos;
					current_line = styler.GetLine(end);

					// We have possibly skipped some lines, so the folding levels
					// have to be adjusted separately
					for (int i = styler.GetLine(start); i <= styler.GetLine(end); ++i)
						styler.SetLevel(i, prev_level);

					sc.ForwardSetState(state);
				}

				if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == closing_brace) {
					sc.SetState(SCE_BIBTEX_DEFAULT);
					--current_level;
				}

				// Non escaped % found which represents a comment until the end of the line
				if (sc.chPrev != '\\' && sc.ch == '%') {
					in_comment = true;
					sc.SetState(SCE_BIBTEX_COMMENT);
				}
			}

			if (sc.state == SCE_BIBTEX_UNKNOWN_ENTRY || sc.state == SCE_BIBTEX_ENTRY) {
				if (!IsAlphabetic(sc.ch) && collect_entry_name)
					collect_entry_name = false;

				if (collect_entry_name) {
					buffer += static_cast<char>(tolower(sc.ch));
                    if (EntryNames.InList(buffer.c_str()))
                        sc.ChangeState(SCE_BIBTEX_ENTRY);
                    else
                        sc.ChangeState(SCE_BIBTEX_UNKNOWN_ENTRY);
				}
			}

			if (sc.atLineEnd) {
				int level = prev_level;

				if (visible_chars == 0 && fold_compact)
					level |= SC_FOLDLEVELWHITEFLAG;

				if ((current_level > prev_level))
					level |= SC_FOLDLEVELHEADERFLAG;
				// else if (current_level < prev_level)
				//	level |= SC_FOLDLEVELBOXFOOTERFLAG; // Deprecated

				if (level != styler.LevelAt(current_line)) {
					styler.SetLevel(current_line, level);
				}

				++current_line;
				prev_level = current_level;
				visible_chars = 0;
			}

			if (!isspacechar(sc.ch))
				++visible_chars;
		}

		sc.Complete();

		// Fill in the real level of the next line, keeping the current flags as they will be filled in later
		int flagsNext = styler.LevelAt(current_line) & ~SC_FOLDLEVELNUMBERMASK;
		styler.SetLevel(current_line, prev_level | flagsNext);
	}
}
static const char * const BibTeXWordLists[] = {
            "Entry Names",
            0,
};

LexerModule lmBibTeX(SCLEX_BIBTEX, ColorizeBibTeX, "bib", 0, BibTeXWordLists);

// Entry Names
//    article, book, booklet, conference, inbook,
//    incollection, inproceedings, manual, mastersthesis,
//    misc, phdthesis, proceedings, techreport, unpublished,
//    string, url

<|endoftext|>


<commit_before>/*
* Top Level window for KArm -- Sirtaj Singh Kang <taj@kde.org>
* Distributed under the GPL.
*/

/*
 * $Id$
 * $Log$
 * Revision 1.37  2000/06/26 21:10:50  blackie
 * added a preference menu, where stuff soon will come ;-)
 *
 * Revision 1.36  2000/06/02 17:45:39  blackie
 * better print layout + added session time for each task
 *
 * Revision 1.35  2000/06/02 06:04:26  kalle
 * Changing the time in the edit dialog also updates the total time tally
 * in the status bar.
 *
 * Revision 1.34  2000/06/01 15:51:09  blackie
 * added printing capabilities
 *
 * Revision 1.33  2000/05/29 14:17:09  kalle
 * Keyboard acceleration
 *
 * Revision 1.32  2000/05/29 13:19:31  kalle
 * Icon loading in karm
 *
 * Revision 1.31  2000/05/29 12:30:54  kalle
 * - Replaced the two listboxes with one listview
 * - Times can be specified as HH:MM [(+|-)HH:MM]
 * - uses XML GUI
 * - general KDE 2 face- and codelifting
 *
 * Revision 1.30  2000/05/21 16:06:28  kulow
 * adding ... behind New and Edit
 *
 * Revision 1.29  2000/02/07 21:17:31  hadacek
 * KAccel/KStdAccel API cleanup + KAction/KAccel extension
 *
 * Revision 1.28  1999/12/30 19:48:15  granroth
 * loadIcon("*.xpm") => BarIcon("*")
 *
 * Revision 1.27  1999/11/20 19:00:32  espensa
 * Cleanup. Using new Add/Edit Task dialog box
 *
 */

#include <qkeycode.h>
#include <qlayout.h>
#include <qpixmap.h>
#include <qpopupmenu.h>

#include <kaccel.h>
#include <kapp.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kaction.h>
#include <kstdaction.h>
#include <qvbox.h>

#include "kaccelmenuwatch.h"
#include "karm.h"
#include "top.h"
#include "version.h"
#include "task.h"
#include "print.h"

#include "top.moc"
KarmWindow::KarmWindow()
  : KTMainWindow(),
	_accel( new KAccel( this ) ),
	_watcher( new KAccelMenuWatch( _accel, this ) ),
	_karm( new Karm( this ) ),
	_totalTime( 0 )
{
  setView( _karm, FALSE );
  _karm->show();
  connect( _karm, SIGNAL( sessionTimeChanged( long ) ),
		   this, SLOT( updateTime( long ) ) );

  // status bar

  statusBar()->insertItem( i18n( "clock inactive" ), 0 );
  statusBar()->insertItem( i18n( "This session:" ), 1 );
  statusBar()->insertItem( i18n( "0:00" ), 2 );

  // popup menus
  makeMenus();
  _watcher->updateMenus();

  // FIXME: this shouldnt stay. We need to check whether the
  // file exists and if not, create a blank one and ask whether
  // we want to add a task.
  _karm->load();

  // connections
  connect( _karm, SIGNAL(timerStarted()), this, SLOT(clockStartMsg()));
  connect( _karm, SIGNAL(timerStopped()), this, SLOT(clockStopMsg()));
  connect( _karm, SIGNAL(timerTick()), this, SLOT(updateTime()));

  KConfig &config = *kapp->config();
  config.setGroup( QString::fromLatin1("Karm") );
  int w = config.readNumEntry( QString::fromLatin1("Width"), 100 );
  int h = config.readNumEntry( QString::fromLatin1("Height"), 100 );
  w = QMAX( w, sizeHint().width() );
  h = QMAX( h, sizeHint().height() );
  resize(w, h);
}

void KarmWindow::quit()
{
  _karm->save();
  KConfig &config = *KGlobal::config();
  config.setGroup( QString::fromLatin1("Karm") );
  config.writeEntry( QString::fromLatin1("Width"), width());
  config.writeEntry( QString::fromLatin1("Height"), height());
  config.sync();
  kapp->quit();
}

// For some reasons, it doesn't seem like the destructor is being invoked
// when selecting quit in the menu, so maybe it should be removed.
// 26 maj. 2000 15:24 -- Jesper Pedersen <blackie@kde.org>
KarmWindow::~KarmWindow()
{
  quit();
}

/**
 * Updates the total time tally by one minute.
 */
void KarmWindow::updateTime()
{
  _totalTime++;
  updateStatusBar();
}

/**
 * Updates the total time tally by the value specified in newval.
 */
void KarmWindow::updateTime( long difference )
{
  _totalTime += difference;
  updateStatusBar();
}

void KarmWindow::updateStatusBar()
{
  QString time = Karm::formatTime( _totalTime );
  statusBar()->changeItem( time, 2);
}

void KarmWindow::clockStartMsg()
{
  toolBar(0)->setItemEnabled( 0, FALSE);
  toolBar(0)->setItemEnabled( 1, TRUE );
  statusBar()->changeItem( i18n( "clock active" ), 0);
}

void KarmWindow::clockStopMsg()
{
  toolBar(0)->setItemEnabled( 1, FALSE);
  toolBar(0)->setItemEnabled( 0, TRUE );
  statusBar()->changeItem( i18n( "clock inactive" ), 0);
}

void KarmWindow::saveProperties( KConfig* )
{
  _karm->save();
}

void KarmWindow::keyBindings()
{
  KKeyDialog::configureKeys( actionCollection(), xmlFile());
}

void KarmWindow::prefs()
{
  dialog = new KDialogBase(KDialogBase::Tabbed, i18n("Preferences"),
                           KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok);

  QVBox *autoSaveMenu = dialog->addVBoxPage(i18n("Auto Save"));
  new QLabel(i18n("Auto Saving will be available from here soooooon\nJesper <blackie@kde.org>"), autoSaveMenu);

  QVBox *printerMenu = dialog->addVBoxPage(i18n("Printer Options"));
  new QLabel(i18n("Options describing the printout should come here sooooon\nJesper <blackie@kde.org>"), printerMenu);

  dialog->show();
}

void KarmWindow::prefsOk()
{
  qDebug("OK\n");
  delete dialog;
}

void KarmWindow::prefsCancel()
{
  qDebug("Cancel\n");
  delete dialog;
}

void KarmWindow::resetSessionTime()
{
  _totalTime = 0;
  statusBar()->changeItem( i18n("0:00"), 2 );
}

void KarmWindow::makeMenus()
{
  (void)KStdAction::quit(this, SLOT(quit()), actionCollection());
  (void)KStdAction::print(this, SLOT(print()), actionCollection());
  (void)KStdAction::keyBindings(this, SLOT(keyBindings()),actionCollection());
  (void)KStdAction::preferences(this,	SLOT(prefs()),actionCollection());
  (void)new KAction(i18n("&Reset Session Time"), CTRL + Key_R,this,
		    SLOT(resetSessionTime()),actionCollection(),
		    "reset_session_time");

  (void)new KAction(i18n("&Start"), BarIcon( QString::fromLatin1("clock") ),
		    CTRL + Key_S ,_karm,
		    SLOT(startClock()),actionCollection(),"start");

  (void)new KAction(i18n("S&top"), BarIcon(QString::fromLatin1("stop")),
		    CTRL + Key_T,_karm,
		    SLOT(stopClock()),actionCollection(),"stop");
  (void)KStdAction::action( KStdAction::New, _karm,	SLOT(newTask()),
			    actionCollection(),"new_task");

  (void)new KAction(i18n("&Delete"), BarIcon(QString::fromLatin1("filedel")),
		    Key_Delete,_karm,
		    SLOT(deleteTask()),actionCollection(),"delete_task");

  (void)new KAction(i18n("&Edit"), BarIcon(QString::fromLatin1("clockedit")),
		    CTRL + Key_E,_karm,
		    SLOT(editTask()),actionCollection(),"edit_task");

  createGUI( QString::fromLatin1("karmui.rc") );
}

void KarmWindow::print()
{
  MyPrinter printer(_karm);
  printer.Print();
}

<commit_msg>QIconSet(BarIcon()) removed. Gives better icons now - but KStdAction::preferences points to "options" which apparently doesn't exist anymore ?<commit_after>/*
* Top Level window for KArm -- Sirtaj Singh Kang <taj@kde.org>
* Distributed under the GPL.
*/

/*
 * $Id$
 * $Log$
 * Revision 1.38  2000/06/28 21:14:50  bieker
 * * strict compilation - fixing some unicode problems
 * * someone forgot to i18n() some strings... (that's easy to catch with
 *   QT_NO_CAST_ASCII :-)
 *
 * Revision 1.37  2000/06/26 21:10:50  blackie
 * added a preference menu, where stuff soon will come ;-)
 *
 * Revision 1.36  2000/06/02 17:45:39  blackie
 * better print layout + added session time for each task
 *
 * Revision 1.35  2000/06/02 06:04:26  kalle
 * Changing the time in the edit dialog also updates the total time tally
 * in the status bar.
 *
 * Revision 1.34  2000/06/01 15:51:09  blackie
 * added printing capabilities
 *
 * Revision 1.33  2000/05/29 14:17:09  kalle
 * Keyboard acceleration
 *
 * Revision 1.32  2000/05/29 13:19:31  kalle
 * Icon loading in karm
 *
 * Revision 1.31  2000/05/29 12:30:54  kalle
 * - Replaced the two listboxes with one listview
 * - Times can be specified as HH:MM [(+|-)HH:MM]
 * - uses XML GUI
 * - general KDE 2 face- and codelifting
 *
 * Revision 1.30  2000/05/21 16:06:28  kulow
 * adding ... behind New and Edit
 *
 * Revision 1.29  2000/02/07 21:17:31  hadacek
 * KAccel/KStdAccel API cleanup + KAction/KAccel extension
 *
 * Revision 1.28  1999/12/30 19:48:15  granroth
 * loadIcon("*.xpm") => BarIcon("*")
 *
 * Revision 1.27  1999/11/20 19:00:32  espensa
 * Cleanup. Using new Add/Edit Task dialog box
 *
 */

#include <qkeycode.h>
#include <qlayout.h>
#include <qpixmap.h>
#include <qpopupmenu.h>

#include <kaccel.h>
#include <kapp.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kaction.h>
#include <kstdaction.h>
#include <qvbox.h>

#include "kaccelmenuwatch.h"
#include "karm.h"
#include "top.h"
#include "version.h"
#include "task.h"
#include "print.h"

#include "top.moc"
KarmWindow::KarmWindow()
  : KTMainWindow(),
	_accel( new KAccel( this ) ),
	_watcher( new KAccelMenuWatch( _accel, this ) ),
	_karm( new Karm( this ) ),
	_totalTime( 0 )
{
  setView( _karm, FALSE );
  _karm->show();
  connect( _karm, SIGNAL( sessionTimeChanged( long ) ),
		   this, SLOT( updateTime( long ) ) );

  // status bar

  statusBar()->insertItem( i18n( "clock inactive" ), 0 );
  statusBar()->insertItem( i18n( "This session:" ), 1 );
  statusBar()->insertItem( i18n( "0:00" ), 2 );

  // popup menus
  makeMenus();
  _watcher->updateMenus();

  // FIXME: this shouldnt stay. We need to check whether the
  // file exists and if not, create a blank one and ask whether
  // we want to add a task.
  _karm->load();

  // connections
  connect( _karm, SIGNAL(timerStarted()), this, SLOT(clockStartMsg()));
  connect( _karm, SIGNAL(timerStopped()), this, SLOT(clockStopMsg()));
  connect( _karm, SIGNAL(timerTick()), this, SLOT(updateTime()));

  KConfig &config = *kapp->config();
  config.setGroup( QString::fromLatin1("Karm") );
  int w = config.readNumEntry( QString::fromLatin1("Width"), 100 );
  int h = config.readNumEntry( QString::fromLatin1("Height"), 100 );
  w = QMAX( w, sizeHint().width() );
  h = QMAX( h, sizeHint().height() );
  resize(w, h);
}

void KarmWindow::quit()
{
  _karm->save();
  KConfig &config = *KGlobal::config();
  config.setGroup( QString::fromLatin1("Karm") );
  config.writeEntry( QString::fromLatin1("Width"), width());
  config.writeEntry( QString::fromLatin1("Height"), height());
  config.sync();
  kapp->quit();
}

// For some reasons, it doesn't seem like the destructor is being invoked
// when selecting quit in the menu, so maybe it should be removed.
// 26 maj. 2000 15:24 -- Jesper Pedersen <blackie@kde.org>
KarmWindow::~KarmWindow()
{
  quit();
}

/**
 * Updates the total time tally by one minute.
 */
void KarmWindow::updateTime()
{
  _totalTime++;
  updateStatusBar();
}

/**
 * Updates the total time tally by the value specified in newval.
 */
void KarmWindow::updateTime( long difference )
{
  _totalTime += difference;
  updateStatusBar();
}

void KarmWindow::updateStatusBar()
{
  QString time = Karm::formatTime( _totalTime );
  statusBar()->changeItem( time, 2);
}

void KarmWindow::clockStartMsg()
{
  toolBar(0)->setItemEnabled( 0, FALSE);
  toolBar(0)->setItemEnabled( 1, TRUE );
  statusBar()->changeItem( i18n( "clock active" ), 0);
}

void KarmWindow::clockStopMsg()
{
  toolBar(0)->setItemEnabled( 1, FALSE);
  toolBar(0)->setItemEnabled( 0, TRUE );
  statusBar()->changeItem( i18n( "clock inactive" ), 0);
}

void KarmWindow::saveProperties( KConfig* )
{
  _karm->save();
}

void KarmWindow::keyBindings()
{
  KKeyDialog::configureKeys( actionCollection(), xmlFile());
}

void KarmWindow::prefs()
{
  dialog = new KDialogBase(KDialogBase::Tabbed, i18n("Preferences"),
                           KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok);

  QVBox *autoSaveMenu = dialog->addVBoxPage(i18n("Auto Save"));
  new QLabel(i18n("Auto Saving will be available from here soooooon\nJesper <blackie@kde.org>"), autoSaveMenu);

  QVBox *printerMenu = dialog->addVBoxPage(i18n("Printer Options"));
  new QLabel(i18n("Options describing the printout should come here sooooon\nJesper <blackie@kde.org>"), printerMenu);

  dialog->show();
}

void KarmWindow::prefsOk()
{
  qDebug("OK\n");
  delete dialog;
}

void KarmWindow::prefsCancel()
{
  qDebug("Cancel\n");
  delete dialog;
}

void KarmWindow::resetSessionTime()
{
  _totalTime = 0;
  statusBar()->changeItem( i18n("0:00"), 2 );
}

void KarmWindow::makeMenus()
{
  (void)KStdAction::quit(this, SLOT(quit()), actionCollection());
  (void)KStdAction::print(this, SLOT(print()), actionCollection());
  (void)KStdAction::keyBindings(this, SLOT(keyBindings()),actionCollection());
  (void)KStdAction::preferences(this, SLOT(prefs()),actionCollection());
  (void)new KAction(i18n("&Reset Session Time"), CTRL + Key_R,this,
		    SLOT(resetSessionTime()),actionCollection(),
		    "reset_session_time");

  (void)new KAction(i18n("&Start"), QString::fromLatin1("clock"),
		    CTRL + Key_S ,_karm,
		    SLOT(startClock()),actionCollection(),"start");

  (void)new KAction(i18n("S&top"), QString::fromLatin1("stop"),
		    CTRL + Key_T,_karm,
		    SLOT(stopClock()),actionCollection(),"stop");
  (void)KStdAction::action( KStdAction::New, _karm,	SLOT(newTask()),
			    actionCollection(),"new_task");

  (void)new KAction(i18n("&Delete"), QString::fromLatin1("filedel"),
		    Key_Delete,_karm,
		    SLOT(deleteTask()),actionCollection(),"delete_task");

  (void)new KAction(i18n("&Edit"), QString::fromLatin1("clockedit"),
		    CTRL + Key_E,_karm,
		    SLOT(editTask()),actionCollection(),"edit_task");

  createGUI( QString::fromLatin1("karmui.rc") );
}

void KarmWindow::print()
{
  MyPrinter printer(_karm);
  printer.Print();
}

<|endoftext|>


<commit_before>#ifndef INCLUDE_ROADAGAIN_CELL
#define INCLUDE_ROADAGAIN_CELL

namespace roadagain
{

class Cell
{
public:
    Cell();
    Cell(const Point& p, CellColor color);

    void reverse();

private:
    Point point_;
    CellColor color_;
}

} // namespace roadagain<commit_msg>Add missing endif to cell.hpp<commit_after>#ifndef INCLUDE_ROADAGAIN_CELL
#define INCLUDE_ROADAGAIN_CELL

namespace roadagain
{

class Cell
{
public:
    Cell();
    Cell(const Point& p, CellColor color);

    void reverse();

private:
    Point point_;
    CellColor color_;
}

} // namespace roadagain

#endif
<|endoftext|>


<commit_before>#ifndef _SDD_MEM_REF_COUNTED_HH_
#define _SDD_MEM_REF_COUNTED_HH_

#include <cassert>
#include <cstdint>     // uint32_t
#include <functional>  // hash
#include <limits>      // numeric_limits
#include <type_traits> // is_nothrow_constructible
#include <utility>     // forward

#include <boost/intrusive/unordered_set.hpp>

#include "sdd/util/packed.hh"

namespace sdd { namespace mem {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief A wrapper to associate a reference counter to a unified data.
///
/// This type is meant to be used by ptr, which takes care of incrementing and decrementing
/// the reference counter, as well as the deletion of the held data.
template <typename T, typename Hash = std::hash<T>>
class
#ifdef __clang__
LIBSDD_ATTRIBUTE_PACKED
#endif
ref_counted
{
  // Can't copy a ref_counted.
  ref_counted(const ref_counted&) = delete;
  ref_counted& operator=(const ref_counted&) = delete;

  // Can't move a ref_counted.
  ref_counted(ref_counted&&) = delete;
  ref_counted& operator=(ref_counted&&) = delete;

private:

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // The order is important here: data_ MUST be the last of all fields. This is necessary
  // because, for SDD, we allocate the alpha function directly behind the node, without any
  // indirection, to avoid a pointer. Thus, the address of the alpha function is computed
  // knowing this is right after the node.

  /// We choose a faster, unsafe mode.
  typedef boost::intrusive::link_mode<boost::intrusive::normal_link> link_mode;
  /// Used by Boost.Intrusive to manage the unicity table.
  boost::intrusive::unordered_set_member_hook<link_mode> member_hook_;

  /// @brief The number of time the encapsulated data is referenced
  ///
  /// Implements a reference-counting garbage collection.
  mutable std::uint32_t ref_count_;

  /// @brief The garbage collected data.
  ///
  /// The ptr class is responsible for the detection of dereferenced data and for
  /// instructing the unicity table to erase it.
  const T data_;

public:

  template <typename... Args>
  ref_counted(Args&&... args)
  noexcept(std::is_nothrow_constructible<T, Args...>::value)
		: member_hook_()
    , ref_count_(0)
    , data_(std::forward<Args>(args)...)
  {
  }

  /// @brief Get a reference of the unified data.
  const T&
  data()
  const noexcept
  {
    return data_;
  }

  /// @brief Get the number of extra bytes that may be used by the contained type.
  ///
  /// This information is needed when a data of variable length is allocated.
  std::size_t
  extra_bytes()
  const noexcept
  {
    // Static dispatch.
    return extra_bytes_impl(data_, 0);
  }

  /// @brief Called when the contained type defines extra_bytes.
  template <typename U>
  static auto
  extra_bytes_impl(const U& x, int)
  noexcept
  -> decltype(x.extra_bytes())
  {
    return x.extra_bytes();
  }

  /// @brief Called when the contained type doesn't define extra_bytes.
  template <typename U>
  static constexpr auto
  extra_bytes_impl(const U&, long)
  noexcept
  -> decltype(0)
  {
    return 0;
  }

private:

  /// A ptr should be able to access and modify the reference counter.
  template <typename U> friend class ptr;

  /// The unicity table needs to access member_hook_.
  template <typename U> friend class unique_table;

  /// @brief A ptr references that unified data.
  void
  increment_reference_counter()
  noexcept
  {
    assert(ref_count_ < std::numeric_limits<uint32_t>::max());
    ++ref_count_;
  }

  /// @brief A ptr no longer references that unified data.
  void
  decrement_reference_counter()
  noexcept
  {
    assert(ref_count_ > 0);
    --ref_count_;
  }

  /// @brief Tell if the unified data is no longer referenced.
  bool
  is_not_referenced()
  const noexcept
  {
    return ref_count_ == 0;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @related ref_counted
template <typename T, typename Hash>
inline
bool
operator==(const ref_counted<T, Hash>& lhs, const ref_counted<T, Hash>& rhs)
noexcept
{
  return lhs.data() == rhs.data();
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::mem

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::mem::ref_counted
template <typename T, typename Hash>
struct hash<sdd::mem::ref_counted<T,Hash>>
{
  std::size_t
  operator()(const sdd::mem::ref_counted<T, Hash>& x)
  const noexcept
  {
    return Hash()(x.data());
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _SDD_MEM_REF_COUNTED_HH_
<commit_msg>Remove useless 'mutable'.<commit_after>#ifndef _SDD_MEM_REF_COUNTED_HH_
#define _SDD_MEM_REF_COUNTED_HH_

#include <cassert>
#include <cstdint>     // uint32_t
#include <functional>  // hash
#include <limits>      // numeric_limits
#include <type_traits> // is_nothrow_constructible
#include <utility>     // forward

#include <boost/intrusive/unordered_set.hpp>

#include "sdd/util/packed.hh"

namespace sdd { namespace mem {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief A wrapper to associate a reference counter to a unified data.
///
/// This type is meant to be used by ptr, which takes care of incrementing and decrementing
/// the reference counter, as well as the deletion of the held data.
template <typename T, typename Hash = std::hash<T>>
class
#ifdef __clang__
LIBSDD_ATTRIBUTE_PACKED
#endif
ref_counted
{
  // Can't copy a ref_counted.
  ref_counted(const ref_counted&) = delete;
  ref_counted& operator=(const ref_counted&) = delete;

  // Can't move a ref_counted.
  ref_counted(ref_counted&&) = delete;
  ref_counted& operator=(ref_counted&&) = delete;

private:

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // The order is important here: data_ MUST be the last of all fields. This is necessary
  // because, for SDD, we allocate the alpha function directly behind the node, without any
  // indirection, to avoid a pointer. Thus, the address of the alpha function is computed
  // knowing this is right after the node.

  /// We choose a faster, unsafe mode.
  typedef boost::intrusive::link_mode<boost::intrusive::normal_link> link_mode;
  /// Used by Boost.Intrusive to manage the unicity table.
  boost::intrusive::unordered_set_member_hook<link_mode> member_hook_;

  /// @brief The number of time the encapsulated data is referenced
  ///
  /// Implements a reference-counting garbage collection.
  std::uint32_t ref_count_;

  /// @brief The garbage collected data.
  ///
  /// The ptr class is responsible for the detection of dereferenced data and for
  /// instructing the unicity table to erase it.
  const T data_;

public:

  template <typename... Args>
  ref_counted(Args&&... args)
  noexcept(std::is_nothrow_constructible<T, Args...>::value)
		: member_hook_()
    , ref_count_(0)
    , data_(std::forward<Args>(args)...)
  {
  }

  /// @brief Get a reference of the unified data.
  const T&
  data()
  const noexcept
  {
    return data_;
  }

  /// @brief Get the number of extra bytes that may be used by the contained type.
  ///
  /// This information is needed when a data of variable length is allocated.
  std::size_t
  extra_bytes()
  const noexcept
  {
    // Static dispatch.
    return extra_bytes_impl(data_, 0);
  }

  /// @brief Called when the contained type defines extra_bytes.
  template <typename U>
  static auto
  extra_bytes_impl(const U& x, int)
  noexcept
  -> decltype(x.extra_bytes())
  {
    return x.extra_bytes();
  }

  /// @brief Called when the contained type doesn't define extra_bytes.
  template <typename U>
  static constexpr auto
  extra_bytes_impl(const U&, long)
  noexcept
  -> decltype(0)
  {
    return 0;
  }

private:

  /// A ptr should be able to access and modify the reference counter.
  template <typename U> friend class ptr;

  /// The unicity table needs to access member_hook_.
  template <typename U> friend class unique_table;

  /// @brief A ptr references that unified data.
  void
  increment_reference_counter()
  noexcept
  {
    assert(ref_count_ < std::numeric_limits<uint32_t>::max());
    ++ref_count_;
  }

  /// @brief A ptr no longer references that unified data.
  void
  decrement_reference_counter()
  noexcept
  {
    assert(ref_count_ > 0);
    --ref_count_;
  }

  /// @brief Tell if the unified data is no longer referenced.
  bool
  is_not_referenced()
  const noexcept
  {
    return ref_count_ == 0;
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @related ref_counted
template <typename T, typename Hash>
inline
bool
operator==(const ref_counted<T, Hash>& lhs, const ref_counted<T, Hash>& rhs)
noexcept
{
  return lhs.data() == rhs.data();
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::mem

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::mem::ref_counted
template <typename T, typename Hash>
struct hash<sdd::mem::ref_counted<T,Hash>>
{
  std::size_t
  operator()(const sdd::mem::ref_counted<T, Hash>& x)
  const noexcept
  {
    return Hash()(x.data());
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _SDD_MEM_REF_COUNTED_HH_
<|endoftext|>


<commit_before>#include "timer.h"

#if __APPLE__ || __linux__ || __ANDROID_API__
    #include <unistd.h> // usleep()
    #if __APPLE__
        #include <mach/mach.h>
        #include <mach/mach_time.h>
    #elif __linux__ || __ANDROID_API__
        #include <sys/time.h>
    #endif
#elif __EMSCRIPTEN__
    #include <unistd.h> // usleep()
    #include <emscripten.h>
#elif _WIN32 || _WIN64
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
#else
    #include <thread>
    #include <chrono>
    using namespace std::chrono;
#endif

namespace rpp
{
    ///////////////////////////////////////////////////////////////////////////////////////////////

    static const double period = []
    {
        #if __APPLE__
            mach_timebase_info_data_t timebase;
            mach_timebase_info(&timebase);
            return double(timebase.numer) / timebase.denom / 1e9;
        #elif __linux__
            return 1e-6;
        #elif __EMSCRIPTEN__
            return 1e-6;
        #elif _WIN32
            LARGE_INTEGER freq;
            QueryPerformanceFrequency(&freq);
            return 1.0 / double(freq.QuadPart);
        #else // default to std::chrono
            return double(microseconds::period::num) / microseconds::period::den;
        #endif
    } ();

    double time_period() noexcept { return period; }

    uint64_t time_now() noexcept
    {
        #ifdef __APPLE__
            return mach_absolute_time();
        #elif __linux__
            struct timeval t;
            gettimeofday(&t, NULL);
            return (t.tv_sec * 1000000ull) + t.tv_usec;
        #elif __EMSCRIPTEN__
            return uint64_t(emscripten_get_now() * 1000);
        #elif _WIN32
            LARGE_INTEGER time;
            QueryPerformanceCounter(&time);
            return time.QuadPart;
        #else
            return duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
        #endif
    }

    void sleep_ms(unsigned int millis) noexcept
    {
        #if __APPLE__ || __linux__ || __EMSCRIPTEN__
            usleep(millis*1000);
        #elif _WIN32
            Sleep(millis);
        #else
            this_thread::sleep_for(milliseconds(millis));
        #endif
    }

    void sleep_us(unsigned int micros) noexcept
    {
        #if __APPLE__ || __linux__ || __EMSCRIPTEN__
            usleep(micros);
        #elif _WIN32
            // On Windows we don't really care much; just do a millisecond sleep
            int millis = micros / 1000;
            if (millis == 0) millis = 1;
            Sleep(millis);
        #else
            this_thread::sleep_for(microseconds(micros));
        #endif
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    Timer::Timer()
    {
        start();
    }

    void Timer::start()
    {
        value = time_now();
    }

    double Timer::elapsed() const
    {
        uint64_t end = time_now();
        return (end - value) * period;
    }

    double Timer::next()
    {
        double t = elapsed();
        start();
        return t;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
}

<commit_msg>Added missing noexcept specifications.<commit_after>#include "timer.h"

#if __APPLE__ || __linux__ || __ANDROID_API__
    #include <unistd.h> // usleep()
    #if __APPLE__
        #include <mach/mach.h>
        #include <mach/mach_time.h>
    #elif __linux__ || __ANDROID_API__
        #include <sys/time.h>
    #endif
#elif __EMSCRIPTEN__
    #include <unistd.h> // usleep()
    #include <emscripten.h>
#elif _WIN32 || _WIN64
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
#else
    #include <thread>
    #include <chrono>
    using namespace std::chrono;
#endif

namespace rpp
{
    ///////////////////////////////////////////////////////////////////////////////////////////////

    static const double period = []
    {
        #if __APPLE__
            mach_timebase_info_data_t timebase;
            mach_timebase_info(&timebase);
            return double(timebase.numer) / timebase.denom / 1e9;
        #elif __linux__
            return 1e-6;
        #elif __EMSCRIPTEN__
            return 1e-6;
        #elif _WIN32
            LARGE_INTEGER freq;
            QueryPerformanceFrequency(&freq);
            return 1.0 / double(freq.QuadPart);
        #else // default to std::chrono
            return double(microseconds::period::num) / microseconds::period::den;
        #endif
    } ();

    double time_period() noexcept { return period; }

    uint64_t time_now() noexcept
    {
        #ifdef __APPLE__
            return mach_absolute_time();
        #elif __linux__
            struct timeval t;
            gettimeofday(&t, NULL);
            return (t.tv_sec * 1000000ull) + t.tv_usec;
        #elif __EMSCRIPTEN__
            return uint64_t(emscripten_get_now() * 1000);
        #elif _WIN32
            LARGE_INTEGER time;
            QueryPerformanceCounter(&time);
            return time.QuadPart;
        #else
            return duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
        #endif
    }

    void sleep_ms(unsigned int millis) noexcept
    {
        #if __APPLE__ || __linux__ || __EMSCRIPTEN__
            usleep(millis*1000);
        #elif _WIN32
            Sleep(millis);
        #else
            this_thread::sleep_for(milliseconds(millis));
        #endif
    }

    void sleep_us(unsigned int micros) noexcept
    {
        #if __APPLE__ || __linux__ || __EMSCRIPTEN__
            usleep(micros);
        #elif _WIN32
            // On Windows we don't really care much; just do a millisecond sleep
            int millis = micros / 1000;
            if (millis == 0) millis = 1;
            Sleep(millis);
        #else
            this_thread::sleep_for(microseconds(micros));
        #endif
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    Timer::Timer() noexcept
    {
        start();
    }

    void Timer::start() noexcept
    {
        value = time_now();
    }

    double Timer::elapsed() const noexcept
    {
        uint64_t end = time_now();
        return (end - value) * period;
    }

    double Timer::next() noexcept
    {
        double t = elapsed();
        start();
        return t;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Lakshman Anumolu, Pradeep Garigipati
 * All rights reserved.
 *
 * This file is part of MeshIO whose distribution is governed by
 * the BSD 2-Clause License contained in the accompanying LICENSE.txt
 * file.
 */

#include <gtest/gtest.h>
#include <meshio/stl.hpp>
#include "testHelpers.hpp"

using namespace std;
using namespace meshio;

TEST(STL, READ_BINARY)
{
    /* Reference STLData object */
    vector< STLData<float> > referenceObjs;
    initializeReferenceSTLObj(referenceObjs);

    /* Read stl file using library function */
    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_binary.stl");

    EXPECT_TRUE(objs[0] == referenceObjs[0]);

    referenceObjs.clear();
    objs.clear();
}

TEST(STL, READ_ASCII)
{
    /* Reference STLData object */
    vector< STLData<float> > referenceObjs;
    initializeReferenceSTLObj(referenceObjs);

    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_ascii.stl");

    EXPECT_TRUE(objs[0] == referenceObjs[0]);

    referenceObjs.clear();
    objs.clear();
}

TEST(STL, WRITE_ASCII)
{
    /* Reference STLData object */
    vector< STLData<float> > referenceObjs;
    initializeReferenceSTLObj(referenceObjs);

    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_ascii.stl");
    stl::write(TEST_DIR "/cube_ascii2ascii.stl", meshio::STL_ASCII, objs);

    referenceObjs.clear();
    objs.clear();
}

TEST(STL, CROSS_CHECK)
{
    vector< STLData<float> > binReadObjs;
    stl::read<float>(binReadObjs, TEST_DIR "/cube_binary.stl");

    vector< STLData<float> > asciiReadObjs;
    stl::read<float>(asciiReadObjs, TEST_DIR "/cube_ascii.stl");

    EXPECT_TRUE(binReadObjs[0] == asciiReadObjs[0]);
}<commit_msg>Updated tests<commit_after>/*
 * Copyright (c) 2015, Lakshman Anumolu, Pradeep Garigipati
 * All rights reserved.
 *
 * This file is part of MeshIO whose distribution is governed by
 * the BSD 2-Clause License contained in the accompanying LICENSE.txt
 * file.
 */

#include <gtest/gtest.h>
#include <meshio/stl.hpp>
#include "testHelpers.hpp"

using namespace std;
using namespace meshio;

TEST(STL, READ_BINARY)
{
    /* Reference STLData object */
    vector< STLData<float> > referenceObjs;
    initializeReferenceSTLObj(referenceObjs);

    /* Read stl file using library function */
    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_binary.stl");

    EXPECT_TRUE(objs[0] == referenceObjs[0]);

    referenceObjs.clear();
    objs.clear();
}

TEST(STL, READ_ASCII)
{
    /* Reference STLData object */
    vector< STLData<float> > referenceObjs;
    initializeReferenceSTLObj(referenceObjs);

    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_ascii.stl");

    EXPECT_TRUE(objs[0] == referenceObjs[0]);

    referenceObjs.clear();
    objs.clear();
}

TEST(STL, WRITE_BINARY)
{
    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_ascii.stl");
    stl::write(TEST_DIR "/cube_ascii2binary.stl", meshio::STL_BINARY, objs);

    objs.clear();
}

TEST(STL, WRITE_ASCII)
{
    vector< STLData<float> > objs;
    stl::read<float>(objs, TEST_DIR "/cube_binary.stl");
    stl::write(TEST_DIR "/cube_binary2ascii.stl", meshio::STL_ASCII, objs);

    objs.clear();
}

TEST(STL, CROSS_CHECK)
{
    vector< STLData<float> > binReadObjs;
    stl::read<float>(binReadObjs, TEST_DIR "/cube_binary.stl");

    vector< STLData<float> > asciiReadObjs;
    stl::read<float>(asciiReadObjs, TEST_DIR "/cube_ascii.stl");

    EXPECT_TRUE(binReadObjs[0] == asciiReadObjs[0]);
}
<|endoftext|>


<commit_before>/* Copyright (C) 2005-2008 Damien Stehle.
   Copyright (C) 2007 David Cade.

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "config.h"
#include "util.h"

using namespace fplll;

void print_help()
{
  cout << "Usage: latticegen [-randseed [<int> | 'time']] options\n"
       << "Options : " << endl
       << " r <d> <b> : gen_intrel" << endl
       << " s <d> <b> <b2> : gen_simdioph" << endl
       << " u <d> <b> : gen_uniform" << endl
       << " n <d> <b> <c> : gen_ntrulike" << endl
       << " N <d> <b> <c> : gen_ntrulike2" << endl
       << " q <d> <k> <b> <c>: gen_qary" << endl
       << " t <d> <f> : gen_trg" << endl
       << " T <d> : gen_trg2" << endl;
}

void print_version()
{
  cout << "latticegen (fplll) " << VERSION << endl
       << "Copyright 2005-2011 Damien Stehle, David Cade, Xavier Pujol." << endl
       << "fplll is free software. You can redistribute it and/or modify" << endl
       << "it under the terms of the GNU Lesser General Public License as published by" << endl
       << "the Free Software Foundation, either version 2.1 of the License, or" << endl
       << "(at your option) any later version." << endl;
}

void fatal_error(const char *message)
{
  cerr << "latticegen: " << message << endl
       << "Try 'latticegen --help' for more information" << endl;
  exit(1);
}

int main(int argc, char *argv[])
{
  int iArg = 1;

  if (argc - iArg < 1 || strcmp(argv[iArg], "--help") == 0)
  {
    print_help();
    return 0;
  }
  else if (strcmp(argv[iArg], "--version") == 0)
  {
    print_version();
    return 0;
  }
  else if (strcmp(argv[iArg], "-randseed") == 0)
  {
    iArg++;
    if (argc - iArg < 1)
      fatal_error("option '-randseed' requires an argument");
    if (strcmp(argv[iArg], "time") == 0)
    {
      RandGen::init_with_time();
    }
    else
    {
      RandGen::init_with_seed(atol(argv[iArg]));
    }
    iArg++;
  }

  if (argc - iArg < 2)
    fatal_error("you must specify a method and a dimension");
  char genMethod = argv[iArg][0];
  int d          = atoi(argv[iArg + 1]);
  iArg += 2;

  IntMatrix m;

  // initialization+filling of the matrix
  switch (genMethod)
  {
  case 'r':
  {
    if (argc - iArg < 1)
      fatal_error("method 'r' requires 2 arguments");
    int b = atoi(argv[iArg]);
    m.resize(d, d + 1);
    m.gen_intrel(b);
    break;
  }
  case 's':
  {
    if (argc - iArg < 2)
      fatal_error("method 's' requires 3 arguments");
    int b  = atoi(argv[iArg]);
    int b2 = atoi(argv[iArg + 1]);
    m.resize(d + 1, d + 1);
    m.gen_simdioph(b, b2);
    break;
  }
  case 'u':
  {
    if (argc - iArg < 1)
      fatal_error("method 'u' requires 2 arguments");
    int b = atoi(argv[iArg]);
    m.resize(d, d);
    m.gen_uniform(b);
    break;
  }
  case 'n':
  {
    if (argc - iArg < 1)
      fatal_error("method 'n' requires 3 arguments");
    int b  = atoi(argv[iArg]);
    char c = argv[iArg + 1][0];
    m.resize(2 * d, 2 * d);
    switch (c)
    {
    case 'b':
    {
      m.gen_ntrulike(b);
      break;
    }
    case 'q':
    {
      m.gen_ntrulike_withq(b);
      break;
    }
    }
    break;
  }
  case 'q':
  {
    if (argc - iArg < 1)
      fatal_error("method 'q' requires 4 arguments");
    int k  = atoi(argv[iArg]);
    int b  = atoi(argv[iArg + 1]);
    char c = argv[iArg + 2][0];
    m.resize(d, d);
    switch (c)
    {
    case 'b':
    {
      m.gen_qary(k, b);
      break;
    }
    case 'q':
    {
      m.gen_qary_withq(k, b);
      break;
    }
    case 'p':
    {
      m.gen_qary_prime(k, b);
      break;
    }
    }
    break;
  }
  case 'N':
  {
    if (argc - iArg < 1)
      fatal_error("method 'N' requires 3 arguments");
    int b = atoi(argv[iArg]);
    int c = argv[iArg + 1][0];
    m.resize(2 * d, 2 * d);
    switch (c)
    {
    case 'b':
    {
      m.gen_ntrulike2(b);
      break;
    }
    case 'q':
    {
      m.gen_ntrulike2_withq(b);
      break;
    }
    }
    break;
  }
  case 't':
  {
    if (argc - iArg < 1)
      fatal_error("method 't' requires 2 arguments");
    double alpha = atof(argv[iArg]);
    m.resize(d, d);
    m.gen_trg(alpha);
    break;
  }
  case 'T':
  {
    FP_NR<mpfr_t> *w = new FP_NR<mpfr_t>[d];

    for (int i = 0; i < d; i++)
      mpfr_inp_str(w[i].get_data(), stdin, 10, GMP_RNDN);

    m.resize(d, d);
    m.gen_trg2(w);

    delete[] w;

    break;
  }
  default:
  {
    fatal_error("invalid method");
    break;
  }
  }
  cout << m << endl;
  return 0;
}
<commit_msg>Don't fail silently on invalid latticegen options<commit_after>/* Copyright (C) 2005-2008 Damien Stehle.
   Copyright (C) 2007 David Cade.

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "config.h"
#include "util.h"

using namespace fplll;

void print_help()
{
  cout << "Usage: latticegen [-randseed [<int> | 'time']] options\n"
       << "Options : " << endl
       << " r <d> <b> : gen_intrel" << endl
       << " s <d> <b> <b2> : gen_simdioph" << endl
       << " u <d> <b> : gen_uniform" << endl
       << " n <d> <b> <c> : gen_ntrulike" << endl
       << " N <d> <b> <c> : gen_ntrulike2" << endl
       << " q <d> <k> <b> <c>: gen_qary" << endl
       << " t <d> <f> : gen_trg" << endl
       << " T <d> : gen_trg2" << endl
       << "See README.md for option descriptions:" << endl
       << "https://github.com/fplll/fplll/blob/master/README.md#latticegen" << endl;
}

void print_version()
{
  cout << "latticegen (fplll) " << VERSION << endl
       << "Copyright 2005-2011 Damien Stehle, David Cade, Xavier Pujol." << endl
       << "fplll is free software. You can redistribute it and/or modify" << endl
       << "it under the terms of the GNU Lesser General Public License as published by" << endl
       << "the Free Software Foundation, either version 2.1 of the License, or" << endl
       << "(at your option) any later version." << endl;
}

void fatal_error(const char *message)
{
  cerr << "latticegen: " << message << endl
       << "Try 'latticegen --help' for more information" << endl;
  exit(1);
}

int main(int argc, char *argv[])
{
  int iArg = 1;

  if (argc - iArg < 1 || strcmp(argv[iArg], "--help") == 0)
  {
    print_help();
    return 0;
  }
  else if (strcmp(argv[iArg], "--version") == 0)
  {
    print_version();
    return 0;
  }
  else if (strcmp(argv[iArg], "-randseed") == 0)
  {
    iArg++;
    if (argc - iArg < 1)
      fatal_error("option '-randseed' requires an argument");
    if (strcmp(argv[iArg], "time") == 0)
    {
      RandGen::init_with_time();
    }
    else
    {
      RandGen::init_with_seed(atol(argv[iArg]));
    }
    iArg++;
  }

  if (argc - iArg < 2)
    fatal_error("you must specify a method and a dimension");
  char genMethod = argv[iArg][0];
  int d          = atoi(argv[iArg + 1]);
  iArg += 2;

  IntMatrix m;

  // initialization+filling of the matrix
  switch (genMethod)
  {
  case 'r':
  {
    if (argc - iArg < 1)
      fatal_error("method 'r' requires 2 arguments");
    int b = atoi(argv[iArg]);
    m.resize(d, d + 1);
    m.gen_intrel(b);
    break;
  }
  case 's':
  {
    if (argc - iArg < 2)
      fatal_error("method 's' requires 3 arguments");
    int b  = atoi(argv[iArg]);
    int b2 = atoi(argv[iArg + 1]);
    m.resize(d + 1, d + 1);
    m.gen_simdioph(b, b2);
    break;
  }
  case 'u':
  {
    if (argc - iArg < 1)
      fatal_error("method 'u' requires 2 arguments");
    int b = atoi(argv[iArg]);
    m.resize(d, d);
    m.gen_uniform(b);
    break;
  }
  case 'n':
  {
    if (argc - iArg < 1)
      fatal_error("method 'n' requires 3 arguments");
    int b  = atoi(argv[iArg]);
    char c = argv[iArg + 1][0];
    m.resize(2 * d, 2 * d);
    switch (c)
    {
    case 'b':
    {
      m.gen_ntrulike(b);
      break;
    }
    case 'q':
    {
      m.gen_ntrulike_withq(b);
      break;
    }
    default:
    {
      fatal_error("parameter c must be 'b' or 'q'");
    }
    }
    break;
  }
  case 'q':
  {
    if (argc - iArg < 1)
      fatal_error("method 'q' requires 4 arguments");
    int k  = atoi(argv[iArg]);
    int b  = atoi(argv[iArg + 1]);
    char c = argv[iArg + 2][0];
    m.resize(d, d);
    switch (c)
    {
    case 'b':
    {
      m.gen_qary(k, b);
      break;
    }
    case 'q':
    {
      m.gen_qary_withq(k, b);
      break;
    }
    case 'p':
    {
      m.gen_qary_prime(k, b);
      break;
    }
    default:
    {
      fatal_error("parameter c must be 'b' or 'q' or 'p'");
    }
    }
    break;
  }
  case 'N':
  {
    if (argc - iArg < 1)
      fatal_error("method 'N' requires 3 arguments");
    int b = atoi(argv[iArg]);
    int c = argv[iArg + 1][0];
    m.resize(2 * d, 2 * d);
    switch (c)
    {
    case 'b':
    {
      m.gen_ntrulike2(b);
      break;
    }
    case 'q':
    {
      m.gen_ntrulike2_withq(b);
      break;
    }
    default:
    {
      fatal_error("parameter c must be 'b' or 'q'");
    }
    }
    break;
  }
  case 't':
  {
    if (argc - iArg < 1)
      fatal_error("method 't' requires 2 arguments");
    double alpha = atof(argv[iArg]);
    m.resize(d, d);
    m.gen_trg(alpha);
    break;
  }
  case 'T':
  {
    FP_NR<mpfr_t> *w = new FP_NR<mpfr_t>[d];

    for (int i = 0; i < d; i++)
      mpfr_inp_str(w[i].get_data(), stdin, 10, GMP_RNDN);

    m.resize(d, d);
    m.gen_trg2(w);

    delete[] w;

    break;
  }
  default:
  {
    fatal_error("invalid method");
    break;
  }
  }
  cout << m << endl;
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Prevent crash on Ctrl-D (end of host stream).<commit_after><|endoftext|>


<commit_before>#ifdef _WIN32 // Seems to be set even on win64?
#define BACKTRACE_WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "framework/logger.h"
#include <chrono>
#include <cstdarg>
#include <mutex>
#ifdef BACKTRACE_LIBUNWIND
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#elif defined(BACKTRACE_WINDOWS)
#include <windows.h>
// windows.h must be included before DbgHelp.h
#include <DbgHelp.h>
#endif

#ifndef LOGFILE
#define LOGFILE "openapoc_log.txt"
#endif

// Don't have interactive dialogues in unit tests
#ifdef UNIT_TEST
#undef ERROR_DIALOG
#else

#if defined(ERROR_DIALOG)
#include <SDL_messagebox.h>
#endif

#endif

#ifdef ANDROID
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "OpenApoc", __VA_ARGS__)
#define LOGDV(fmt, ap) __android_log_vprint(ANDROID_LOG_DEBUG, "OpenApoc", fmt, ap)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "OpenApoc", __VA_ARGS__)
#define LOGWV(fmt, ap) __android_log_vprint(ANDROID_LOG_WARN, "OpenApoc", fmt, ap)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenApoc", __VA_ARGS__)
#define LOGEV(fmt, ap) __android_log_vprint(ANDROID_LOG_ERROR, "OpenApoc", fmt, ap)
#define LOG_PATH "/storage/emulated/0/openapoc/data/"
#else
#define LOGD(...)
#define LOGDV(fmt, ap)
#define LOGW(...)
#define LOGWV(fmt, ap)
#define LOGE(...)
#define LOGEV(fmt, ap)
#define LOG_PATH
#endif

#define MAX_SYMBOL_LENGTH 1000

namespace OpenApoc
{

#if defined(BACKTRACE_LIBUNWIND)
static void print_backtrace(FILE *f)
{

	unw_cursor_t cursor;
	unw_context_t ctx;
	unw_word_t ip;
	unw_getcontext(&ctx);
	unw_init_local(&cursor, &ctx);

	fprintf(f, "  called by:\n");
	while (unw_step(&cursor) > 0)
	{
		Dl_info info;
		unw_get_reg(&cursor, UNW_REG_IP, &ip);
		if (ip == 0)
			break;
		dladdr(reinterpret_cast<void *>(ip), &info);
		if (info.dli_sname)
		{
			fprintf(f, "  0x%lx %s+0x%lx (%s)\n", static_cast<uintptr_t>(ip), info.dli_sname,
			        static_cast<uintptr_t>(ip) - reinterpret_cast<uintptr_t>(info.dli_saddr),
			        info.dli_fname);
			continue;
		}
		// If dladdr() failed, try libunwind
		unw_word_t offsetInFn;
		char fnName[MAX_SYMBOL_LENGTH];
		if (!unw_get_proc_name(&cursor, fnName, MAX_SYMBOL_LENGTH, &offsetInFn))
		{
			fprintf(f, "  0x%lx %s+0x%lx (%s)\n", static_cast<uintptr_t>(ip), fnName, offsetInFn,
			        info.dli_fname);
			continue;
		}
		else
			fprintf(f, "  0x%lx\n", static_cast<uintptr_t>(ip));
	}
}
#elif defined(BACKTRACE_WINDOWS)
#define MAX_STACK_FRAMES 100
static void print_backtrace(FILE *f)
{
	static bool initialised = false;
	static HANDLE process;

	unsigned int frames;
	void *ip[MAX_STACK_FRAMES];
	SYMBOL_INFO *sym;

	if (!initialised)
	{
		process = GetCurrentProcess();
		SymInitialize(process, NULL, true);
		initialised = true;
	}

	if (!process)
	{
		fprintf(f, "Failed to get process for backtrace\n");
		return;
	}

	sym = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * (sizeof(char)), 1);
	if (!sym)
	{
		fprintf(f, "Failed to allocate symbol info for backtrace\n");
		return;
	}
	sym->MaxNameLen = MAX_SYMBOL_LENGTH;
	sym->SizeOfStruct = sizeof(SYMBOL_INFO);

	/* Skip 2 frames (print_backtrace and the LogError function itself) */
	frames = CaptureStackBackTrace(2, MAX_STACK_FRAMES, ip, NULL);

	for (unsigned int frame = 0; frame < frames; frame++)
	{
		SymFromAddr(process, (DWORD64)(ip[frame]), 0, sym);
		fprintf(f, "  0x%p %s+0x%lx\n", ip[frame], sym->Name,
		        (uintptr_t)ip[frame] - (uintptr_t)sym->Address);
	}

	free(sym);
}
#else
#warning no backtrace enabled for this platform
static void print_backtrace(FILE *f)
{
	// TODO: Other platform backtrace?
}
#endif

static FILE *outFile = nullptr;

static std::mutex logMutex;
static std::chrono::time_point<std::chrono::high_resolution_clock> timeInit =
    std::chrono::high_resolution_clock::now();

void Log(LogLevel level, UString prefix, UString format, ...)
{
	bool exit_app = false;
	const char *level_prefix;
	auto timeNow = std::chrono::high_resolution_clock::now();
	unsigned long long clockns =
	    std::chrono::duration<unsigned long long, std::nano>(timeNow - timeInit).count();

	logMutex.lock();
	if (!outFile)
	{
#ifdef UNIT_TEST
		outFile = stderr;
#else
#ifndef ANDROID
		outFile = fopen(LOG_PATH LOGFILE, "w");
		if (!outFile)
		{
			// No log file, have to hope stderr goes somewhere useful
			fprintf(stderr, "Failed to open logfile \"%s\"\n", LOGFILE);
			LOGE("Failed to open logfile \"%s\"\n", LOGFILE);
			return;
		}
#endif
#endif
	}

	switch (level)
	{
		case LogLevel::Info:
			level_prefix = "I";
			break;
		case LogLevel::Warning:
			level_prefix = "W";
			break;
		default:
			level_prefix = "E";
			break;
	}

	va_list arglist;
	va_start(arglist, format);
#ifdef ANDROID
	LOGD("%s %llu %s: ", level_prefix, clockns, prefix.c_str());
	LOGDV(format.c_str(), arglist);
	va_end(arglist);
#else
	fprintf(outFile, "%s %llu %s: ", level_prefix, clockns, prefix.c_str());
	vfprintf(outFile, format.c_str(), arglist);

	// On error print a backtrace to the log file
	if (level == LogLevel::Error)
		print_backtrace(outFile);
	fprintf(outFile, "\n");
	va_end(arglist);

	// If it's a warning or error flush the outfile (in case we crash 'soon') and also print to
	// stderr
	if (level != LogLevel::Info)
	{
		fflush(outFile);
		va_start(arglist, format);
		fprintf(stderr, "%s %llu %s: ", level_prefix, clockns, prefix.c_str());
		vfprintf(stderr, format.c_str(), arglist);
		fprintf(stderr, "\n");
		va_end(arglist);
	}
#endif
#if defined(ERROR_DIALOG)
	if (level == LogLevel::Error)
	{
		/* How big should the string be? */
		va_start(arglist, format);
		auto strSize = vsnprintf(NULL, 0, format.c_str(), arglist);
		strSize += 1; // NULL terminator
		std::unique_ptr<char[]> string(new char[strSize]);
		va_end(arglist);

		/* Now format the string */
		va_start(arglist, format);
		vsnprintf(string.get(), strSize, format.c_str(), arglist);
		va_end(arglist);

		SDL_MessageBoxData mBoxData;
		mBoxData.flags = SDL_MESSAGEBOX_ERROR;
		mBoxData.window = NULL; // Might happen before we get our window?
		mBoxData.title = "OpenApoc ERROR";
		mBoxData.message = string.get();
		mBoxData.numbuttons = 2;
		SDL_MessageBoxButtonData buttons[2];
		buttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
		buttons[0].buttonid = 1;
		buttons[0].text = "Exit";
		buttons[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
		buttons[1].buttonid = 2;
		buttons[1].text = "try to limp along";
		mBoxData.buttons = buttons;
		mBoxData.colorScheme = NULL; // Use system settings

		int but;
		SDL_ShowMessageBox(&mBoxData, &but);

		/* button 1 = "exit", button 2 = "try to limp along" */
		if (but == 1)
		{
			exit_app = true;
		}
	}
#endif

	logMutex.unlock();

	if (exit_app)
	{
		exit(EXIT_FAILURE);
	}
}

}; // namespace OpenApoc
<commit_msg>Enable error dialogs by default on windows<commit_after>#ifdef _WIN32 // Seems to be set even on win64?
#define BACKTRACE_WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#define ERROR_DIALOG
#endif

#include "framework/logger.h"
#include <chrono>
#include <cstdarg>
#include <mutex>
#ifdef BACKTRACE_LIBUNWIND
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#elif defined(BACKTRACE_WINDOWS)
#include <windows.h>
// windows.h must be included before DbgHelp.h
#include <DbgHelp.h>
#endif

#ifndef LOGFILE
#define LOGFILE "openapoc_log.txt"
#endif

// Don't have interactive dialogues in unit tests
#ifdef UNIT_TEST
#undef ERROR_DIALOG
#else

#if defined(ERROR_DIALOG)
#include <SDL_messagebox.h>
#endif

#endif

#ifdef ANDROID
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "OpenApoc", __VA_ARGS__)
#define LOGDV(fmt, ap) __android_log_vprint(ANDROID_LOG_DEBUG, "OpenApoc", fmt, ap)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "OpenApoc", __VA_ARGS__)
#define LOGWV(fmt, ap) __android_log_vprint(ANDROID_LOG_WARN, "OpenApoc", fmt, ap)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenApoc", __VA_ARGS__)
#define LOGEV(fmt, ap) __android_log_vprint(ANDROID_LOG_ERROR, "OpenApoc", fmt, ap)
#define LOG_PATH "/storage/emulated/0/openapoc/data/"
#else
#define LOGD(...)
#define LOGDV(fmt, ap)
#define LOGW(...)
#define LOGWV(fmt, ap)
#define LOGE(...)
#define LOGEV(fmt, ap)
#define LOG_PATH
#endif

#define MAX_SYMBOL_LENGTH 1000

namespace OpenApoc
{

#if defined(BACKTRACE_LIBUNWIND)
static void print_backtrace(FILE *f)
{

	unw_cursor_t cursor;
	unw_context_t ctx;
	unw_word_t ip;
	unw_getcontext(&ctx);
	unw_init_local(&cursor, &ctx);

	fprintf(f, "  called by:\n");
	while (unw_step(&cursor) > 0)
	{
		Dl_info info;
		unw_get_reg(&cursor, UNW_REG_IP, &ip);
		if (ip == 0)
			break;
		dladdr(reinterpret_cast<void *>(ip), &info);
		if (info.dli_sname)
		{
			fprintf(f, "  0x%lx %s+0x%lx (%s)\n", static_cast<uintptr_t>(ip), info.dli_sname,
			        static_cast<uintptr_t>(ip) - reinterpret_cast<uintptr_t>(info.dli_saddr),
			        info.dli_fname);
			continue;
		}
		// If dladdr() failed, try libunwind
		unw_word_t offsetInFn;
		char fnName[MAX_SYMBOL_LENGTH];
		if (!unw_get_proc_name(&cursor, fnName, MAX_SYMBOL_LENGTH, &offsetInFn))
		{
			fprintf(f, "  0x%lx %s+0x%lx (%s)\n", static_cast<uintptr_t>(ip), fnName, offsetInFn,
			        info.dli_fname);
			continue;
		}
		else
			fprintf(f, "  0x%lx\n", static_cast<uintptr_t>(ip));
	}
}
#elif defined(BACKTRACE_WINDOWS)
#define MAX_STACK_FRAMES 100
static void print_backtrace(FILE *f)
{
	static bool initialised = false;
	static HANDLE process;

	unsigned int frames;
	void *ip[MAX_STACK_FRAMES];
	SYMBOL_INFO *sym;

	if (!initialised)
	{
		process = GetCurrentProcess();
		SymInitialize(process, NULL, true);
		initialised = true;
	}

	if (!process)
	{
		fprintf(f, "Failed to get process for backtrace\n");
		return;
	}

	sym = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * (sizeof(char)), 1);
	if (!sym)
	{
		fprintf(f, "Failed to allocate symbol info for backtrace\n");
		return;
	}
	sym->MaxNameLen = MAX_SYMBOL_LENGTH;
	sym->SizeOfStruct = sizeof(SYMBOL_INFO);

	/* Skip 2 frames (print_backtrace and the LogError function itself) */
	frames = CaptureStackBackTrace(2, MAX_STACK_FRAMES, ip, NULL);

	for (unsigned int frame = 0; frame < frames; frame++)
	{
		SymFromAddr(process, (DWORD64)(ip[frame]), 0, sym);
		fprintf(f, "  0x%p %s+0x%lx\n", ip[frame], sym->Name,
		        (uintptr_t)ip[frame] - (uintptr_t)sym->Address);
	}

	free(sym);
}
#else
#warning no backtrace enabled for this platform
static void print_backtrace(FILE *f)
{
	// TODO: Other platform backtrace?
}
#endif

static FILE *outFile = nullptr;

static std::mutex logMutex;
static std::chrono::time_point<std::chrono::high_resolution_clock> timeInit =
    std::chrono::high_resolution_clock::now();

void Log(LogLevel level, UString prefix, UString format, ...)
{
	bool exit_app = false;
	const char *level_prefix;
	auto timeNow = std::chrono::high_resolution_clock::now();
	unsigned long long clockns =
	    std::chrono::duration<unsigned long long, std::nano>(timeNow - timeInit).count();

	logMutex.lock();
	if (!outFile)
	{
#ifdef UNIT_TEST
		outFile = stderr;
#else
#ifndef ANDROID
		outFile = fopen(LOG_PATH LOGFILE, "w");
		if (!outFile)
		{
			// No log file, have to hope stderr goes somewhere useful
			fprintf(stderr, "Failed to open logfile \"%s\"\n", LOGFILE);
			LOGE("Failed to open logfile \"%s\"\n", LOGFILE);
			return;
		}
#endif
#endif
	}

	switch (level)
	{
		case LogLevel::Info:
			level_prefix = "I";
			break;
		case LogLevel::Warning:
			level_prefix = "W";
			break;
		default:
			level_prefix = "E";
			break;
	}

	va_list arglist;
	va_start(arglist, format);
#ifdef ANDROID
	LOGD("%s %llu %s: ", level_prefix, clockns, prefix.c_str());
	LOGDV(format.c_str(), arglist);
	va_end(arglist);
#else
	fprintf(outFile, "%s %llu %s: ", level_prefix, clockns, prefix.c_str());
	vfprintf(outFile, format.c_str(), arglist);

	// On error print a backtrace to the log file
	if (level == LogLevel::Error)
		print_backtrace(outFile);
	fprintf(outFile, "\n");
	va_end(arglist);

	// If it's a warning or error flush the outfile (in case we crash 'soon') and also print to
	// stderr
	if (level != LogLevel::Info)
	{
		fflush(outFile);
		va_start(arglist, format);
		fprintf(stderr, "%s %llu %s: ", level_prefix, clockns, prefix.c_str());
		vfprintf(stderr, format.c_str(), arglist);
		fprintf(stderr, "\n");
		va_end(arglist);
	}
#endif
#if defined(ERROR_DIALOG)
	if (level == LogLevel::Error)
	{
		/* How big should the string be? */
		va_start(arglist, format);
		auto strSize = vsnprintf(NULL, 0, format.c_str(), arglist);
		strSize += 1; // NULL terminator
		std::unique_ptr<char[]> string(new char[strSize]);
		va_end(arglist);

		/* Now format the string */
		va_start(arglist, format);
		vsnprintf(string.get(), strSize, format.c_str(), arglist);
		va_end(arglist);

		SDL_MessageBoxData mBoxData;
		mBoxData.flags = SDL_MESSAGEBOX_ERROR;
		mBoxData.window = NULL; // Might happen before we get our window?
		mBoxData.title = "OpenApoc ERROR";
		mBoxData.message = string.get();
		mBoxData.numbuttons = 2;
		SDL_MessageBoxButtonData buttons[2];
		buttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
		buttons[0].buttonid = 1;
		buttons[0].text = "Exit";
		buttons[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
		buttons[1].buttonid = 2;
		buttons[1].text = "try to limp along";
		mBoxData.buttons = buttons;
		mBoxData.colorScheme = NULL; // Use system settings

		int but;
		SDL_ShowMessageBox(&mBoxData, &but);

		/* button 1 = "exit", button 2 = "try to limp along" */
		if (but == 1)
		{
			exit_app = true;
		}
	}
#endif

	logMutex.unlock();

	if (exit_app)
	{
		exit(EXIT_FAILURE);
	}
}

}; // namespace OpenApoc
<|endoftext|>


<commit_before>
#include <GameData.h>
#include <File.h>
#include <DatCat.h>
#include <ExdData.h>
#include <ExdCat.h>
#include <Exd.h>
#include <Exh.h>
#include <iostream>
#include <cctype>
#include <set>
#include <Exd/ExdDataGenerated.h>
#include <Logging/Logger.h>

#include <fstream>
#include <streambuf>
#include <regex>

Sapphire::Data::ExdDataGenerated g_exdData;

using namespace Sapphire;

const std::string datLocation( "/home/mordred/sqpack" );
//const std::string datLocation( "/mnt/c/Program Files (x86)/Steam/steamapps/common/FINAL FANTASY XIV Online/game/sqpack" );

bool invalidChar( char c )
{
  return !( c >= 0 && c < 128 );
}
void stripUnicode( std::string& str )
{
    str.erase( std::remove_if( str.begin(), str.end(), invalidChar ), str.end() );
   str.erase(std::remove_if(str.begin(), str.end(),
                            [](char c) { return !std::isalpha(c) && !std::isdigit(c) && !std::isspace(c) && !std::ispunct(c); }),
             str.end());
}

int main()
{

  Logger::init( "action_parse" );

  Logger::info( "Setting up EXD data" );
  if( !g_exdData.init( datLocation ) )
  {
    Logger::fatal( "Error setting up EXD data " );
    return 0;
  }
  auto idList = g_exdData.getActionIdList();

  for( auto id : idList )
  {
  auto gld = g_exdData.get< Sapphire::Data::Action >( id );
  auto gld1 = g_exdData.get< Sapphire::Data::ActionTransient >( id );
  if( gld )
  {
    Logger::info( "got {0}", gld->name );
    std::string desc = gld1->description;
    stripUnicode( desc );;
    desc = std::regex_replace( desc, std::regex( "HI" ), "\n" );
    desc = std::regex_replace( desc, std::regex( "IH" ), "" );
//    Logger::info( "got {0}", desc );

    std::smatch sm;
    std::regex r(R"(with a potency of \d*)");
    if( std::regex_search(desc, sm, r ) )
    {
      std::string potStr = sm.str();
      auto pos = potStr.find_last_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( pos + 1 );
	Logger::info( "Base Potency: {}", potStr);
      }
    }

    std::smatch sm1;
    std::regex r1(R"(\d* when executed from a target's rear)");
    if( std::regex_search(desc, sm1, r1 ) )
    {
      std::string potStr = sm1.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Rear Potency: {}", potStr);
      }
    }

    std::smatch sm2;
    std::regex r2(R"(\d* when executed from a target's flank)");
    if( std::regex_search(desc, sm2, r2 ) )
    {
      std::string potStr = sm2.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Flank Potency: {}", potStr);
      }
    }

    std::smatch sm3;
    std::regex r3(R"(\d* when executed in front of target)");
    if( std::regex_search(desc, sm3, r3 ) )
    {
      std::string potStr = sm3.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Frontal Potency: {}", potStr);
      }
    }

    std::smatch sm4;
    std::regex r4(R"(Combo Potency: \d*)");
    if( std::regex_search(desc, sm4, r4 ) )
    {
      std::string potStr = sm4.str();
      auto pos = potStr.find_last_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( pos + 1 );
	Logger::info( "Combo Potency: {}", potStr);
      }
    }

  }
  else
    Logger::warn( "failed to get classjob {}", 1 );
  }

  return 0;
}
<commit_msg>Parse more action info from tooltips<commit_after>
#include <GameData.h>
#include <File.h>
#include <DatCat.h>
#include <ExdData.h>
#include <ExdCat.h>
#include <Exd.h>
#include <Exh.h>
#include <iostream>
#include <cctype>
#include <set>
#include <Exd/ExdDataGenerated.h>
#include <Logging/Logger.h>

#include <fstream>
#include <streambuf>
#include <regex>

Sapphire::Data::ExdDataGenerated g_exdData;

using namespace Sapphire;

const std::string datLocation( "/home/mordred/sqpack" );
//const std::string datLocation( "/mnt/c/Program Files (x86)/Steam/steamapps/common/FINAL FANTASY XIV Online/game/sqpack" );

bool invalidChar( char c )
{
  return !( c >= 0 && c < 128 );
}
void stripUnicode( std::string& str )
{
    str.erase( std::remove_if( str.begin(), str.end(), invalidChar ), str.end() );
   str.erase(std::remove_if(str.begin(), str.end(),
                            [](char c) { return !std::isalpha(c) && !std::isdigit(c) && !std::isspace(c) && !std::ispunct(c); }),
             str.end());
}

int main()
{

  Logger::init( "action_parse" );

  Logger::info( "Setting up EXD data" );
  if( !g_exdData.init( datLocation ) )
  {
    Logger::fatal( "Error setting up EXD data " );
    return 0;
  }
  auto idList = g_exdData.getActionIdList();

  for( auto id : idList )
  {
  auto gld = g_exdData.get< Sapphire::Data::Action >( id );
  auto gld1 = g_exdData.get< Sapphire::Data::ActionTransient >( id );
  if( gld )
  {
    if( gld->classJob == -1 || gld->name.empty() )
      continue;
    Logger::info( "{0} - {1}", id, gld->name );
    std::string desc = gld1->description;
    stripUnicode( desc );;
    desc = std::regex_replace( desc, std::regex( "HI" ), "\n" );
    desc = std::regex_replace( desc, std::regex( "IH" ), "" );
//    Logger::info( "got {0}", desc );

    std::smatch sm;
    std::regex r(R"(with a potency of \d*)");
    if( std::regex_search(desc, sm, r ) )
    {
      std::string potStr = sm.str();
      auto pos = potStr.find_last_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( pos + 1 );
	Logger::info( "Base Potency: {}", potStr);
      }
    }

    std::smatch sm1;
    std::regex r1(R"(\d* when executed from a target's rear)");
    if( std::regex_search(desc, sm1, r1 ) )
    {
      std::string potStr = sm1.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Rear Potency: {}", potStr);
      }
    }

    std::smatch sm2;
    std::regex r2(R"(\d* when executed from a target's flank)");
    if( std::regex_search(desc, sm2, r2 ) )
    {
      std::string potStr = sm2.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Flank Potency: {}", potStr);
      }
    }

    std::smatch sm3;
    std::regex r3(R"(\d* when executed in front of target)");
    if( std::regex_search(desc, sm3, r3 ) )
    {
      std::string potStr = sm3.str();
      auto pos = potStr.find_first_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( 0, pos );
	Logger::info( "Frontal Potency: {}", potStr);
      }
    }

    std::smatch sm4;
    std::regex r4(R"(Combo Potency: \d*)");
    if( std::regex_search(desc, sm4, r4 ) )
    {
      std::string potStr = sm4.str();
      auto pos = potStr.find_last_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( pos + 1 );
	Logger::info( "Combo Potency: {}", potStr);
      }
    }

    std::smatch sm5;
    std::regex r5(R"(Cure Potency: \d*)");
    if( std::regex_search(desc, sm5, r5 ) )
    {
      std::string potStr = sm5.str();
      auto pos = potStr.find_last_of( " " );
      if( pos  != std::string::npos )
      {
        potStr = potStr.substr( pos + 1 );
	Logger::info( "Cure Potency: {}", potStr);
      }
    }

    Logger::info( "-" );
  }
  else
    Logger::warn( "failed to get classjob {}", 1 );
  }

  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 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 "operation.h"

#include "settings.h"

#include "utils/persistentsettings.h"

#include <QDir>

#include <iostream>

QVariant Operation::valueFromString(const QString &v)
{
    int pos = v.indexOf(QLatin1Char(':'));
    if (pos <= 0)
        return QVariant();
    const QString type = v.left(pos);
    const QString value = v.mid(pos + 1);

    if (type == QLatin1String("int")) {
        return QVariant(value.toInt());
    } else if (type == QLatin1String("bool")) {
        const QString tmp = value.toLower();
        return QVariant(tmp == QLatin1String("true") || tmp == QLatin1String("yes")
                        || tmp == QLatin1String("1") || tmp == QLatin1String("on"));
    } else if (type == QLatin1String("QByteArray")) {
        return QVariant(value.toLocal8Bit());
    } else if (type == QLatin1String("QString")) {
        return QVariant(value);
    } else if (type == QLatin1String("QVariantList")) {
        QVariantList list;
        const QStringList elements = value.split(QLatin1Char(','));
        foreach (const QString &e, elements)
            list << QVariant(e);
        return QVariant(list);
    }
    return QVariant();
}

QString Operation::makeUnique(const QString &name, const QStringList &inUse)
{
    QString unique = name;
    int i = 1;
    while (inUse.contains(unique))
        unique = name + QString::number(++i);
    return unique;
}

Operation::KeyValuePair::KeyValuePair(const QString &k, const QString &v) :
    value(valueFromString(v))
{
    key = k.split(QLatin1Char('/'));
}

Operation::KeyValuePair::KeyValuePair(const QString &k, const QVariant &v) :
    value(v)
{
    key = k.split(QLatin1Char('/'));
}

Operation::KeyValuePair::KeyValuePair(const QStringList &k, const QString &v) :
    key(k), value(valueFromString(v))
{ }

Operation::KeyValuePair::KeyValuePair(const QStringList &k, const QVariant &v) :
    key(k), value(v)
{ }

QVariantMap Operation::load(const QString &file) const
{
    QVariantMap map;

    // Read values from original file:
    Utils::FileName path = Settings::instance()->getPath(file);
    if (path.toFileInfo().exists()) {
        Utils::PersistentSettingsReader reader;
        if (!reader.load(path))
            return QVariantMap();
        map = reader.restoreValues();
    }

    return map;
}

bool Operation::save(const QVariantMap &map, const QString &file) const
{
    Utils::FileName path = Settings::instance()->getPath(file);

    if (path.isEmpty()) {
        std::cerr << "Error: No path found for " << qPrintable(file) << "." << std::endl;
        return false;
    }

    Utils::FileName dir = path.parentDir();
    if (!dir.toFileInfo().exists())
        QDir(dir.toString()).mkpath(dir.toString());

    Utils::PersistentSettingsWriter writer(path, QLatin1String("unknown"));
    return writer.save(map, 0);
}
<commit_msg>SDKtool: Create group/world readable files<commit_after>/****************************************************************************
**
** Copyright (C) 2012 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 "operation.h"

#include "settings.h"

#include "utils/persistentsettings.h"

#include <QDir>
#include <QFile>

#include <iostream>

QVariant Operation::valueFromString(const QString &v)
{
    int pos = v.indexOf(QLatin1Char(':'));
    if (pos <= 0)
        return QVariant();
    const QString type = v.left(pos);
    const QString value = v.mid(pos + 1);

    if (type == QLatin1String("int")) {
        return QVariant(value.toInt());
    } else if (type == QLatin1String("bool")) {
        const QString tmp = value.toLower();
        return QVariant(tmp == QLatin1String("true") || tmp == QLatin1String("yes")
                        || tmp == QLatin1String("1") || tmp == QLatin1String("on"));
    } else if (type == QLatin1String("QByteArray")) {
        return QVariant(value.toLocal8Bit());
    } else if (type == QLatin1String("QString")) {
        return QVariant(value);
    } else if (type == QLatin1String("QVariantList")) {
        QVariantList list;
        const QStringList elements = value.split(QLatin1Char(','));
        foreach (const QString &e, elements)
            list << QVariant(e);
        return QVariant(list);
    }
    return QVariant();
}

QString Operation::makeUnique(const QString &name, const QStringList &inUse)
{
    QString unique = name;
    int i = 1;
    while (inUse.contains(unique))
        unique = name + QString::number(++i);
    return unique;
}

Operation::KeyValuePair::KeyValuePair(const QString &k, const QString &v) :
    value(valueFromString(v))
{
    key = k.split(QLatin1Char('/'));
}

Operation::KeyValuePair::KeyValuePair(const QString &k, const QVariant &v) :
    value(v)
{
    key = k.split(QLatin1Char('/'));
}

Operation::KeyValuePair::KeyValuePair(const QStringList &k, const QString &v) :
    key(k), value(valueFromString(v))
{ }

Operation::KeyValuePair::KeyValuePair(const QStringList &k, const QVariant &v) :
    key(k), value(v)
{ }

QVariantMap Operation::load(const QString &file) const
{
    QVariantMap map;

    // Read values from original file:
    Utils::FileName path = Settings::instance()->getPath(file);
    if (path.toFileInfo().exists()) {
        Utils::PersistentSettingsReader reader;
        if (!reader.load(path))
            return QVariantMap();
        map = reader.restoreValues();
    }

    return map;
}

bool Operation::save(const QVariantMap &map, const QString &file) const
{
    Utils::FileName path = Settings::instance()->getPath(file);

    if (path.isEmpty()) {
        std::cerr << "Error: No path found for " << qPrintable(file) << "." << std::endl;
        return false;
    }

    Utils::FileName dir = path.parentDir();
    if (!dir.toFileInfo().exists())
        QDir(dir.toString()).mkpath(dir.toString());

    Utils::PersistentSettingsWriter writer(path, QLatin1String("unknown"));
    return writer.save(map, 0)
            && QFile::setPermissions(path.toString(),
                                     QFile::ReadOwner | QFile::WriteOwner
                                     | QFile::ReadGroup | QFile::ReadOther);
}
<|endoftext|>