<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	transaction_base.cxx
 *
 *   DESCRIPTION
 *      common code and definitions for the transaction classes
 *   pqxx::transaction_base defines the interface for any abstract class that
 *   represents a database transaction
 *
 * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <stdexcept>

#include "pqxx/connection_base"
#include "pqxx/result"
#include "pqxx/tablestream"
#include "pqxx/transaction_base"

using namespace PGSTD;
using namespace pqxx::internal;

pqxx::transaction_base::transaction_base(connection_base &C,
    					 const string &TName,
					 const string &CName) :
  namedclass(TName, CName),
  m_Conn(C),
  m_UniqueCursorNum(1),
  m_Focus(),
  m_Status(st_nascent),
  m_Registered(false),
  m_PendingError()
{
  m_Conn.RegisterTransaction(this);
  m_Registered = true;
}

pqxx::transaction_base::~transaction_base()
{
  try
  {
    if (!m_PendingError.empty())
      process_notice("UNPROCESSED ERROR: " + m_PendingError + "\n");

    if (m_Registered)
    {
      m_Conn.process_notice(description() + " was never closed properly!\n");
      m_Conn.UnregisterTransaction(this);
    }
  }
  catch (const exception &e)
  {
    try
    {
      process_notice(string(e.what()) + "\n");
    }
    catch (const exception &)
    {
      process_notice(e.what());
    }
  }
}

void pqxx::transaction_base::commit()
{
  CheckPendingError();

  // Check previous status code.  Caller should only call this function if
  // we're in "implicit" state, but multiple commits are silently accepted.
  switch (m_Status)
  {
  case st_nascent:	// Empty transaction.  No skin off our nose.
    return;

  case st_active:	// Just fine.  This is what we expect.
    break;

  case st_aborted:
    throw logic_error("Attempt to commit previously aborted " + description());

  case st_committed:
    // Transaction has been committed already.  This is not exactly proper
    // behaviour, but throwing an exception here would only give the impression
    // that an abort is needed--which would only confuse things further at this
    // stage.
    // Therefore, multiple commits are accepted, though under protest.
    m_Conn.process_notice(description() + " committed more than once\n");
    return;

  case st_in_doubt:
    // Transaction may or may not have been committed.  Report the problem but
    // don't compound our troubles by throwing.
    throw logic_error(description() +
		      "committed again while in an undetermined state\n");

  default:
    throw logic_error("libpqxx internal error: pqxx::transaction: invalid status code");
  }

  // Tricky one.  If stream is nested in transaction but inside the same scope,
  // the Commit() will come before the stream is closed.  Which means the
  // commit is premature.  Punish this swiftly and without fail to discourage
  // the habit from forming.
  if (m_Focus.get())
    throw runtime_error("Attempt to commit " + description() + " "
			"with " + m_Focus.get()->description() + " "
			"still open");

  try
  {
    do_commit();
    m_Status = st_committed;
  }
  catch (const in_doubt_error &)
  {
    m_Status = st_in_doubt;
    throw;
  }
  catch (const exception &)
  {
    m_Status = st_aborted;
    throw;
  }

  m_Conn.AddVariables(m_Vars);

  End();
}

void pqxx::transaction_base::abort()
{
  // Check previous status code.  Quietly accept multiple aborts to
  // simplify emergency bailout code.
  switch (m_Status)
  {
  case st_nascent:	// Never began transaction.  No need to issue rollback.
    break;

  case st_active:
    try { do_abort(); } catch (const exception &) { }
    break;

  case st_aborted:
    return;

  case st_committed:
    throw logic_error("Attempt to abort previously committed " + description());

  case st_in_doubt:
    // Aborting an in-doubt transaction is probably a reasonably sane response
    // to an insane situation.  Log it, but do not complain.
    m_Conn.process_notice("Warning: " + description() + " "
		          "aborted after going into indeterminate state; "
			  "it may have been executed anyway.\n");
    return;

  default:
    throw logic_error("libpqxx internal error: invalid transaction status");
  }

  m_Status = st_aborted;
  End();
}

pqxx::result pqxx::transaction_base::exec(const char Query[],
    					  const string &Desc)
{
  CheckPendingError();

  const string N = (Desc.empty() ? "" : "'" + Desc + "' ");

  if (m_Focus.get())
    throw logic_error("Attempt to execute query " + N +
		      "on " + description() + " "
		      "with " + m_Focus.get()->description() + " "
		      "still open");

  switch (m_Status)
  {
  case st_nascent:
    // Make sure transaction has begun before executing anything
    Begin();
    break;

  case st_active:
    break;

  case st_committed:
    throw logic_error("Attempt to execute query " + N +
	              "in committed " + description());

  case st_aborted:
    throw logic_error("Attempt to execute query " + N +
	              "in aborted " + description());

  case st_in_doubt:
    throw logic_error("Attempt to execute query " + N + "in " +
		      description() + ", "
		      "which is in indeterminate state");
  default:
    throw logic_error("libpqxx internal error: pqxx::transaction: "
		      "invalid status code");
  }

  // TODO: Pass Desc to do_exec(), and from there on down
  return do_exec(Query);
}

void pqxx::transaction_base::set_variable(const string &Var,
                                          const string &Value)
{
  // Before committing to this new value, see what the backend thinks about it
  m_Conn.RawSetVar(Var, Value);
  m_Vars[Var] = Value;
}

string pqxx::transaction_base::get_variable(const string &Var) const
{
  const map<string,string>::const_iterator i = m_Vars.find(Var);
  if (i != m_Vars.end()) return i->second;
  return m_Conn.RawGetVar(Var);
}

void pqxx::transaction_base::Begin()
{
  if (m_Status != st_nascent)
    throw logic_error("libpqxx internal error: pqxx::transaction: "
		      "Begin() called while not in nascent state");

  try
  {
    // Better handle any pending notifications before we begin
    m_Conn.get_notifs();

    do_begin();
    m_Status = st_active;
  }
  catch (const exception &)
  {
    End();
    throw;
  }
}

void pqxx::transaction_base::End() throw ()
{
  if (!m_Registered) return;

  try
  {
    m_Conn.UnregisterTransaction(this);
    m_Registered = false;

    CheckPendingError();

    if (m_Focus.get())
      m_Conn.process_notice("Closing " + description() + " "
			    " with " + m_Focus.get()->description() + " "
			    "still open\n");

    if (m_Status == st_active) abort();
  }
  catch (const exception &e)
  {
    try
    {
      m_Conn.process_notice(string(e.what()) + "\n");
    }
    catch (const exception &)
    {
      m_Conn.process_notice(e.what());
    }
  }
}

void pqxx::transaction_base::RegisterFocus(transactionfocus *S)
{
  m_Focus.Register(S);
}

void pqxx::transaction_base::UnregisterFocus(transactionfocus *S) throw ()
{
  try
  {
    m_Focus.Unregister(S);
  }
  catch (const exception &e)
  {
    m_Conn.process_notice(string(e.what()) + "\n");
  }
}

pqxx::result pqxx::transaction_base::DirectExec(const char C[], int Retries)
{
  CheckPendingError();
  return m_Conn.Exec(C, Retries);
}

void pqxx::transaction_base::RegisterPendingError(const string &Err) throw ()
{
  if (m_PendingError.empty() && !Err.empty())
  {
    try
    {
      m_PendingError = Err;
    }
    catch (const exception &e)
    {
      try
      {
        process_notice("UNABLE TO PROCESS ERROR\n");
        process_notice(e.what());
        process_notice("ERROR WAS:");
        process_notice(Err);
      }
      catch (...)
      {
      }
    }
  }
}

void pqxx::transaction_base::CheckPendingError()
{
  if (!m_PendingError.empty())
  {
    const string Err(m_PendingError);
#ifdef PQXX_HAVE_STRING_CLEAR
    m_PendingError.clear();
#else
    m_PendingError.resize(0);
#endif
    throw runtime_error(m_PendingError);
  }
}

namespace
{
string MakeCopyString(const string &Table, const string &Columns)
{
  string Q = "COPY " + Table + " ";
  if (!Columns.empty()) Q += "(" + Columns + ") ";
  return Q;
}
} // namespace

void pqxx::transaction_base::BeginCopyRead(const string &Table,
    const string &Columns)
{
  exec(MakeCopyString(Table, Columns) + "TO STDOUT");
}

void pqxx::transaction_base::BeginCopyWrite(const string &Table,
    const string &Columns)
{
  exec(MakeCopyString(Table, Columns) + "FROM STDIN");
  m_Conn.go_async();
}

void pqxx::internal::transactionfocus::register_me()
{
  m_Trans.RegisterFocus(this);
  m_registered = true;
}

void pqxx::internal::transactionfocus::unregister_me() throw ()
{
  m_Trans.UnregisterFocus(this);
  m_registered = false;
}

void pqxx::internal::transactionfocus::reg_pending_error(const string &err) throw ()
{
  m_Trans.RegisterPendingError(err);
}

<commit_msg>Bugfix: no longer go async<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	transaction_base.cxx
 *
 *   DESCRIPTION
 *      common code and definitions for the transaction classes
 *   pqxx::transaction_base defines the interface for any abstract class that
 *   represents a database transaction
 *
 * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <stdexcept>

#include "pqxx/connection_base"
#include "pqxx/result"
#include "pqxx/tablestream"
#include "pqxx/transaction_base"

using namespace PGSTD;
using namespace pqxx::internal;

pqxx::transaction_base::transaction_base(connection_base &C,
    					 const string &TName,
					 const string &CName) :
  namedclass(TName, CName),
  m_Conn(C),
  m_UniqueCursorNum(1),
  m_Focus(),
  m_Status(st_nascent),
  m_Registered(false),
  m_PendingError()
{
  m_Conn.RegisterTransaction(this);
  m_Registered = true;
}

pqxx::transaction_base::~transaction_base()
{
  try
  {
    if (!m_PendingError.empty())
      process_notice("UNPROCESSED ERROR: " + m_PendingError + "\n");

    if (m_Registered)
    {
      m_Conn.process_notice(description() + " was never closed properly!\n");
      m_Conn.UnregisterTransaction(this);
    }
  }
  catch (const exception &e)
  {
    try
    {
      process_notice(string(e.what()) + "\n");
    }
    catch (const exception &)
    {
      process_notice(e.what());
    }
  }
}

void pqxx::transaction_base::commit()
{
  CheckPendingError();

  // Check previous status code.  Caller should only call this function if
  // we're in "implicit" state, but multiple commits are silently accepted.
  switch (m_Status)
  {
  case st_nascent:	// Empty transaction.  No skin off our nose.
    return;

  case st_active:	// Just fine.  This is what we expect.
    break;

  case st_aborted:
    throw logic_error("Attempt to commit previously aborted " + description());

  case st_committed:
    // Transaction has been committed already.  This is not exactly proper
    // behaviour, but throwing an exception here would only give the impression
    // that an abort is needed--which would only confuse things further at this
    // stage.
    // Therefore, multiple commits are accepted, though under protest.
    m_Conn.process_notice(description() + " committed more than once\n");
    return;

  case st_in_doubt:
    // Transaction may or may not have been committed.  Report the problem but
    // don't compound our troubles by throwing.
    throw logic_error(description() +
		      "committed again while in an undetermined state\n");

  default:
    throw logic_error("libpqxx internal error: pqxx::transaction: invalid status code");
  }

  // Tricky one.  If stream is nested in transaction but inside the same scope,
  // the Commit() will come before the stream is closed.  Which means the
  // commit is premature.  Punish this swiftly and without fail to discourage
  // the habit from forming.
  if (m_Focus.get())
    throw runtime_error("Attempt to commit " + description() + " "
			"with " + m_Focus.get()->description() + " "
			"still open");

  try
  {
    do_commit();
    m_Status = st_committed;
  }
  catch (const in_doubt_error &)
  {
    m_Status = st_in_doubt;
    throw;
  }
  catch (const exception &)
  {
    m_Status = st_aborted;
    throw;
  }

  m_Conn.AddVariables(m_Vars);

  End();
}

void pqxx::transaction_base::abort()
{
  // Check previous status code.  Quietly accept multiple aborts to
  // simplify emergency bailout code.
  switch (m_Status)
  {
  case st_nascent:	// Never began transaction.  No need to issue rollback.
    break;

  case st_active:
    try { do_abort(); } catch (const exception &) { }
    break;

  case st_aborted:
    return;

  case st_committed:
    throw logic_error("Attempt to abort previously committed " + description());

  case st_in_doubt:
    // Aborting an in-doubt transaction is probably a reasonably sane response
    // to an insane situation.  Log it, but do not complain.
    m_Conn.process_notice("Warning: " + description() + " "
		          "aborted after going into indeterminate state; "
			  "it may have been executed anyway.\n");
    return;

  default:
    throw logic_error("libpqxx internal error: invalid transaction status");
  }

  m_Status = st_aborted;
  End();
}

pqxx::result pqxx::transaction_base::exec(const char Query[],
    					  const string &Desc)
{
  CheckPendingError();

  const string N = (Desc.empty() ? "" : "'" + Desc + "' ");

  if (m_Focus.get())
    throw logic_error("Attempt to execute query " + N +
		      "on " + description() + " "
		      "with " + m_Focus.get()->description() + " "
		      "still open");

  switch (m_Status)
  {
  case st_nascent:
    // Make sure transaction has begun before executing anything
    Begin();
    break;

  case st_active:
    break;

  case st_committed:
    throw logic_error("Attempt to execute query " + N +
	              "in committed " + description());

  case st_aborted:
    throw logic_error("Attempt to execute query " + N +
	              "in aborted " + description());

  case st_in_doubt:
    throw logic_error("Attempt to execute query " + N + "in " +
		      description() + ", "
		      "which is in indeterminate state");
  default:
    throw logic_error("libpqxx internal error: pqxx::transaction: "
		      "invalid status code");
  }

  // TODO: Pass Desc to do_exec(), and from there on down
  return do_exec(Query);
}

void pqxx::transaction_base::set_variable(const string &Var,
                                          const string &Value)
{
  // Before committing to this new value, see what the backend thinks about it
  m_Conn.RawSetVar(Var, Value);
  m_Vars[Var] = Value;
}

string pqxx::transaction_base::get_variable(const string &Var) const
{
  const map<string,string>::const_iterator i = m_Vars.find(Var);
  if (i != m_Vars.end()) return i->second;
  return m_Conn.RawGetVar(Var);
}

void pqxx::transaction_base::Begin()
{
  if (m_Status != st_nascent)
    throw logic_error("libpqxx internal error: pqxx::transaction: "
		      "Begin() called while not in nascent state");

  try
  {
    // Better handle any pending notifications before we begin
    m_Conn.get_notifs();

    do_begin();
    m_Status = st_active;
  }
  catch (const exception &)
  {
    End();
    throw;
  }
}

void pqxx::transaction_base::End() throw ()
{
  if (!m_Registered) return;

  try
  {
    m_Conn.UnregisterTransaction(this);
    m_Registered = false;

    CheckPendingError();

    if (m_Focus.get())
      m_Conn.process_notice("Closing " + description() + " "
			    " with " + m_Focus.get()->description() + " "
			    "still open\n");

    if (m_Status == st_active) abort();
  }
  catch (const exception &e)
  {
    try
    {
      m_Conn.process_notice(string(e.what()) + "\n");
    }
    catch (const exception &)
    {
      m_Conn.process_notice(e.what());
    }
  }
}

void pqxx::transaction_base::RegisterFocus(transactionfocus *S)
{
  m_Focus.Register(S);
}

void pqxx::transaction_base::UnregisterFocus(transactionfocus *S) throw ()
{
  try
  {
    m_Focus.Unregister(S);
  }
  catch (const exception &e)
  {
    m_Conn.process_notice(string(e.what()) + "\n");
  }
}

pqxx::result pqxx::transaction_base::DirectExec(const char C[], int Retries)
{
  CheckPendingError();
  return m_Conn.Exec(C, Retries);
}

void pqxx::transaction_base::RegisterPendingError(const string &Err) throw ()
{
  if (m_PendingError.empty() && !Err.empty())
  {
    try
    {
      m_PendingError = Err;
    }
    catch (const exception &e)
    {
      try
      {
        process_notice("UNABLE TO PROCESS ERROR\n");
        process_notice(e.what());
        process_notice("ERROR WAS:");
        process_notice(Err);
      }
      catch (...)
      {
      }
    }
  }
}

void pqxx::transaction_base::CheckPendingError()
{
  if (!m_PendingError.empty())
  {
    const string Err(m_PendingError);
#ifdef PQXX_HAVE_STRING_CLEAR
    m_PendingError.clear();
#else
    m_PendingError.resize(0);
#endif
    throw runtime_error(m_PendingError);
  }
}

namespace
{
string MakeCopyString(const string &Table, const string &Columns)
{
  string Q = "COPY " + Table + " ";
  if (!Columns.empty()) Q += "(" + Columns + ") ";
  return Q;
}
} // namespace

void pqxx::transaction_base::BeginCopyRead(const string &Table,
    const string &Columns)
{
  exec(MakeCopyString(Table, Columns) + "TO STDOUT");
}

void pqxx::transaction_base::BeginCopyWrite(const string &Table,
    const string &Columns)
{
  exec(MakeCopyString(Table, Columns) + "FROM STDIN");
}

void pqxx::internal::transactionfocus::register_me()
{
  m_Trans.RegisterFocus(this);
  m_registered = true;
}

void pqxx::internal::transactionfocus::unregister_me() throw ()
{
  m_Trans.UnregisterFocus(this);
  m_registered = false;
}

void
pqxx::internal::transactionfocus::reg_pending_error(const string &err) throw ()
{
  m_Trans.RegisterPendingError(err);
}

<|endoftext|>


<commit_before>/*******************************************************************************
 * pxgsettings - A helper binary to query gsettings
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 * Copyright (C) 2011 Dominique Leuenberger <dominique@leuenberger.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include <cstdio>
#include <unistd.h>
#include <signal.h>
#include <stdexcept>

#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>

using namespace std;

static GMainLoop* loop = NULL;

static int print_value(GVariant *value, const char *suffix) {

	if (!value) return 0;
	if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
		return printf("%s%s", g_variant_get_string(value, NULL), suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
		return printf("%d%s", g_variant_get_int32(value), suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) {
		gboolean result;
		result = g_variant_get_boolean(value);
		return printf("%s%s", result ? "true" : "false",  suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
		int count;
		const gchar** items;
		items = g_variant_get_strv(value, NULL);
		for (count=0; items[count]; count++) {
			printf("%s%s", count < 1 ? "" : ",",  items[count]);
		}
		printf("%s", suffix);
		return count;
	}
	else {
		throw exception();
	}

	return 0;
}

static void on_value_change(GSettings *settings, const gchar *key, gpointer user_data) {
	printf("%s/%s\t", (gchar *)user_data, key);
	print_value(g_settings_get_value(settings, key), "\n");
}

static void on_sig(int /*signal*/) {
	g_main_loop_quit(loop);
}

static gboolean err(GIOChannel* /*source*/, GIOCondition /*condition*/, gpointer /*data*/) {
	g_main_loop_quit(loop);
	return false;
}

static gboolean in(GIOChannel *source, GIOCondition condition, gpointer data) {
	gchar *key, *val;
	GIOStatus st = g_io_channel_read_line(source, &key, NULL, NULL, NULL);

	// Remove the trailing '\n'
	for (int i=0 ; key && key[i] ; i++)
		if (key[i] == '\n')
			key[i] = '\0';

	// If we were successful
	if (key && st == G_IO_STATUS_NORMAL) {
		if (!g_strrstr(key, "\t"))
			goto exit;

		val = g_strrstr(key, "\t") + 1;
		*(val-1) = '\0';

		g_free(key);
		return true;
	}
	else if (key && st == G_IO_STATUS_AGAIN) {
		g_free(key);
		return in(source, condition, data);
	}

exit:
	g_free(key);
	return err(source, condition, data);
}

int main(int argc, char **argv) {
	if (argc < 2) return 1;

	// Register sighup handler
	if (signal(SIGHUP, on_sig) == SIG_ERR || signal(SIGPIPE, on_sig) == SIG_ERR || signal(SIGABRT, on_sig) == SIG_ERR) {
		fprintf(stderr, "Unable to trap signals!");
		return 2;
	}

	// Switch stdout to line buffering
	if (setvbuf(stdout, NULL, _IOLBF, 0)) {
		fprintf(stderr, "Unable to switch stdout to line buffering!");
		return 3;
	}

	// Switch stdin to line buffering
	if (setvbuf(stdin, NULL, _IOLBF, 0)) {
		fprintf(stderr, "Unable to switch stdin to line buffering!");
		return 4;
	}

	// Init
#if !GLIB_CHECK_VERSION(2,36,0)
	g_type_init();
#endif

	// Get the main loop
	loop = g_main_loop_new(NULL, false);

	// Setup our GIO Channels
	GIOChannel* inchan  = g_io_channel_unix_new(fileno(stdin));
	GIOChannel* outchan = g_io_channel_unix_new(fileno(stdout));
	g_io_add_watch(inchan,  G_IO_IN,  in, NULL);
	g_io_add_watch(inchan,  G_IO_PRI, in, NULL);
	g_io_add_watch(inchan,  G_IO_ERR, err, NULL);
	g_io_add_watch(inchan,  G_IO_HUP, err, NULL);
	g_io_add_watch(outchan, G_IO_ERR, err, NULL);
	g_io_add_watch(outchan, G_IO_HUP, err, NULL);

	// Get GSettings obkecy
	GSettings* settings;

	for (int i=1; i<argc; i++) {
		settings = g_settings_new(argv[i]);
#if GLIB_CHECK_VERSION(2,46,0)
		GSettingsSchema *schema;
		g_object_get (settings, "settings-schema", &schema, NULL);
		gchar** keys = g_settings_schema_list_keys(schema);
		g_settings_schema_unref(schema);
#else
		gchar** keys = g_settings_list_keys(settings);
#endif
		g_signal_connect(settings, "changed::", G_CALLBACK (on_value_change), argv[i]);
		for (int j=0; keys[j]; on_value_change(settings, keys[j++],argv[i] ));
		g_strfreev(keys);
	}

	g_main_loop_run(loop);

	// Cleanup
	g_object_unref(settings);
	g_io_channel_shutdown(inchan,  FALSE, NULL);
	g_io_channel_shutdown(outchan, FALSE, NULL);
	g_io_channel_unref(inchan);
	g_io_channel_unref(outchan);
	g_main_loop_unref(loop);
}
<commit_msg>pxgsettings: use the correct syntax to connect to the changed signal<commit_after>/*******************************************************************************
 * pxgsettings - A helper binary to query gsettings
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 * Copyright (C) 2011 Dominique Leuenberger <dominique@leuenberger.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include <cstdio>
#include <unistd.h>
#include <signal.h>
#include <stdexcept>

#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>

using namespace std;

static GMainLoop* loop = NULL;

static int print_value(GVariant *value, const char *suffix) {

	if (!value) return 0;
	if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
		return printf("%s%s", g_variant_get_string(value, NULL), suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
		return printf("%d%s", g_variant_get_int32(value), suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) {
		gboolean result;
		result = g_variant_get_boolean(value);
		return printf("%s%s", result ? "true" : "false",  suffix);
	}
	else if(g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
		int count;
		const gchar** items;
		items = g_variant_get_strv(value, NULL);
		for (count=0; items[count]; count++) {
			printf("%s%s", count < 1 ? "" : ",",  items[count]);
		}
		printf("%s", suffix);
		return count;
	}
	else {
		throw exception();
	}

	return 0;
}

static void on_value_change(GSettings *settings, const gchar *key, gpointer user_data) {
	printf("%s/%s\t", (gchar *)user_data, key);
	print_value(g_settings_get_value(settings, key), "\n");
}

static void on_sig(int /*signal*/) {
	g_main_loop_quit(loop);
}

static gboolean err(GIOChannel* /*source*/, GIOCondition /*condition*/, gpointer /*data*/) {
	g_main_loop_quit(loop);
	return false;
}

static gboolean in(GIOChannel *source, GIOCondition condition, gpointer data) {
	gchar *key, *val;
	GIOStatus st = g_io_channel_read_line(source, &key, NULL, NULL, NULL);

	// Remove the trailing '\n'
	for (int i=0 ; key && key[i] ; i++)
		if (key[i] == '\n')
			key[i] = '\0';

	// If we were successful
	if (key && st == G_IO_STATUS_NORMAL) {
		if (!g_strrstr(key, "\t"))
			goto exit;

		val = g_strrstr(key, "\t") + 1;
		*(val-1) = '\0';

		g_free(key);
		return true;
	}
	else if (key && st == G_IO_STATUS_AGAIN) {
		g_free(key);
		return in(source, condition, data);
	}

exit:
	g_free(key);
	return err(source, condition, data);
}

int main(int argc, char **argv) {
	if (argc < 2) return 1;

	// Register sighup handler
	if (signal(SIGHUP, on_sig) == SIG_ERR || signal(SIGPIPE, on_sig) == SIG_ERR || signal(SIGABRT, on_sig) == SIG_ERR) {
		fprintf(stderr, "Unable to trap signals!");
		return 2;
	}

	// Switch stdout to line buffering
	if (setvbuf(stdout, NULL, _IOLBF, 0)) {
		fprintf(stderr, "Unable to switch stdout to line buffering!");
		return 3;
	}

	// Switch stdin to line buffering
	if (setvbuf(stdin, NULL, _IOLBF, 0)) {
		fprintf(stderr, "Unable to switch stdin to line buffering!");
		return 4;
	}

	// Init
#if !GLIB_CHECK_VERSION(2,36,0)
	g_type_init();
#endif

	// Get the main loop
	loop = g_main_loop_new(NULL, false);

	// Setup our GIO Channels
	GIOChannel* inchan  = g_io_channel_unix_new(fileno(stdin));
	GIOChannel* outchan = g_io_channel_unix_new(fileno(stdout));
	g_io_add_watch(inchan,  G_IO_IN,  in, NULL);
	g_io_add_watch(inchan,  G_IO_PRI, in, NULL);
	g_io_add_watch(inchan,  G_IO_ERR, err, NULL);
	g_io_add_watch(inchan,  G_IO_HUP, err, NULL);
	g_io_add_watch(outchan, G_IO_ERR, err, NULL);
	g_io_add_watch(outchan, G_IO_HUP, err, NULL);

	// Get GSettings obkecy
	GSettings* settings;

	for (int i=1; i<argc; i++) {
		settings = g_settings_new(argv[i]);
#if GLIB_CHECK_VERSION(2,46,0)
		GSettingsSchema *schema;
		g_object_get (settings, "settings-schema", &schema, NULL);
		gchar** keys = g_settings_schema_list_keys(schema);
		g_settings_schema_unref(schema);
#else
		gchar** keys = g_settings_list_keys(settings);
#endif
		g_signal_connect(settings, "changed", G_CALLBACK (on_value_change), argv[i]);
		for (int j=0; keys[j]; on_value_change(settings, keys[j++],argv[i] ));
		g_strfreev(keys);
	}

	g_main_loop_run(loop);

	// Cleanup
	g_object_unref(settings);
	g_io_channel_shutdown(inchan,  FALSE, NULL);
	g_io_channel_shutdown(outchan, FALSE, NULL);
	g_io_channel_unref(inchan);
	g_io_channel_unref(outchan);
	g_main_loop_unref(loop);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 The Project Oak Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "absl/types/optional.h"
#include "examples/trusted_information_retrieval/proto/trusted_information_retrieval.grpc.pb.h"
#include "examples/trusted_information_retrieval/proto/trusted_information_retrieval.pb.h"
#include "glog/logging.h"
#include "include/grpcpp/grpcpp.h"
#include "oak/client/application_client.h"

ABSL_FLAG(std::string, address, "localhost:8080", "Address of the Oak application to connect to");
ABSL_FLAG(std::vector<std::string>, location, std::vector<std::string>{},
          "Requested location (latitude and longitude separated by comma)");
ABSL_FLAG(std::string, ca_cert, "", "Path to the PEM-encoded CA root certificate");

using ::oak::examples::trusted_information_retrieval::ListPointsOfInterestRequest;
using ::oak::examples::trusted_information_retrieval::ListPointsOfInterestResponse;
using ::oak::examples::trusted_information_retrieval::Location;
using ::oak::examples::trusted_information_retrieval::PointOfInterest;
using ::oak::examples::trusted_information_retrieval::TrustedInformationRetrieval;

void get_nearest_point_of_interest(TrustedInformationRetrieval::Stub* stub, float latitude,
                                   float longitude) {
  grpc::ClientContext context;
  LOG(INFO) << "Getting nearest point of interest:";
  ListPointsOfInterestRequest request;
  Location* location = request.mutable_location();
  location->set_latitude(latitude);
  location->set_longitude(longitude);
  ListPointsOfInterestResponse response;
  grpc::Status status = stub->ListPointsOfInterest(&context, request, &response);
  if (!status.ok()) {
    LOG(ERROR) << "Could not get nearest point of interest: " << status.error_code() << ": "
               << status.error_message();
  }
  LOG(INFO) << "Response:";
  LOG(INFO) << " - name: " << response.point_of_interest().name();
  LOG(INFO) << " - latitude: " << response.point_of_interest().location().latitude();
  LOG(INFO) << " - longitude: " << response.point_of_interest().location().longitude();
}

int main(int argc, char** argv) {
  absl::ParseCommandLine(argc, argv);

  std::string address = absl::GetFlag(FLAGS_address);
  std::string ca_cert = oak::ApplicationClient::LoadRootCert(absl::GetFlag(FLAGS_ca_cert));
  LOG(INFO) << "Connecting to Oak Application: " << address;

  auto stub = TrustedInformationRetrieval::NewStub(
      oak::ApplicationClient::CreateTlsChannel(address, ca_cert));

  // Parse arguments.
  auto location = absl::GetFlag(FLAGS_location);
  if (location.size() != 2) {
    LOG(FATAL) << "Incorrect number of coordinates: " << location.size() << " (expected 2)";
  }
  float latitude;
  if (!absl::SimpleAtof(location.front(), &latitude) && latitude >= -90.0 && latitude <= 90.0) {
    LOG(FATAL) << "Latitude must be a valid floating point number >=-90 and <= 90.";
  }
  float longitude;
  if (!absl::SimpleAtof(location.back(), &longitude) && longitude >= -180.0 && longitude <= 180.0) {
    LOG(FATAL) << "Longitude must be a valid floating point number >= -180 and <= 180.";
  }

  // Get nearest point of interest from the server.
  get_nearest_point_of_interest(stub.get(), latitude, longitude);

  return EXIT_SUCCESS;
}
<commit_msg>Use labels in TIR (#1073)<commit_after>/*
 * Copyright 2020 The Project Oak Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "absl/types/optional.h"
#include "examples/trusted_information_retrieval/proto/trusted_information_retrieval.grpc.pb.h"
#include "examples/trusted_information_retrieval/proto/trusted_information_retrieval.pb.h"
#include "glog/logging.h"
#include "include/grpcpp/grpcpp.h"
#include "oak/client/application_client.h"

ABSL_FLAG(std::string, address, "localhost:8080", "Address of the Oak application to connect to");
ABSL_FLAG(std::vector<std::string>, location, std::vector<std::string>{},
          "Requested location (latitude and longitude separated by comma)");
ABSL_FLAG(std::string, ca_cert, "", "Path to the PEM-encoded CA root certificate");

using ::oak::examples::trusted_information_retrieval::ListPointsOfInterestRequest;
using ::oak::examples::trusted_information_retrieval::ListPointsOfInterestResponse;
using ::oak::examples::trusted_information_retrieval::Location;
using ::oak::examples::trusted_information_retrieval::PointOfInterest;
using ::oak::examples::trusted_information_retrieval::TrustedInformationRetrieval;

void get_nearest_point_of_interest(TrustedInformationRetrieval::Stub* stub, float latitude,
                                   float longitude) {
  grpc::ClientContext context;
  LOG(INFO) << "Getting nearest point of interest:";
  ListPointsOfInterestRequest request;
  Location* location = request.mutable_location();
  location->set_latitude(latitude);
  location->set_longitude(longitude);
  ListPointsOfInterestResponse response;
  grpc::Status status = stub->ListPointsOfInterest(&context, request, &response);
  if (!status.ok()) {
    LOG(ERROR) << "Could not get nearest point of interest: " << status.error_code() << ": "
               << status.error_message();
  }
  LOG(INFO) << "Response:";
  LOG(INFO) << " - name: " << response.point_of_interest().name();
  LOG(INFO) << " - latitude: " << response.point_of_interest().location().latitude();
  LOG(INFO) << " - longitude: " << response.point_of_interest().location().longitude();
}

int main(int argc, char** argv) {
  absl::ParseCommandLine(argc, argv);

  std::string address = absl::GetFlag(FLAGS_address);
  std::string ca_cert = oak::ApplicationClient::LoadRootCert(absl::GetFlag(FLAGS_ca_cert));
  LOG(INFO) << "Connecting to Oak Application: " << address;

  // TODO(#1066): Use a more restrictive Label.
  oak::label::Label label = oak::PublicUntrustedLabel();
  // Connect to the Oak Application.
  auto stub = TrustedInformationRetrieval::NewStub(oak::ApplicationClient::CreateChannel(
      address, oak::ApplicationClient::GetTlsChannelCredentials(ca_cert), label));
  if (stub == nullptr) {
    LOG(FATAL) << "Failed to create application stub";
  }

  // Parse arguments.
  auto location = absl::GetFlag(FLAGS_location);
  if (location.size() != 2) {
    LOG(FATAL) << "Incorrect number of coordinates: " << location.size() << " (expected 2)";
  }
  float latitude;
  if (!absl::SimpleAtof(location.front(), &latitude) && latitude >= -90.0 && latitude <= 90.0) {
    LOG(FATAL) << "Latitude must be a valid floating point number >=-90 and <= 90.";
  }
  float longitude;
  if (!absl::SimpleAtof(location.back(), &longitude) && longitude >= -180.0 && longitude <= 180.0) {
    LOG(FATAL) << "Longitude must be a valid floating point number >= -180 and <= 180.";
  }

  // Get nearest point of interest from the server.
  get_nearest_point_of_interest(stub.get(), latitude, longitude);

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>Skip ExternalWrapTest on Ozone.<commit_after><|endoftext|>


<commit_before><commit_msg>Fix compiler warnings.<commit_after><|endoftext|>


<commit_before>/*
 * Reference: http://plms.oxfordjournals.org/content/s2-42/1/230.full.pdf+html
 *
 * Instruction set
 * ===============
 * m-config   symbol   operations   final m-config
 * string     char     op1,op2,...  string
 *
 * op:
 *   L - move left one step
 *   R - move right one step
 *   P<symbol> - print symbol on tap
 *   E - erase symbol from tap
 * symbol:
 *   ~ - matches blank cell
 *   * - matches any symbol
 *   other char matches themselves
 *
 * Lines starting with # are ignored by the interpreter
 */

#include <iostream>
#include <string>
#include <regex>
#include <map>
#include <vector>
#include <queue>

using namespace std;

struct Configuration {
    string state;
    char symbol;
    bool operator<(const Configuration &o) const {
        return state < o.state || (state == o.state && symbol < o.symbol);
    }
};

struct Action {
    string ops;
    string state;
};

string start;
map< Configuration, Action > program;
map< int, char > tape;

void load_program() {
    cin.sync_with_stdio(false);
    string line;
    while (getline(cin, line)) {
        // skip empty lines
        if (line.length() == 0) {
            continue;
        }

        // lines begining with # are comments
        if (line.at(0) == '#') {
            continue;
        }

        istringstream iss(line);
        string state, symbol, ops, fstate;
        iss >> state >> symbol >> ops >> fstate;

        if (start.length() == 0) {
            start = state;
        }

        Configuration c = {state, symbol.at(0)};
        Action a = {ops, fstate};
        program[c] = a;
    }
}

void print_program() {
    for (auto it=program.begin(); it != program.end(); it++) {
        cout << it->first.state << " ";
        cout << it->first.symbol << " ";
        cout << it->second.ops << " ";
        cout << it->second.state << endl;
    }
}

void print_tape() {
    cout << "tape: ";
    for (auto it=tape.begin(); it != tape.end(); it++) {
        cout << it->second;
    }
    cout << endl;
}

void print_config(Configuration c) {
    cout << "conf: " << c.state << " " << c.symbol << endl;
}

char read_tape(int tp) {
    if (tape.count(tp)) {
        return tape[tp];
    } else {
        return '~';
    }
}

int perform_ops(int tp, string ops) {
    for (int i = 0; i < ops.length(); i++) {
        char op = ops.at(i);
        switch (op) {
            case 'R':
                tp++;
                break;
            case 'L':
                tp--;
                break;
            case 'E':
                tape[tp] = '~';
                break;
            case 'P':
                i++;
                tape[tp] = ops.at(i);
            case ',':
                break;
            default:
                cout << "unknown op: " << op << endl;
                exit(1);
        }
    }
    return tp;
}

void eval(string curr, int tp, int max) {
    int cnt = 0;
    while (cnt < max) {
        cnt++;
        char s = read_tape(tp);
        Configuration c = {curr, s};
        if (program.count(c) == 0) {
            c = {curr, '*'};
        }
        if (program.count(c) == 0) {
            break;
        }
        Action a = program[c];
        tp = perform_ops(tp, a.ops);
        curr = a.state;
        print_config(c);
        print_tape();
    }
}

int main(int argc, char *argv[]) {
    load_program();
    print_program();
    eval(start, 0, 1000);
    print_tape();
    return 0;
}
<commit_msg>move globals into struct Machine<commit_after>/*
 * Reference: http://plms.oxfordjournals.org/content/s2-42/1/230.full.pdf+html
 *
 * Instruction set
 * ===============
 * m-config   symbol   operations   final m-config
 * string     char     op1,op2,...  string
 *
 * op:
 *   L - move left one step
 *   R - move right one step
 *   P<symbol> - print symbol on tap
 *   E - erase symbol from tap
 * symbol:
 *   ~ - matches blank cell
 *   * - matches any symbol
 *   other char matches themselves
 *
 * Lines starting with # are ignored by the interpreter
 */

#include <iostream>
#include <string>
#include <regex>
#include <map>
#include <vector>
#include <queue>

using namespace std;

struct Configuration {
    string state;
    char symbol;
    bool operator<(const Configuration &o) const {
        return state < o.state || (state == o.state && symbol < o.symbol);
    }
};

struct Action {
    string ops;
    string state;
};

struct Machine {
    int tp = 0;
    string start;
    map< Configuration, Action > program;
    map< int, char > tape;
};

void load_program(Machine &m) {
    cin.sync_with_stdio(false);
    string line;
    while (getline(cin, line)) {
        // skip empty lines
        if (line.length() == 0) {
            continue;
        }

        // lines begining with # are comments
        if (line.at(0) == '#') {
            continue;
        }

        istringstream iss(line);
        string state, symbol, ops, fstate;
        iss >> state >> symbol >> ops >> fstate;

        if (m.start.length() == 0) {
            m.start = state;
        }

        Configuration c = {state, symbol.at(0)};
        Action a = {ops, fstate};
        m.program[c] = a;
    }
}

void print_program(const Machine &m) {
    for (auto it=m.program.begin(); it != m.program.end(); it++) {
        cout << it->first.state << " ";
        cout << it->first.symbol << " ";
        cout << it->second.ops << " ";
        cout << it->second.state << endl;
    }
}

void print_tape(const Machine &m) {
    cout << "tape: ";
    for (auto it=m.tape.begin(); it != m.tape.end(); it++) {
        cout << it->second;
    }
    cout << endl;
}

void print_config(Configuration c) {
    cout << "conf: " << c.state << " " << c.symbol << endl;
}

char read_tape(Machine &m, int tp) {
    if (m.tape.count(tp)) {
        return m.tape[tp];
    } else {
        return '~';
    }
}

int perform_ops(Machine &m, int tp, string ops) {
    for (int i = 0; i < ops.length(); i++) {
        char op = ops.at(i);
        switch (op) {
            case 'R':
                tp++;
                break;
            case 'L':
                tp--;
                break;
            case 'E':
                m.tape[tp] = '~';
                break;
            case 'P':
                i++;
                m.tape[tp] = ops.at(i);
            case ',':
                break;
            default:
                cout << "unknown op: " << op << endl;
                exit(1);
        }
    }
    return tp;
}

void eval(Machine &m, int max) {
    string curr = m.start;
    int cnt = 0;
    while (cnt < max) {
        cnt++;
        char s = read_tape(m, m.tp);
        Configuration c = {curr, s};
        if (m.program.count(c) == 0) {
            c = {curr, '*'};
        }
        if (m.program.count(c) == 0) {
            break;
        }
        Action a = m.program[c];
        m.tp = perform_ops(m, m.tp, a.ops);
        curr = a.state;
        print_config(c);
        print_tape(m);
    }
}

int main(int argc, char *argv[]) {
    Machine m;
    load_program(m);
    print_program(m);
    eval(m, 1000);
    print_tape(m);
    return 0;
}
<|endoftext|>


<commit_before>/*
 * TTBlue Global Object
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTFoundation.h"
#include "TTEnvironment.h"
#include "TTClass.h"

#define thisTTClass TTEnvironment

// The environment object has one instance, which is global in scope.
TTEnvironment*	ttEnvironment = NULL;

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

TTEnvironment::TTEnvironment()
	: TTObject(kTTValNONE), debugBasic(false), debugMessaging(false), sr(0)
{
	classes = new TTHash();
	tags = new TTHash();

	registerAttributeSimple(debugBasic,		kTypeBoolean);
	registerAttributeSimple(debugMessaging,	kTypeBoolean);
	registerAttributeSimple(sr,				kTypeUInt32);

	registerMessageWithArgument(getVersion);

	setAttributeValue(TT("sr"), TTUInt32(44100));
}

TTEnvironment::~TTEnvironment()
{
	// If on Windows, we need to call FreeLibrary() on all plug-ins loaded with LoadLibrary()
	// On the Mac, we may need to do the equivalent

	delete tags;
	delete classes;
}

TTErr TTEnvironment::getVersion(TTValue &value)
{
	value = TTFOUNDATION_VERSION_STRING;
	return kTTErrNone;
}

TTErr TTEnvironment::registerClass(const TTSymbolPtr className, const TTString& tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	TTValue		v((TTString&)tagString);	// The tags to be associated with the class we are registering.
	TTValue		tagObjects;					// Contains a TTList of objects in the environment with the given tag.
	TTClassPtr	theClass;
	TTErr		err;
	TTList*		classNamesForTag;			// The TTList contained by tagObjects
	TTUInt16	size;
	TTSymbolPtr	tag;
	TTValue		result;

	err = classes->lookup(className, result);

	// If a class is already registered with this name, then we do not want to register another class with the same name!
	if (err == kTTErrValueNotFound) {

		// 1. Turn the string into an array of symbols
		v.transformCSVStringToSymbolArray();

		// 2. Create the class and associate it with its name
		theClass = new TTClass(className, v, anInstantiationMethod);

		// 3. For each symbol in the TTValue array...
		size = v.getSize();
		for (TTUInt16 i=0; i<size; i++) {
			v.get(i, &tag);

			// 4. Look to see if this tag exists yet
			err = tags->lookup(tag, tagObjects);
			if (!err) {
				classNamesForTag = (TTList*)(TTPtr(tagObjects));

				// TODO: The following code demonstrates so extreme lameness that we need to evaluate.
				//	First, we should probably just do this section of code with TTValue instead of TTList (but we needed code to test TTList)
				//	Second, TTList is taking references but keeping things internally as pointers, which leads to lots of confusion
				//	Third, we have to pass objects that are permanent - so no temporaries are allowed unless we make TTList do a copy
				//	etc.

				// TODO: We need to factor out a function to add a tag for a named class (or a given class ptr)

				//classNamesForTag->append(className);
				classNamesForTag->append(*new TTValue(className));
			}
			else {
				classNamesForTag = new TTList;
				tagObjects = TTPtr(classNamesForTag);
				tags->append(tag ,tagObjects);
				classNamesForTag->append(*new TTValue(className));
			}
		}

		// 4. Register it
		err = registerClass(theClass);
	}
	return err;
}

TTErr TTEnvironment::registerClass(TTClassPtr theClass)
{
	return classes->append(theClass->name, TTPtr(theClass));
}

TTErr TTEnvironment::getAllClassNames(TTValue& returnedClassNames)
{
	return classes->getKeys(returnedClassNames);
}

TTErr TTEnvironment::getClassNamesWithTags(TTValue& classNames, const TTValue& searchTags)
{
	// TODO: right now we only look for the first tag, we should look for each and then do a union on the results.
	// Well, that's not what's really happening, but the point is that this really only works if we are searching for one tag.

	TTUInt16	size = searchTags.getSize();
	TTSymbolPtr	tag;
	TTValue		tagObjects;
	TTErr		err = kTTErrGeneric;
	TTList*		classNamesForTag;

	for(TTUInt16 i=0; i<size; i++){
		searchTags.get(i, &tag);

		err = tags->lookup(tag, tagObjects);
		if(!err){
			classNamesForTag = (TTList*)(TTPtr(tagObjects));
			classNamesForTag->assignToValue(classNames);
		}
	}

	return err;
}

TTErr TTEnvironment::createInstance(const TTSymbolPtr className, TTObjectPtr* anObject, const TTValue& anArgument)
{
	return createInstance(className, anObject, (TTValue&)anArgument); // throw away the const (I know, I know...), maybe the non-const constructor shouldn't exist at all?
}

TTErr TTEnvironment::createInstance(const TTSymbolPtr className, TTObjectPtr* anObject, TTValue& anArgument)
{
	TTValue		v;
	TTClassPtr	theClass;
	TTErr		err;
	TTObjectPtr	newObject = NULL;
	TTObjectPtr	oldObject = NULL;

	err = classes->lookup(className, v);
	if(!err){
		theClass = TTClassPtr(TTPtr(v));
		if(theClass)
			err = theClass->createInstance(&newObject, anArgument);
		else
			err = kTTErrGeneric;
	}

	if(!err && newObject){
		if(*anObject)
			oldObject = *anObject;
		*anObject = newObject;
		if(oldObject)
			releaseInstance(&oldObject);

		(*anObject)->classPtr = theClass;
		(*anObject)->valid = true;
	}

	//TODO: Add instance tracking.  For each instance of a class, we push the instance onto a linked list of instances for that class
	// When the object is freed using deleteInstance(), then we pop it.
	// What would this achieve?
	//	- we could check statistics on them or do other logging
	//	- we could access instances remotely, and perhaps then manipulate them remotely in a shared manner
	//	- if an object is referenced by another object, and thus shared, then we need to reference counting here before freeing.
	// THEREFORE: we should have an addReference() and release() method (instead of a deleteInstance() method).
	//	- the reference counting itself should probably be done inside of TTObject though, yes?
	return err;
}

TTObjectPtr TTEnvironment::referenceInstance(TTObjectPtr anObject)
{
	// TODO: make sure that anObject is valid or wrap with an exception?
	anObject->referenceCount++;
	return anObject;
}

TTErr TTEnvironment::releaseInstance(TTObjectPtr* anObject)
{
	TTValue v = **anObject;

	(*anObject)->valid = false;
	(*anObject)->observers->iterateObjectsSendingMessage(TT("objectFreeing"), v);

	// If the object is locked (e.g. in the middle of processing a vector in another thread)
	//	then we spin until the lock is released
	//	TODO: we should also be able to time-out in the event that we have a dead lock.
	while((*anObject)->getlock())
		;

	(*anObject)->referenceCount--;
	if((*anObject)->referenceCount < 1){
		delete *anObject;
		*anObject = NULL;
	}
	return kTTErrNone;
}

#if 0
#pragma mark -
#pragma mark Public Interface
#endif

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, TTValue& arguments)
{
	return ttEnvironment->createInstance(className, returnedObjectPtr, arguments);
}

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, const TTValue& arguments)
{
	return ttEnvironment->createInstance(className, returnedObjectPtr, arguments);
}

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, const TTUInt16 arguments)
{
	TTValue	v(arguments);
	return ttEnvironment->createInstance(className, returnedObjectPtr, v);
}

TTObjectPtr TTObjectReference(TTObjectPtr anObject)
{
	return ttEnvironment->referenceInstance(anObject);
}

TTErr TTObjectRelease(TTObjectPtr* anObject)
{
	if(*anObject)
		return ttEnvironment->releaseInstance(anObject);
	else
		return kTTErrNone;
}

TTErr TTClassRegister(const TTSymbolPtr className, const TTString& tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	return ttEnvironment->registerClass(className, tagString, anInstantiationMethod);
}

TTErr TTClassRegister(const TTSymbolPtr className, TTImmutableCString tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	return ttEnvironment->registerClass(className, TTString(tagString), anInstantiationMethod);
}

TTErr TTGetRegisteredClassNames(TTValue& classNames)
{
	return ttEnvironment->getAllClassNames(classNames);
}

TTErr TTGetRegisteredClassNamesForTags(TTValue& classNames, const TTValue& searchTags)
{
	return ttEnvironment->getClassNamesWithTags(classNames, searchTags);
}

<commit_msg>TTEnvironment: added an assertion to catch bad TTObject release attempts immediately, rather than waiting for memory corruption to bite us in some undetermined way later on...<commit_after>/*
 * TTBlue Global Object
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTFoundation.h"
#include "TTEnvironment.h"
#include "TTClass.h"

#define thisTTClass TTEnvironment

// The environment object has one instance, which is global in scope.
TTEnvironment*	ttEnvironment = NULL;

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

TTEnvironment::TTEnvironment()
	: TTObject(kTTValNONE), debugBasic(false), debugMessaging(false), sr(0)
{
	classes = new TTHash();
	tags = new TTHash();

	registerAttributeSimple(debugBasic,		kTypeBoolean);
	registerAttributeSimple(debugMessaging,	kTypeBoolean);
	registerAttributeSimple(sr,				kTypeUInt32);

	registerMessageWithArgument(getVersion);

	setAttributeValue(TT("sr"), TTUInt32(44100));
}

TTEnvironment::~TTEnvironment()
{
	// If on Windows, we need to call FreeLibrary() on all plug-ins loaded with LoadLibrary()
	// On the Mac, we may need to do the equivalent

	delete tags;
	delete classes;
}

TTErr TTEnvironment::getVersion(TTValue &value)
{
	value = TTFOUNDATION_VERSION_STRING;
	return kTTErrNone;
}

TTErr TTEnvironment::registerClass(const TTSymbolPtr className, const TTString& tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	TTValue		v((TTString&)tagString);	// The tags to be associated with the class we are registering.
	TTValue		tagObjects;					// Contains a TTList of objects in the environment with the given tag.
	TTClassPtr	theClass;
	TTErr		err;
	TTList*		classNamesForTag;			// The TTList contained by tagObjects
	TTUInt16	size;
	TTSymbolPtr	tag;
	TTValue		result;

	err = classes->lookup(className, result);

	// If a class is already registered with this name, then we do not want to register another class with the same name!
	if (err == kTTErrValueNotFound) {

		// 1. Turn the string into an array of symbols
		v.transformCSVStringToSymbolArray();

		// 2. Create the class and associate it with its name
		theClass = new TTClass(className, v, anInstantiationMethod);

		// 3. For each symbol in the TTValue array...
		size = v.getSize();
		for (TTUInt16 i=0; i<size; i++) {
			v.get(i, &tag);

			// 4. Look to see if this tag exists yet
			err = tags->lookup(tag, tagObjects);
			if (!err) {
				classNamesForTag = (TTList*)(TTPtr(tagObjects));

				// TODO: The following code demonstrates so extreme lameness that we need to evaluate.
				//	First, we should probably just do this section of code with TTValue instead of TTList (but we needed code to test TTList)
				//	Second, TTList is taking references but keeping things internally as pointers, which leads to lots of confusion
				//	Third, we have to pass objects that are permanent - so no temporaries are allowed unless we make TTList do a copy
				//	etc.

				// TODO: We need to factor out a function to add a tag for a named class (or a given class ptr)

				//classNamesForTag->append(className);
				classNamesForTag->append(*new TTValue(className));
			}
			else {
				classNamesForTag = new TTList;
				tagObjects = TTPtr(classNamesForTag);
				tags->append(tag ,tagObjects);
				classNamesForTag->append(*new TTValue(className));
			}
		}

		// 4. Register it
		err = registerClass(theClass);
	}
	return err;
}

TTErr TTEnvironment::registerClass(TTClassPtr theClass)
{
	return classes->append(theClass->name, TTPtr(theClass));
}

TTErr TTEnvironment::getAllClassNames(TTValue& returnedClassNames)
{
	return classes->getKeys(returnedClassNames);
}

TTErr TTEnvironment::getClassNamesWithTags(TTValue& classNames, const TTValue& searchTags)
{
	// TODO: right now we only look for the first tag, we should look for each and then do a union on the results.
	// Well, that's not what's really happening, but the point is that this really only works if we are searching for one tag.

	TTUInt16	size = searchTags.getSize();
	TTSymbolPtr	tag;
	TTValue		tagObjects;
	TTErr		err = kTTErrGeneric;
	TTList*		classNamesForTag;

	for(TTUInt16 i=0; i<size; i++){
		searchTags.get(i, &tag);

		err = tags->lookup(tag, tagObjects);
		if(!err){
			classNamesForTag = (TTList*)(TTPtr(tagObjects));
			classNamesForTag->assignToValue(classNames);
		}
	}

	return err;
}

TTErr TTEnvironment::createInstance(const TTSymbolPtr className, TTObjectPtr* anObject, const TTValue& anArgument)
{
	return createInstance(className, anObject, (TTValue&)anArgument); // throw away the const (I know, I know...), maybe the non-const constructor shouldn't exist at all?
}

TTErr TTEnvironment::createInstance(const TTSymbolPtr className, TTObjectPtr* anObject, TTValue& anArgument)
{
	TTValue		v;
	TTClassPtr	theClass;
	TTErr		err;
	TTObjectPtr	newObject = NULL;
	TTObjectPtr	oldObject = NULL;

	err = classes->lookup(className, v);
	if(!err){
		theClass = TTClassPtr(TTPtr(v));
		if(theClass)
			err = theClass->createInstance(&newObject, anArgument);
		else
			err = kTTErrGeneric;
	}

	if(!err && newObject){
		if(*anObject)
			oldObject = *anObject;
		*anObject = newObject;
		if(oldObject)
			releaseInstance(&oldObject);

		(*anObject)->classPtr = theClass;
		(*anObject)->valid = true;
	}

	//TODO: Add instance tracking.  For each instance of a class, we push the instance onto a linked list of instances for that class
	// When the object is freed using deleteInstance(), then we pop it.
	// What would this achieve?
	//	- we could check statistics on them or do other logging
	//	- we could access instances remotely, and perhaps then manipulate them remotely in a shared manner
	//	- if an object is referenced by another object, and thus shared, then we need to reference counting here before freeing.
	// THEREFORE: we should have an addReference() and release() method (instead of a deleteInstance() method).
	//	- the reference counting itself should probably be done inside of TTObject though, yes?
	return err;
}

TTObjectPtr TTEnvironment::referenceInstance(TTObjectPtr anObject)
{
	// TODO: make sure that anObject is valid or wrap with an exception?
	anObject->referenceCount++;
	return anObject;
}

TTErr TTEnvironment::releaseInstance(TTObjectPtr* anObject)
{
	TTValue v = **anObject;

	TT_ASSERT("can only release a valid instance", *anObject && (*anObject)->valid == 1 && (*anObject)->referenceCount);

	(*anObject)->valid = false;
	(*anObject)->observers->iterateObjectsSendingMessage(TT("objectFreeing"), v);

	// If the object is locked (e.g. in the middle of processing a vector in another thread)
	//	then we spin until the lock is released
	//	TODO: we should also be able to time-out in the event that we have a dead lock.
	while((*anObject)->getlock())
		;

	(*anObject)->referenceCount--;
	if((*anObject)->referenceCount < 1){
		delete *anObject;
		*anObject = NULL;
	}
	return kTTErrNone;
}

#if 0
#pragma mark -
#pragma mark Public Interface
#endif

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, TTValue& arguments)
{
	return ttEnvironment->createInstance(className, returnedObjectPtr, arguments);
}

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, const TTValue& arguments)
{
	return ttEnvironment->createInstance(className, returnedObjectPtr, arguments);
}

TTErr TTObjectInstantiate(const TTSymbolPtr className, TTObjectPtr* returnedObjectPtr, const TTUInt16 arguments)
{
	TTValue	v(arguments);
	return ttEnvironment->createInstance(className, returnedObjectPtr, v);
}

TTObjectPtr TTObjectReference(TTObjectPtr anObject)
{
	return ttEnvironment->referenceInstance(anObject);
}

TTErr TTObjectRelease(TTObjectPtr* anObject)
{
	if(*anObject)
		return ttEnvironment->releaseInstance(anObject);
	else
		return kTTErrNone;
}

TTErr TTClassRegister(const TTSymbolPtr className, const TTString& tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	return ttEnvironment->registerClass(className, tagString, anInstantiationMethod);
}

TTErr TTClassRegister(const TTSymbolPtr className, TTImmutableCString tagString, const TTObjectInstantiationMethod anInstantiationMethod)
{
	return ttEnvironment->registerClass(className, TTString(tagString), anInstantiationMethod);
}

TTErr TTGetRegisteredClassNames(TTValue& classNames)
{
	return ttEnvironment->getAllClassNames(classNames);
}

TTErr TTGetRegisteredClassNamesForTags(TTValue& classNames, const TTValue& searchTags)
{
	return ttEnvironment->getClassNamesWithTags(classNames, searchTags);
}

<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include <KApplication>
#include <KLocale>
#include <KAboutData>
#include <KCmdLineArgs>

#include <QtCore/QFile>

#include "KdeMainWindow.h"

#include "MarbleTest.h"

#if STATIC_BUILD
 #include <QtCore/QtPlugin>
 Q_IMPORT_PLUGIN(qjpeg)
 Q_IMPORT_PLUGIN(qsvg)
#endif

int main (int argc, char *argv[])
{
    KAboutData aboutData( "marble", 0,
                          ki18n( "Marble Desktop Globe" ),
                          "0.3.8",
                          ki18n( "A World Atlas." ),
                          KAboutData::License_LGPL, ki18n( "(c) 2007" ),
                          KLocalizedString(),
                          "http://edu.kde.org/marble" );
    aboutData.addAuthor( ki18n( "Torsten Rahn" ),
                         ki18n( "Original author and maintainer" ),
                         "rahn@kde.org" );
    aboutData.addAuthor( ki18n( "Inge Wallin" ),
                         ki18n( "co-maintainer" ),
                         "inge@lysator.liu.se" );

    KCmdLineArgs::init( argc, argv, &aboutData );

    KCmdLineOptions  options;
    options.add( "timedemo", ki18n( "Make a time measurement to check performance" ) );
    options.add( "gpsdemo", ki18n( "Check speed of gps drawing" ) );
    options.add( "enableCurrentLocation", ki18n( "Enable tab to show the current location" ) );
    options.add( "enableFileView",
                 ki18n( "Enable tab to see gpxFileView") );
    KCmdLineArgs::addCmdLineOptions( options );
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

    KApplication app;

    MainWindow *window = new MainWindow();
    window->setAttribute( Qt::WA_DeleteOnClose, true );

    MarbleTest *marbleTest = new MarbleTest( window->marbleWidget() );

    window->show();

    if ( args->isSet( "timedemo" ) ) {
        window->resize(900, 640);
        marbleTest->timeDemo();
        return 0;
    }

    if ( args->isSet( "gpsdemo" ) ) {
        window->resize( 900, 640 );
        marbleTest->gpsDemo();
        return 0;
    }

    if ( args->isSet( "enableCurrentLocation" ) ) {
        window->controlView()->setCurrentLocationTabShown(true);
    }

    if ( args->isSet( "enableFileView" ) ) {
        window->controlView()->setFileViewTabShown(true);
    }

    // Read the files that are given on the command line.
    // FIXME: What should the '1' below really be?
    // Command line arguments, i.e. files to open
    for (int i = 0; i < args->count(); i++) {

        // FIXME: Use openUrl( args->url(i)) instead?
        if ( QFile::exists( args->arg( i ) ) )
            ( window->controlView() )->addPlaceMarkFile( args->arg( i ) );
    }

    delete marbleTest;

    return app.exec();
}
<commit_msg>- sync version number <commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include <KApplication>
#include <KLocale>
#include <KAboutData>
#include <KCmdLineArgs>

#include <QtCore/QFile>

#include "KdeMainWindow.h"

#include "MarbleTest.h"

#if STATIC_BUILD
 #include <QtCore/QtPlugin>
 Q_IMPORT_PLUGIN(qjpeg)
 Q_IMPORT_PLUGIN(qsvg)
#endif

int main (int argc, char *argv[])
{
    KAboutData aboutData( "marble", 0,
                          ki18n( "Marble Desktop Globe" ),
                          "0.3.9",
                          ki18n( "A World Atlas." ),
                          KAboutData::License_LGPL, ki18n( "(c) 2007" ),
                          KLocalizedString(),
                          "http://edu.kde.org/marble" );
    aboutData.addAuthor( ki18n( "Torsten Rahn" ),
                         ki18n( "Original author and maintainer" ),
                         "rahn@kde.org" );
    aboutData.addAuthor( ki18n( "Inge Wallin" ),
                         ki18n( "co-maintainer" ),
                         "inge@lysator.liu.se" );

    KCmdLineArgs::init( argc, argv, &aboutData );

    KCmdLineOptions  options;
    options.add( "timedemo", ki18n( "Make a time measurement to check performance" ) );
    options.add( "gpsdemo", ki18n( "Check speed of gps drawing" ) );
    options.add( "enableCurrentLocation", ki18n( "Enable tab to show the current location" ) );
    options.add( "enableFileView",
                 ki18n( "Enable tab to see gpxFileView") );
    KCmdLineArgs::addCmdLineOptions( options );
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

    KApplication app;

    MainWindow *window = new MainWindow();
    window->setAttribute( Qt::WA_DeleteOnClose, true );

    MarbleTest *marbleTest = new MarbleTest( window->marbleWidget() );

    window->show();

    if ( args->isSet( "timedemo" ) ) {
        window->resize(900, 640);
        marbleTest->timeDemo();
        return 0;
    }

    if ( args->isSet( "gpsdemo" ) ) {
        window->resize( 900, 640 );
        marbleTest->gpsDemo();
        return 0;
    }

    if ( args->isSet( "enableCurrentLocation" ) ) {
        window->controlView()->setCurrentLocationTabShown(true);
    }

    if ( args->isSet( "enableFileView" ) ) {
        window->controlView()->setFileViewTabShown(true);
    }

    // Read the files that are given on the command line.
    // FIXME: What should the '1' below really be?
    // Command line arguments, i.e. files to open
    for (int i = 0; i < args->count(); i++) {

        // FIXME: Use openUrl( args->url(i)) instead?
        if ( QFile::exists( args->arg( i ) ) )
            ( window->controlView() )->addPlaceMarkFile( args->arg( i ) );
    }

    delete marbleTest;

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


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

template <typename T>
std::ifstream& operator>> <> (std::ifstream& infile, Node<T>* root);

template <typename T>
std::ostream& operator<< <> (std::ostream& outfile, Node<T>* root);

template <typename T>
struct Node
{
	Node<T>* leftNode;
	Node<T>* rightNode;
	T value;

	Node(T value)
	{
		this->value = value;
		leftNode = nullptr;
		rightNode = nullptr;
	}
};

template <typename T>
class BinarySearchTree
{
private:
	Node<T>* _root;
	void destroyTree(Node<T>* node);
	void insertElement(Node<T>* &node, const T &value);
	Node<T>* findPrev(Node<T>* &node, const T& value);
	Node<T>* findElement(const T& value) const;

public:
	BinarySearchTree();
	~BinarySearchTree();

	T value_() const;
	int count_(const Node<T>* node) const;

	Node<T>* leftNode_() const;
	Node<T>* rightNode_() const;
	Node<T>* root() const;

	void insert(const T& value);
	bool isFound(const T& value) const;

	Node<T>* findPrev(const T& value);

	void infile(std::string filename);
	void outfile(Node<T>* root, std::ostream& outfile) const;
	void out(std::string filename) const;
	void paintTree(const Node<T>* node, int level) const;
	void deleteNode(const T& value);

	friend std::ifstream& operator>> <> (std::ifstream& infile, Node<T>* root);
	friend std::ostream& operator<< <> (std::ostream& outfile, Node<T>* root);
};

template <typename T>
BinarySearchTree<T>::BinarySearchTree()
{
	_root = nullptr;
}

template <typename T>
BinarySearchTree<T>::~BinarySearchTree()
{
	destroyTree(_root);
}

template <typename T>
void BinarySearchTree<T>::destroyTree(Node<T>* node)
{
	if (!node)
		return;

	destroyTree(node->leftNode);
	destroyTree(node->rightNode);

	delete node;
}

template <typename T>
T BinarySearchTree<T>::value_() const
{
	return _root->value;
}

template <typename T>
int BinarySearchTree<T>::count_(const Node<T>* node) const
{
	if (!node)
		return 0;

	else
		return count_(node->leftNode) + count_(node->rightNode) + 1;
}

template <typename T>
Node<T>* BinarySearchTree<T>::root() const
{
	return _root;
}

template <typename T>
Node<T>* BinarySearchTree<T>::leftNode_() const
{
	return _root->leftNode;
}

template <typename T>
Node<T>* BinarySearchTree<T>::rightNode_() const
{
	return _root->rightNode;
}

template <typename T>
void BinarySearchTree<T>::insertElement(Node<T>* &node, const T &value)
{
	if (node)
	{
		if (value == node->value)
			throw std::logic_error("This is current element!\n");
		if (value < node->value)
			insertElement(node->leftNode, value);
		else if (value > node->value)
			insertElement(node->rightNode, value);
	}
	else node = new Node<T>(value);
}

template <typename T>
void BinarySearchTree<T>::insert(const T& value)
{
	insertElement(_root, value);
}

template <typename T>
Node<T>*  BinarySearchTree<T>::findElement(const T& value) const
{
	Node<T> *currNode = _root;

	while (currNode)
	{
		if (currNode->value == value)
			break;
		else
		{
			if (currNode->value < value)
				currNode = currNode->rightNode;
			else
				currNode = currNode->leftNode;
		}
	}
	return currNode;
}

template <typename T>
bool BinarySearchTree<T>::isFound(const T& value) const
{
	Node<T> *retNode = findElement(value);
	if (retNode)
		return true;
	else
		return false;
}

template <typename T>
void BinarySearchTree<T>::infile(std::string filename)
{
	std::ifstream infile;
	infile.open(filename);
	if (!infile)
		throw std::logic_error("The file isn't find");
	T value;
	int count;
	infile >> count;
	while (count--)
	{
		infile >> value;
		insert(value);
	}
	infile.close();
}

template <typename T>
std::ifstream& operator>> (std::string filename, Node<T>* root)
{
	return root.infile(filename);
}

template <typename T>
void BinarySearchTree<T>::out(std::string filename) const
{
	std::ofstream ofile(filename);
	if (!ofile)
		throw std::logic_error("The file isn't find\n");
	int count = count_(_root);
	if (count == 0)
		throw std::logic_error("The tree is empty\n");
		ofile << count << " ";
	outfile(_root, ofile);
	ofile.close();
}

template <typename T>
void BinarySearchTree<T>::outfile(Node<T>* root, std::ostream& ofile) const
{
	if (!root)
		return;
	else
	{
		ofile << root->value << " ";
		outfile(root->rightNode, ofile);
		outfile(root->leftNode, ofile);
	}
}

template <typename T>
std::ostream& operator<< (std::ostream& outfile, Node<T>* root)
{
	return root.outfile(outfile);
}

template <typename T>
void BinarySearchTree<T>::paintTree(const Node<T>* node, int level) const
{
	if (node)
	{
		paintTree(node->rightNode, level++);
		for (int i = 0; i < level; i++)
		{
			std::cout << "-";
		}
		std::cout << node->value << std::endl;
		paintTree(node->leftNode, level++);
	}
}

template <typename T>
void BinarySearchTree<T>::deleteNode(const T& value)
{
	if (isFound(value) == false)
		throw std::logic_error("This element is not found in BST!\n");
	Node<T> *currNode = findElement(value);
	Node<T> *parentNode = findPrev(value);

	if (currNode->leftNode == nullptr && currNode->rightNode == nullptr)
	{
		if (parentNode->leftNode == currNode)
			parentNode->leftNode = nullptr;
		if (parentNode->rightNode == currNode)
			parentNode->rightNode = nullptr;
		currNode = nullptr;
	}

	else if (currNode->rightNode == nullptr)
	{
		if (parentNode->leftNode == currNode)
			parentNode->leftNode = currNode->leftNode;
		if (parentNode->rightNode == currNode)
			parentNode->rightNode = currNode->leftNode;
		currNode = nullptr;
	}

	else
	{
		Node <T>* minNode = currNode->rightNode;
		while (minNode->leftNode)
			minNode = minNode->leftNode;
		T val = minNode->value;
		deleteNode(minNode->value);
		currNode->value = val;
	}
}

template <typename T>
Node<T>* BinarySearchTree<T>::findPrev(Node<T>* &node, const T &value)
{
	Node<T>* currNode = node;

	if (isFound(value))
	{
		if (value < currNode->value)
			if (value == currNode->leftNode->value)
				return currNode;
			else
				return findPrev(currNode->leftNode, value);
		else if (value > currNode->value)
			if (value == currNode->rightNode->value)
				return currNode;
			else
				return findPrev(currNode->rightNode, value);
		else return nullptr;
	}

	else return nullptr;
}

template <typename T>
Node<T>* BinarySearchTree<T>::findPrev(const T& value)
{
	return findPrev(_root, value);
}
<commit_msg>Update binary_search_tree.hpp<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

template <typename T>
std::ifstream& operator>> <> (std::ifstream& infile, Node<T>* root);

template <typename T>
std::ostream& operator<< <> (std::ostream& outfile, Node<T>* root);

template <typename T>
struct Node
{
	Node<T>* leftNode;
	Node<T>* rightNode;
	T value;

	Node(T value)
	{
		this->value = value;
		leftNode = nullptr;
		rightNode = nullptr;
	}
};

template <typename T>
class BinarySearchTree
{
private:
	Node<T>* _root;
	void destroyTree(Node<T>* node);
	void insertElement(Node<T>* &node, const T &value);
	Node<T>* findPrev(Node<T>* &node, const T& value);
	Node<T>* findElement(const T& value) const;

public:
	BinarySearchTree();
	~BinarySearchTree();

	T value_() const;
	int count_(const Node<T>* node) const;

	Node<T>* leftNode_() const;
	Node<T>* rightNode_() const;
	Node<T>* root() const;

	void insert(const T& value);
	bool isFound(const T& value) const;

	Node<T>* findPrev(const T& value);

	void infile(std::string filename);
	void outfile(Node<T>* root, std::ostream& outfile) const;
	void out(std::string filename) const;
	void paintTree(const Node<T>* node, int level) const;
	void deleteNode(const T& value);

	friend std::ifstream& operator>> <> (std::ifstream& infile, BinarySearchTree<T>& node);
	friend std::ostream& operator<< <> (std::ostream& outfile, BinarySearchTree<T>& node);
};

template <typename T>
BinarySearchTree<T>::BinarySearchTree()
{
	_root = nullptr;
}

template <typename T>
BinarySearchTree<T>::~BinarySearchTree()
{
	destroyTree(_root);
}

template <typename T>
void BinarySearchTree<T>::destroyTree(Node<T>* node)
{
	if (!node)
		return;

	destroyTree(node->leftNode);
	destroyTree(node->rightNode);

	delete node;
}

template <typename T>
T BinarySearchTree<T>::value_() const
{
	return _root->value;
}

template <typename T>
int BinarySearchTree<T>::count_(const Node<T>* node) const
{
	if (!node)
		return 0;

	else
		return count_(node->leftNode) + count_(node->rightNode) + 1;
}

template <typename T>
Node<T>* BinarySearchTree<T>::root() const
{
	return _root;
}

template <typename T>
Node<T>* BinarySearchTree<T>::leftNode_() const
{
	return _root->leftNode;
}

template <typename T>
Node<T>* BinarySearchTree<T>::rightNode_() const
{
	return _root->rightNode;
}

template <typename T>
void BinarySearchTree<T>::insertElement(Node<T>* &node, const T &value)
{
	if (node)
	{
		if (value == node->value)
			throw std::logic_error("This is current element!\n");
		if (value < node->value)
			insertElement(node->leftNode, value);
		else if (value > node->value)
			insertElement(node->rightNode, value);
	}
	else node = new Node<T>(value);
}

template <typename T>
void BinarySearchTree<T>::insert(const T& value)
{
	insertElement(_root, value);
}

template <typename T>
Node<T>*  BinarySearchTree<T>::findElement(const T& value) const
{
	Node<T> *currNode = _root;

	while (currNode)
	{
		if (currNode->value == value)
			break;
		else
		{
			if (currNode->value < value)
				currNode = currNode->rightNode;
			else
				currNode = currNode->leftNode;
		}
	}
	return currNode;
}

template <typename T>
bool BinarySearchTree<T>::isFound(const T& value) const
{
	Node<T> *retNode = findElement(value);
	if (retNode)
		return true;
	else
		return false;
}

template <typename T>
void BinarySearchTree<T>::infile(std::string filename)
{
	std::ifstream infile;
	infile.open(filename);
	if (!infile)
		throw std::logic_error("The file isn't find");
	T value;
	int count;
	infile >> count;
	while (count--)
	{
		infile >> value;
		insert(value);
	}
	infile.close();
}

template <typename T>
std::ifstream& operator>> (std::string filename, BinarySearchTree<T>& node)
{
	return node.infile(filename);
}

template <typename T>
void BinarySearchTree<T>::out(std::string filename) const
{
	std::ofstream ofile(filename);
	if (!ofile)
		throw std::logic_error("The file isn't find\n");
	int count = count_(_root);
	if (count == 0)
		throw std::logic_error("The tree is empty\n");
		ofile << count << " ";
	outfile(_root, ofile);
	ofile.close();
}

template <typename T>
void BinarySearchTree<T>::outfile(Node<T>* root, std::ostream& ofile) const
{
	if (!root)
		return;
	else
	{
		ofile << root->value << " ";
		outfile(root->rightNode, ofile);
		outfile(root->leftNode, ofile);
	}
}

template <typename T>
std::ostream& operator<< (std::ostream& outfile, BinarySearchTree<T>& node)
{
	return node.outfile(outfile);
}

template <typename T>
void BinarySearchTree<T>::paintTree(const Node<T>* node, int level) const
{
	if (node)
	{
		paintTree(node->rightNode, level++);
		for (int i = 0; i < level; i++)
		{
			std::cout << "-";
		}
		std::cout << node->value << std::endl;
		paintTree(node->leftNode, level++);
	}
}

template <typename T>
void BinarySearchTree<T>::deleteNode(const T& value)
{
	if (isFound(value) == false)
		throw std::logic_error("This element is not found in BST!\n");
	Node<T> *currNode = findElement(value);
	Node<T> *parentNode = findPrev(value);

	if (currNode->leftNode == nullptr && currNode->rightNode == nullptr)
	{
		if (parentNode->leftNode == currNode)
			parentNode->leftNode = nullptr;
		if (parentNode->rightNode == currNode)
			parentNode->rightNode = nullptr;
		currNode = nullptr;
	}

	else if (currNode->rightNode == nullptr)
	{
		if (parentNode->leftNode == currNode)
			parentNode->leftNode = currNode->leftNode;
		if (parentNode->rightNode == currNode)
			parentNode->rightNode = currNode->leftNode;
		currNode = nullptr;
	}

	else
	{
		Node <T>* minNode = currNode->rightNode;
		while (minNode->leftNode)
			minNode = minNode->leftNode;
		T val = minNode->value;
		deleteNode(minNode->value);
		currNode->value = val;
	}
}

template <typename T>
Node<T>* BinarySearchTree<T>::findPrev(Node<T>* &node, const T &value)
{
	Node<T>* currNode = node;

	if (isFound(value))
	{
		if (value < currNode->value)
			if (value == currNode->leftNode->value)
				return currNode;
			else
				return findPrev(currNode->leftNode, value);
		else if (value > currNode->value)
			if (value == currNode->rightNode->value)
				return currNode;
			else
				return findPrev(currNode->rightNode, value);
		else return nullptr;
	}

	else return nullptr;
}

template <typename T>
Node<T>* BinarySearchTree<T>::findPrev(const T& value)
{
	return findPrev(_root, value);
}
<|endoftext|>


<commit_before>#include "libnanocv/nanocv.h"
#include "libnanocv/tasks/task_synthetic_shapes.h"
#include "libnanocv/util/thread.h"
#include "libnanocv/util/measure.hpp"
#include "libnanocv/util/tabulator.h"
#include "libnanocv/trainers/batch.h"
#include "libnanocv/trainers/minibatch.h"
#include "libnanocv/trainers/stochastic.h"

using namespace ncv;

template
<
        typename ttrainer
>
void test_optimizer(const task_t& task, ttrainer trainer, const string_t& name, tabulator_t& table)
{
        const size_t cmd_trials = 16;

        stats_t<scalar_t> tvalues;
        stats_t<scalar_t> vvalues;
        stats_t<scalar_t> terrors;
        stats_t<scalar_t> verrors;

        const size_t usec = ncv::measure_robustly_usec([&] ()
        {
                sampler_t tsampler(task);
                tsampler.setup(sampler_t::atype::annotated);

                sampler_t vsampler(task);
                tsampler.split(80, vsampler);

                const trainer_result_t result = trainer(tsampler, vsampler);

                tvalues(result.m_opt_state.m_tvalue);
                vvalues(result.m_opt_state.m_vvalue);

                terrors(result.m_opt_state.m_terror_avg);
                verrors(result.m_opt_state.m_verror_avg);
        }, cmd_trials);

        table.append(name)
                << tvalues.avg() << terrors.avg() << vvalues.avg() << verrors.avg()
                << (usec / 1000);
}

void test_optimizers(
        const task_t& task, const model_t& model, const loss_t& loss, const string_t& criterion,
        const string_t& config_name)
{
        const size_t cmd_iterations = 32;
        const size_t cmd_epochs = cmd_iterations;
        const scalar_t cmd_epsilon = 1e-4;
        const bool verbose = false;

        // batch optimizers
        const auto batch_optimizers =
        {
                batch_optimizer::GD,
                batch_optimizer::CGD,
                batch_optimizer::LBFGS
        };

        // minibatch optimizers
        const auto minibatch_optimizers =
        {
                batch_optimizer::GD,
                batch_optimizer::CGD,
                batch_optimizer::LBFGS
        };

        // stochastic optimizers
        const auto stochastic_optimizers =
        {
                stochastic_optimizer::SG,
                stochastic_optimizer::SGA,
                stochastic_optimizer::SIA,
                stochastic_optimizer::AG,
                stochastic_optimizer::ADAGRAD,
                stochastic_optimizer::ADADELTA
        };

        // run optimizers and collect results
        tabulator_t table("optimizer\\");
        table.header() << "train loss" << "train error" << "valid loss" << "valid error" << "time [msec]";

        for (batch_optimizer optimizer : batch_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        return ncv::batch_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_iterations, cmd_epsilon, verbose);
                }, "batch [" + text::to_string(optimizer) + "]", table);
        }

        for (batch_optimizer optimizer : minibatch_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        return ncv::minibatch_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_epochs, cmd_epsilon, verbose);
                }, "minibatch [" + text::to_string(optimizer) + "]", table);
        }

        for (stochastic_optimizer optimizer : stochastic_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        return ncv::stochastic_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_epochs, verbose);
                }, "stochastic [" + text::to_string(optimizer) + "]", table);
        }

        table.print(std::cout);
}

int main(int argc, char *argv[])
{
        ncv::init();

        const size_t cmd_samples = 8 * 1024;
        const size_t cmd_rows = 16;
        const size_t cmd_cols = 16;
        const size_t cmd_outputs = 8;

        synthetic_shapes_task_t task(
                "rows=" + text::to_string(cmd_rows) + "," +
                "cols=" + text::to_string(cmd_cols) + "," +
                "color=luma" + "," +
                "dims=" + text::to_string(cmd_outputs) + "," +
                "size=" + text::to_string(cmd_samples));
        task.load("");
	task.describe();

        const string_t lmodel0;
        const string_t lmodel1 = lmodel0 + "linear:dims=32;act-snorm;";
        const string_t lmodel2 = lmodel1 + "linear:dims=32;act-snorm;";
        const string_t lmodel3 = lmodel2 + "linear:dims=32;act-snorm;";

        string_t cmodel;
        cmodel = cmodel + "conv:dims=8,rows=5,cols=5;pool-max;act-snorm;";
        cmodel = cmodel + "conv:dims=8,rows=3,cols=3;act-snorm;";

        const string_t outlayer = "linear:dims=" + text::to_string(cmd_outputs) + ";";

        strings_t cmd_networks =
        {
                lmodel0 + outlayer,
                lmodel1 + outlayer,
                lmodel2 + outlayer,
                lmodel3 + outlayer,

                cmodel + outlayer
        };

        const strings_t cmd_losses = { "classnll", "logistic" }; //loss_manager_t::instance().ids();
        const strings_t cmd_criteria = { "avg" }; //criterion_manager_t::instance().ids();

        // vary the model
        for (const string_t& cmd_network : cmd_networks)
        {
                log_info() << "<<< running network [" << cmd_network << "] ...";

                const rmodel_t model = model_manager_t::instance().get("forward-network", cmd_network);
                assert(model);
                model->resize(task, true);

                // vary the loss
                for (const string_t& cmd_loss : cmd_losses)
                {
                        log_info() << "<<< running loss [" << cmd_loss << "] ...";

                        const rloss_t loss = loss_manager_t::instance().get(cmd_loss);
                        assert(loss);

                        // vary the criteria
                        for (const string_t& cmd_criterion : cmd_criteria)
                        {
                                log_info() << "<<< running criterion [" << cmd_criterion << "] ...";

                                test_optimizers(task, *model, *loss, cmd_criterion,
                                                "loss [" + cmd_loss + "], criterion [" + cmd_criterion + "]");
                        }
                }

                log_info();
        }

        // OK
        log_info() << done;
        return EXIT_SUCCESS;
}
<commit_msg>fix benchmark<commit_after>#include "libnanocv/nanocv.h"
#include "libnanocv/tasks/task_synthetic_shapes.h"
#include "libnanocv/util/thread.h"
#include "libnanocv/util/measure.hpp"
#include "libnanocv/util/tabulator.h"
#include "libnanocv/trainers/batch.h"
#include "libnanocv/trainers/minibatch.h"
#include "libnanocv/trainers/stochastic.h"

using namespace ncv;

template
<
        typename ttrainer
>
void test_optimizer(const task_t& task, ttrainer trainer, const string_t& name, tabulator_t& table)
{
        const size_t cmd_trials = 16;

        stats_t<scalar_t> tvalues;
        stats_t<scalar_t> vvalues;
        stats_t<scalar_t> terrors;
        stats_t<scalar_t> verrors;

        const size_t usec = ncv::measure_robustly_usec([&] ()
        {
                sampler_t tsampler(task);
                tsampler.setup(sampler_t::atype::annotated);

                sampler_t vsampler(task);
                tsampler.split(80, vsampler);

                const trainer_result_t result = trainer(tsampler, vsampler);

                tvalues(result.m_opt_state.m_tvalue);
                vvalues(result.m_opt_state.m_vvalue);

                terrors(result.m_opt_state.m_terror_avg);
                verrors(result.m_opt_state.m_verror_avg);
        }, cmd_trials);

        table.append(name)
                << tvalues.avg() << terrors.avg() << vvalues.avg() << verrors.avg()
                << (usec / 1000);
}

void test_optimizers(
        const task_t& task, model_t& model, const loss_t& loss, const string_t& criterion,
        const string_t& config_name)
{
        const size_t cmd_iterations = 32;
        const size_t cmd_epochs = cmd_iterations;
        const scalar_t cmd_epsilon = 1e-4;
        const bool verbose = false;

        // batch optimizers
        const auto batch_optimizers =
        {
                batch_optimizer::GD,
                batch_optimizer::CGD,
                batch_optimizer::LBFGS
        };

        // minibatch optimizers
        const auto minibatch_optimizers =
        {
                batch_optimizer::GD,
                batch_optimizer::CGD,
                batch_optimizer::LBFGS
        };

        // stochastic optimizers
        const auto stochastic_optimizers =
        {
                stochastic_optimizer::SG,
                stochastic_optimizer::SGA,
                stochastic_optimizer::SIA,
                stochastic_optimizer::AG,
                stochastic_optimizer::ADAGRAD,
                stochastic_optimizer::ADADELTA
        };

        // run optimizers and collect results
        tabulator_t table("optimizer\\");
        table.header() << "train loss" << "train error" << "valid loss" << "valid error" << "time [msec]";

        for (batch_optimizer optimizer : batch_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        model.random_params();
                        return ncv::batch_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_iterations, cmd_epsilon, verbose);
                }, "batch [" + text::to_string(optimizer) + "]", table);
        }

        for (batch_optimizer optimizer : minibatch_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        model.random_params();
                        return ncv::minibatch_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_epochs, cmd_epsilon, verbose);
                }, "minibatch [" + text::to_string(optimizer) + "]", table);
        }

        for (stochastic_optimizer optimizer : stochastic_optimizers)
        {
                test_optimizer(task, [&] (const sampler_t& tsampler, const sampler_t& vsampler)
                {
                        model.random_params();
                        return ncv::stochastic_train(
                                model, task, tsampler, vsampler, ncv::n_threads(),
                                loss, criterion, optimizer, cmd_epochs, verbose);
                }, "stochastic [" + text::to_string(optimizer) + "]", table);
        }

        table.print(std::cout);
}

int main(int argc, char *argv[])
{
        ncv::init();

        const size_t cmd_samples = 8 * 1024;
        const size_t cmd_rows = 16;
        const size_t cmd_cols = 16;
        const size_t cmd_outputs = 9;

        synthetic_shapes_task_t task(
                "rows=" + text::to_string(cmd_rows) + "," +
                "cols=" + text::to_string(cmd_cols) + "," +
                "color=luma" + "," +
                "dims=" + text::to_string(cmd_outputs) + "," +
                "size=" + text::to_string(cmd_samples));
        task.load("");
	task.describe();

        const string_t lmodel0;
        const string_t lmodel1 = lmodel0 + "linear:dims=16;act-snorm;";
        const string_t lmodel2 = lmodel1 + "linear:dims=16;act-snorm;";
        const string_t lmodel3 = lmodel2 + "linear:dims=16;act-snorm;";

        string_t cmodel;
        cmodel = cmodel + "conv:dims=8,rows=5,cols=5;pool-max;act-snorm;";
        cmodel = cmodel + "conv:dims=8,rows=3,cols=3;act-snorm;";

        const string_t outlayer = "linear:dims=" + text::to_string(cmd_outputs) + ";";

        strings_t cmd_networks =
        {
                lmodel0 + outlayer,
                lmodel1 + outlayer,
                lmodel2 + outlayer,
                lmodel3 + outlayer,

                cmodel + outlayer
        };

        const strings_t cmd_losses = { "classnll", "logistic" }; //loss_manager_t::instance().ids();
        const strings_t cmd_criteria = { "avg" }; //criterion_manager_t::instance().ids();

        // vary the model
        for (const string_t& cmd_network : cmd_networks)
        {
                log_info() << "<<< running network [" << cmd_network << "] ...";

                const rmodel_t model = model_manager_t::instance().get("forward-network", cmd_network);
                assert(model);
                model->resize(task, true);

                // vary the loss
                for (const string_t& cmd_loss : cmd_losses)
                {
                        log_info() << "<<< running loss [" << cmd_loss << "] ...";

                        const rloss_t loss = loss_manager_t::instance().get(cmd_loss);
                        assert(loss);

                        // vary the criteria
                        for (const string_t& cmd_criterion : cmd_criteria)
                        {
                                log_info() << "<<< running criterion [" << cmd_criterion << "] ...";

                                test_optimizers(task, *model, *loss, cmd_criterion,
                                                "loss [" + cmd_loss + "], criterion [" + cmd_criterion + "]");
                        }
                }

                log_info();
        }

        // OK
        log_info() << done;
        return EXIT_SUCCESS;
}
<|endoftext|>