<commit_before>/*
 * main.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <signal.h>
#include <execinfo.h>

#include "MediaServerServiceHandler.hpp"

#include <protocol/TBinaryProtocol.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <server/TNonblockingServer.h>
#include <concurrency/PosixThreadFactory.h>
#include <concurrency/ThreadManager.h>

#include "media_config_loader.hpp"

#include <glibmm.h>
#include <fstream>

#include <gst/gst.h>

#include <version.hpp>
#include "log.hpp"

#define GST_DEFAULT_NAME "media_server"

GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::apache::thrift::concurrency;

using namespace ::kurento;

using boost::shared_ptr;
using ::kurento::MediaServerServiceHandler;
using ::Glib::KeyFile;
using ::Glib::KeyFileFlags;

#define DEFAULT_CONFIG_FILE "/etc/kurento/kurento.conf"

#define MEDIA_SERVER_ADDRESS_KEY "serverAddress"
#define MEDIA_SERVER_SERVICE_PORT_KEY "serverPort"

static std::string serverAddress;
static gint serverServicePort;
static GstSDPMessage *sdp_message;
static KeyFile configFile;

Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create (true);
static TNonblockingServer *p_server = NULL;

static gchar *conf_file;

static GOptionEntry entries[] = {
  {
    "conf-file", 'f', 0, G_OPTION_ARG_FILENAME, &conf_file, "Configuration file",
    NULL
  },
  {NULL}
};

static void
create_media_server_service ()
{
  int port;
  port = MEDIA_SERVER_SERVICE_PORT;
  shared_ptr < MediaServerServiceHandler >
  handler (new MediaServerServiceHandler () );
  shared_ptr < TProcessor >
  processor (new MediaServerServiceProcessor (handler) );
  shared_ptr < TProtocolFactory >
  protocolFactory (new TBinaryProtocolFactory () );
  shared_ptr < PosixThreadFactory > threadFactory (new PosixThreadFactory () );
  shared_ptr < ThreadManager > threadManager =
    ThreadManager::newSimpleThreadManager (15);
  threadManager->threadFactory (threadFactory);
  threadManager->start ();
  TNonblockingServer server (processor, protocolFactory, port, threadManager);
  p_server = &server;
  GST_INFO ("Starting MediaServerService");
  kill (getppid(), SIGCONT);
  server.serve ();
  GST_INFO ("MediaServerService stopped finishing thread");
  throw Glib::Thread::Exit ();
}

static void
check_port (int port)
{
  if (port <= 0 || port > G_MAXUSHORT)
    throw Glib::KeyFileError (Glib::KeyFileError::PARSE, "Invalid value");
}

static void
set_default_server_config ()
{
  serverAddress = MEDIA_SERVER_ADDRESS;
  serverServicePort = MEDIA_SERVER_SERVICE_PORT;
}

static void
load_config (const std::string &file_name)
{
  gint port;
  GST_INFO ("Reading configuration from: %s", file_name.c_str () );
  /* Try to open de file */
  {
    std::ifstream file (file_name);

    if (!file) {
      GST_INFO ("Config file not found, creating a new one");
      std::ofstream of (file_name);
    }
  }

  try {
    if (!configFile.load_from_file (file_name,
        KeyFileFlags::KEY_FILE_KEEP_COMMENTS |
        KeyFileFlags::KEY_FILE_KEEP_TRANSLATIONS) ) {
      GST_WARNING ("Error loading configuration from %s, loading "
          "default server config, but no "
          "codecs will be available", file_name.c_str () );
      set_default_server_config ();
      return;
    }
  } catch (Glib::Error ex) {
    GST_WARNING ("Error loading configuration: %s", ex.what ().c_str () );
    GST_WARNING ("Error loading configuration from %s, loading "
        "default server config, but no "
        "codecs will be available", file_name.c_str () );
    set_default_server_config ();
    return;
  }

  try {
    serverAddress = configFile.get_string (SERVER_GROUP,
        MEDIA_SERVER_ADDRESS_KEY);
  } catch (Glib::KeyFileError err) {
    GST_INFO (err.what ().c_str () );
    GST_INFO ("Setting default address");
    configFile.set_string (SERVER_GROUP, MEDIA_SERVER_ADDRESS_KEY,
        MEDIA_SERVER_ADDRESS);
    serverAddress = MEDIA_SERVER_ADDRESS;
  }

  try {
    port = configFile.get_integer (SERVER_GROUP, MEDIA_SERVER_SERVICE_PORT_KEY);
    check_port (port);
    serverServicePort = port;
  } catch (Glib::KeyFileError err) {
    GST_INFO (err.what ().c_str () );
    GST_INFO ("Setting default server port");
    configFile.set_integer (SERVER_GROUP, MEDIA_SERVER_SERVICE_PORT_KEY,
        MEDIA_SERVER_SERVICE_PORT);
    serverServicePort = MEDIA_SERVER_SERVICE_PORT;
  }

  try {
    sdp_message = load_session_descriptor (configFile);
  } catch (Glib::KeyFileError err) {
    GST_WARNING (err.what ().c_str () );
    GST_WARNING ("Wrong codec configuration, communication won't be possible");
  }

  std::ofstream f (file_name, std::ios::out | std::ios::trunc);
  f << configFile.to_data ();
  f.close ();
  GST_INFO ("Configuration loaded successfully");
  GST_DEBUG ("Final config file:\n%s", configFile.to_data ().c_str () );
}

static void
initialiseExecutableName (char *exe, int size)
{
  char link[1024];
  int len;
  snprintf (link, sizeof (link), "/proc/%d/exe", getpid () );
  len = readlink (link, exe, size);

  if (len == -1) {
    fprintf (stderr, "ERROR GETTING NAME\n");
    exit (1);
  }

  exe[len] = '\0';
}

static const char *
getExecutableName ()
{
  static char *exe = NULL;
  static char aux[1024];

  if (exe == NULL) {
    initialiseExecutableName (aux, sizeof (aux) );
    exe = aux;
  }

  return exe;
}

static void
bt_sighandler (int sig, siginfo_t *info, gpointer data)
{
  void *trace[35];
  char **messages = (char **) NULL;
  int i, trace_size = 0;

//      ucontext_t *uc = (ucontext_t *)data;

  /* Do something useful with siginfo_t */
  if (sig == SIGSEGV) {
    printf ("Got signal %d, faulty address is %p\n", sig,
        (gpointer) info->si_addr);
  } else if (sig == SIGKILL || sig == SIGINT) {
    loop->quit ();
    return;
  } else {
    printf ("Got signal %d\n", sig);
  }

  trace_size = backtrace (trace, 35);
  /* overwrite sigaction with caller's address */
  //trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
  messages = backtrace_symbols (trace, trace_size);
  /* skip first stack frame (points here) */
  g_print ("\t[bt] Execution path:\n");

  for (i = 1; i < trace_size; ++i) {
    g_print ("\t[bt] #%d %s\n", i, messages[i]);
    char syscom[256];
    gchar **strs;
    const gchar *exe;
    strs = g_strsplit (messages[i], "(", 2);

    if (strs[1] == NULL)
      exe = getExecutableName ();
    else
      exe = strs[0];

    sprintf (syscom, "echo -n \"\t[bt]\t\t\"; addr2line %p -s -e %s",
        trace[i], exe);
    g_strfreev (strs);
    system (syscom);
  }

  if (sig == SIGPIPE) {
    GST_DEBUG ("Ignore sigpipe");
  } else {
    exit (sig);
  }
}

int
main (int argc, char **argv)
{
  GError *error = NULL;
  GOptionContext *context;
  struct sigaction sa;
  context = g_option_context_new ("");
  g_option_context_add_main_entries (context, entries, NULL);
  g_option_context_add_group (context, gst_init_get_option_group () );

  if (!g_option_context_parse (context, &argc, &argv, &error) ) {
    GST_ERROR ("option parsing failed: %s\n", error->message);
    exit (1);
  }

  g_option_context_free (context);

  gst_init (&argc, &argv);
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);
  /* Install our signal handler */
  sa.sa_sigaction = /*(void (*)(int, siginfo*, gpointer)) */ bt_sighandler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_RESTART | SA_SIGINFO;
  sigaction (SIGSEGV, &sa, NULL);
  sigaction (SIGPIPE, &sa, NULL);
  sigaction (SIGINT, &sa, NULL);
  sigaction (SIGKILL, &sa, NULL);
  Glib::thread_init ();
  GST_INFO ("Kmsc version: %s", get_version () );

  if (!conf_file)
    load_config (DEFAULT_CONFIG_FILE);
  else
    load_config ( (std::string) conf_file);

  sigc::slot < void >ss = sigc::ptr_fun (&create_media_server_service);
  Glib::Thread::create (ss, true); /* Created thread not used to join
                                      because of a bug in thrift */
  loop->run ();

  return 0;
}
<commit_msg>Fix bug #552: Exit main loop from main thread's context<commit_after>/*
 * main.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <signal.h>
#include <execinfo.h>

#include "MediaServerServiceHandler.hpp"

#include <protocol/TBinaryProtocol.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <server/TNonblockingServer.h>
#include <concurrency/PosixThreadFactory.h>
#include <concurrency/ThreadManager.h>

#include "media_config_loader.hpp"

#include <glibmm.h>
#include <fstream>

#include <gst/gst.h>

#include <version.hpp>
#include "log.hpp"

#define GST_DEFAULT_NAME "media_server"

GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::apache::thrift::concurrency;

using namespace ::kurento;

using boost::shared_ptr;
using ::kurento::MediaServerServiceHandler;
using ::Glib::KeyFile;
using ::Glib::KeyFileFlags;

#define DEFAULT_CONFIG_FILE "/etc/kurento/kurento.conf"

#define MEDIA_SERVER_ADDRESS_KEY "serverAddress"
#define MEDIA_SERVER_SERVICE_PORT_KEY "serverPort"

static std::string serverAddress;
static gint serverServicePort;
static GstSDPMessage *sdp_message;
static KeyFile configFile;

Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create (true);
static TNonblockingServer *p_server = NULL;

static gchar *conf_file;

static GOptionEntry entries[] = {
  {
    "conf-file", 'f', 0, G_OPTION_ARG_FILENAME, &conf_file, "Configuration file",
    NULL
  },
  {NULL}
};

static void
create_media_server_service ()
{
  int port;
  port = MEDIA_SERVER_SERVICE_PORT;
  shared_ptr < MediaServerServiceHandler >
  handler (new MediaServerServiceHandler () );
  shared_ptr < TProcessor >
  processor (new MediaServerServiceProcessor (handler) );
  shared_ptr < TProtocolFactory >
  protocolFactory (new TBinaryProtocolFactory () );
  shared_ptr < PosixThreadFactory > threadFactory (new PosixThreadFactory () );
  shared_ptr < ThreadManager > threadManager =
    ThreadManager::newSimpleThreadManager (15);
  threadManager->threadFactory (threadFactory);
  threadManager->start ();
  TNonblockingServer server (processor, protocolFactory, port, threadManager);
  p_server = &server;
  GST_INFO ("Starting MediaServerService");
  kill (getppid(), SIGCONT);
  server.serve ();
  GST_INFO ("MediaServerService stopped finishing thread");
  throw Glib::Thread::Exit ();
}

static void
check_port (int port)
{
  if (port <= 0 || port > G_MAXUSHORT)
    throw Glib::KeyFileError (Glib::KeyFileError::PARSE, "Invalid value");
}

static void
set_default_server_config ()
{
  serverAddress = MEDIA_SERVER_ADDRESS;
  serverServicePort = MEDIA_SERVER_SERVICE_PORT;
}

static void
load_config (const std::string &file_name)
{
  gint port;
  GST_INFO ("Reading configuration from: %s", file_name.c_str () );
  /* Try to open de file */
  {
    std::ifstream file (file_name);

    if (!file) {
      GST_INFO ("Config file not found, creating a new one");
      std::ofstream of (file_name);
    }
  }

  try {
    if (!configFile.load_from_file (file_name,
        KeyFileFlags::KEY_FILE_KEEP_COMMENTS |
        KeyFileFlags::KEY_FILE_KEEP_TRANSLATIONS) ) {
      GST_WARNING ("Error loading configuration from %s, loading "
          "default server config, but no "
          "codecs will be available", file_name.c_str () );
      set_default_server_config ();
      return;
    }
  } catch (Glib::Error ex) {
    GST_WARNING ("Error loading configuration: %s", ex.what ().c_str () );
    GST_WARNING ("Error loading configuration from %s, loading "
        "default server config, but no "
        "codecs will be available", file_name.c_str () );
    set_default_server_config ();
    return;
  }

  try {
    serverAddress = configFile.get_string (SERVER_GROUP,
        MEDIA_SERVER_ADDRESS_KEY);
  } catch (Glib::KeyFileError err) {
    GST_INFO (err.what ().c_str () );
    GST_INFO ("Setting default address");
    configFile.set_string (SERVER_GROUP, MEDIA_SERVER_ADDRESS_KEY,
        MEDIA_SERVER_ADDRESS);
    serverAddress = MEDIA_SERVER_ADDRESS;
  }

  try {
    port = configFile.get_integer (SERVER_GROUP, MEDIA_SERVER_SERVICE_PORT_KEY);
    check_port (port);
    serverServicePort = port;
  } catch (Glib::KeyFileError err) {
    GST_INFO (err.what ().c_str () );
    GST_INFO ("Setting default server port");
    configFile.set_integer (SERVER_GROUP, MEDIA_SERVER_SERVICE_PORT_KEY,
        MEDIA_SERVER_SERVICE_PORT);
    serverServicePort = MEDIA_SERVER_SERVICE_PORT;
  }

  try {
    sdp_message = load_session_descriptor (configFile);
  } catch (Glib::KeyFileError err) {
    GST_WARNING (err.what ().c_str () );
    GST_WARNING ("Wrong codec configuration, communication won't be possible");
  }

  std::ofstream f (file_name, std::ios::out | std::ios::trunc);
  f << configFile.to_data ();
  f.close ();
  GST_INFO ("Configuration loaded successfully");
  GST_DEBUG ("Final config file:\n%s", configFile.to_data ().c_str () );
}

static void
initialiseExecutableName (char *exe, int size)
{
  char link[1024];
  int len;
  snprintf (link, sizeof (link), "/proc/%d/exe", getpid () );
  len = readlink (link, exe, size);

  if (len == -1) {
    fprintf (stderr, "ERROR GETTING NAME\n");
    exit (1);
  }

  exe[len] = '\0';
}

static const char *
getExecutableName ()
{
  static char *exe = NULL;
  static char aux[1024];

  if (exe == NULL) {
    initialiseExecutableName (aux, sizeof (aux) );
    exe = aux;
  }

  return exe;
}

static bool
quit_loop ()
{
  loop->quit ();

  return FALSE;
}

static void
bt_sighandler (int sig, siginfo_t *info, gpointer data)
{
  void *trace[35];
  char **messages = (char **) NULL;
  int i, trace_size = 0;

//      ucontext_t *uc = (ucontext_t *)data;

  /* Do something useful with siginfo_t */
  if (sig == SIGSEGV) {
    printf ("Got signal %d, faulty address is %p\n", sig,
        (gpointer) info->si_addr);
  } else if (sig == SIGKILL || sig == SIGINT) {
    /* since we connect to a signal handler, asynchronous management might */
    /* might happen so we need to set an idle handler to exit the main loop */
    /* in the mainloop context. */
    Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create ();
    idle_source->connect (sigc::ptr_fun (&quit_loop) );
    idle_source->attach (loop->get_context() );
    return;
  } else {
    printf ("Got signal %d\n", sig);
  }

  trace_size = backtrace (trace, 35);
  /* overwrite sigaction with caller's address */
  //trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
  messages = backtrace_symbols (trace, trace_size);
  /* skip first stack frame (points here) */
  g_print ("\t[bt] Execution path:\n");

  for (i = 1; i < trace_size; ++i) {
    g_print ("\t[bt] #%d %s\n", i, messages[i]);
    char syscom[256];
    gchar **strs;
    const gchar *exe;
    strs = g_strsplit (messages[i], "(", 2);

    if (strs[1] == NULL)
      exe = getExecutableName ();
    else
      exe = strs[0];

    sprintf (syscom, "echo -n \"\t[bt]\t\t\"; addr2line %p -s -e %s",
        trace[i], exe);
    g_strfreev (strs);
    system (syscom);
  }

  if (sig == SIGPIPE) {
    GST_DEBUG ("Ignore sigpipe");
  } else {
    exit (sig);
  }
}

int
main (int argc, char **argv)
{
  GError *error = NULL;
  GOptionContext *context;
  struct sigaction sa;
  context = g_option_context_new ("");
  g_option_context_add_main_entries (context, entries, NULL);
  g_option_context_add_group (context, gst_init_get_option_group () );

  if (!g_option_context_parse (context, &argc, &argv, &error) ) {
    GST_ERROR ("option parsing failed: %s\n", error->message);
    exit (1);
  }

  g_option_context_free (context);

  gst_init (&argc, &argv);
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);
  /* Install our signal handler */
  sa.sa_sigaction = /*(void (*)(int, siginfo*, gpointer)) */ bt_sighandler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_RESTART | SA_SIGINFO;
  sigaction (SIGSEGV, &sa, NULL);
  sigaction (SIGPIPE, &sa, NULL);
  sigaction (SIGINT, &sa, NULL);
  sigaction (SIGKILL, &sa, NULL);
  Glib::thread_init ();
  GST_INFO ("Kmsc version: %s", get_version () );

  if (!conf_file)
    load_config (DEFAULT_CONFIG_FILE);
  else
    load_config ( (std::string) conf_file);

  sigc::slot < void >ss = sigc::ptr_fun (&create_media_server_service);
  Glib::Thread::create (ss, true); /* Created thread not used to join
                                      because of a bug in thrift */
  loop->run ();

  return 0;
}
<|endoftext|>


<commit_before>#include "getusername.h"
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include <unistd.h>
#include <string>

using namespace std;

const string utf8 = "UTF-8";

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx
// Sets errno to:
//     ERROR_INVALID_PARAMETER - parameter is not valid
//     ERROR_BAD_ENVIRONMENT - locale is not UTF-8
//     ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files
//     ERROR_NO_ASSOCIATION - calling process has no controlling terminal
//     ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string
//     ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file
//     ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure
//     ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal
//     ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code
//
// Returns:
//     1 - succeeded
//     0 - failed
BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize)
{
	errno = 0;

	// Check parameters
	if (!lpBuffer || !lpnSize) {
		errno = ERROR_INVALID_PARAMETER;
		return 0;
	}

	// Select locale from environment
	setlocale(LC_ALL, "");
	// Check that locale is UTF-8
	if (nl_langinfo(CODESET) != utf8) {
		errno = ERROR_BAD_ENVIRONMENT;
		return 0;
	}

	// Get username from system in a thread-safe manner
	char userName[*lpnSize];
	int err = getlogin_r(userName, *lpnSize);
	// Map errno to Win32 Error Codes
	if (err != 0) {
		switch (errno) {
		case EMFILE:
		case ENFILE:
			errno = ERROR_TOO_MANY_OPEN_FILES;
			break;
		case ENXIO:
			errno = ERROR_NO_ASSOCIATION;
			break;
		case ERANGE:
			errno = ERROR_INSUFFICIENT_BUFFER;
			break;
		case ENOENT:
			errno = ERROR_NO_SUCH_USER;
			break;
		case ENOMEM:
			errno = ERROR_OUTOFMEMORY;
			break;
		case ENOTTY:
			errno = ERROR_NO_ASSOCIATION;
			break;
		default:
			errno = ERROR_INVALID_FUNCTION;
		}
		return 0;
	}

	// TODO: Convert to char* to wchar* (UTF-8 to UTF-16 LE w/o BOM)

	// Unfortunately codecvt is not yet supported by G++, othwerise:
	// wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> conversion;

	// TODO: Use PAL's Unicode converters

	// TODO: set the lpnSize to the userName length (see msdn)

	return 1;
}

<commit_msg>Convert get_login_r to UTF-16 and return<commit_after>#include "getusername.h"
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <scxcorelib/scxstrencodingconv.h>

using std::string;
using std::vector;

using SCXCoreLib::Utf8ToUtf16le;

const string utf8 = "UTF-8";

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx
// Sets errno to:
//     ERROR_INVALID_PARAMETER - parameter is not valid
//     ERROR_BAD_ENVIRONMENT - locale is not UTF-8
//     ERROR_TOO_MANY_OPEN_FILES - already have the maximum allowed number of open files
//     ERROR_NO_ASSOCIATION - calling process has no controlling terminal
//     ERROR_INSUFFICIENT_BUFFER - buffer not large enough to hold username string
//     ERROR_NO_SUCH_USER - there was no corresponding entry in the utmp-file
//     ERROR_OUTOFMEMORY - insufficient memory to allocate passwd structure
//     ERROR_NO_ASSOCIATION - standard input didn't refer to a terminal
//     ERROR_INVALID_FUNCTION - getlogin_r() returned an unrecognized error code
//
// Returns:
//     1 - succeeded
//     0 - failed
BOOL GetUserName(WCHAR_T *lpBuffer, LPDWORD lpnSize)
{
	errno = 0;

	// Check parameters
	if (!lpBuffer || !lpnSize) {
		errno = ERROR_INVALID_PARAMETER;
		return 0;
	}

	// Select locale from environment
	setlocale(LC_ALL, "");
	// Check that locale is UTF-8
	if (nl_langinfo(CODESET) != utf8) {
		errno = ERROR_BAD_ENVIRONMENT;
		return 0;
	}

	// Get username from system in a thread-safe manner
	char userName[*lpnSize];
	int err = getlogin_r(userName, *lpnSize);
	// Map errno to Win32 Error Codes
	if (err != 0) {
		switch (errno) {
		case EMFILE:
		case ENFILE:
			errno = ERROR_TOO_MANY_OPEN_FILES;
			break;
		case ENXIO:
			errno = ERROR_NO_ASSOCIATION;
			break;
		case ERANGE:
			errno = ERROR_INSUFFICIENT_BUFFER;
			break;
		case ENOENT:
			errno = ERROR_NO_SUCH_USER;
			break;
		case ENOMEM:
			errno = ERROR_OUTOFMEMORY;
			break;
		case ENOTTY:
			errno = ERROR_NO_ASSOCIATION;
			break;
		default:
			errno = ERROR_INVALID_FUNCTION;
		}
		return 0;
	}

	// Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM)
	string input = string(userName);
	vector<unsigned char> output;
	Utf8ToUtf16le(input, output);

	if (output.size()/2 + 1 > *lpnSize) {
		errno = ERROR_INSUFFICIENT_BUFFER;
		return 0;
	}

	// Add two null bytes (because it's UTF-16)
	output.push_back('\0');
	output.push_back('\0');

	memcpy(lpBuffer, &output[0], output.size());
	*lpnSize = output.size()/2;

	return 1;
}
<|endoftext|>


<commit_before>#ifndef JOINT_CPP_STRING_HPP
#define JOINT_CPP_STRING_HPP

#include <algorithm>

#include <joint.cpp/BytesView.hpp>
#include <joint.cpp/detail/Iterator.hpp>

namespace joint
{

	class Utf32View
	{
		typedef char Byte;
		typedef uint32_t value_type;

	public:
		class iterator : public detail::IteratorOps<iterator, value_type, value_type>
		{
			friend class Utf32View;
			friend class detail::IteratorOps<iterator, value_type, value_type>;

		private:
			const Byte* _begin;
			const Byte* _end;
			const Byte* _ptr;

		public:
			iterator() { }

		protected:
			iterator(const Byte* begin, const Byte* end, const Byte* ptr)
				: _begin(begin), _end(end), _ptr(ptr)
			{ }

			bool Equals(iterator other) const
			{ return _ptr == other._ptr; }

			value_type Dereference() const
			{
				Byte firstByte = *_ptr;
				value_type valueMask = 0x7F;
				size_t len = 0;
				for (; len < 4; ++len)
				{
					if ((firstByte & ~valueMask) != ~valueMask)
						break;
					valueMask >>= 1;
				}
				len = std::min(len, size_t(_end - _ptr));

				value_type result = firstByte & valueMask;
				for (size_t i = 1; i < len; ++i)
					result = (result << 6) | (*(_ptr + i) & 0x3F);

				return result;
			}

			void Increment()
			{
				while (_ptr < _end && (*(++_ptr) & 0xC0) == 0x80)
				{ }
			}

			void Decrement()
			{
				while (_ptr > _begin && (*(--_ptr) & 0xC0) == 0x80)
				{ }
			}
		};

		typedef iterator const_iterator;

	private:
		BytesView _bytes;

	public:
		explicit Utf32View(BytesView bytes)
			: _bytes(bytes)
		{ }

		const_iterator begin() const { return const_iterator(_bytes.begin(), _bytes.end(), _bytes.begin()); }
		const_iterator end() const { return const_iterator(_bytes.begin(), _bytes.end(), _bytes.end()); }
	};

	Utf32View::const_iterator begin(const Utf32View& v) { return v.begin(); }
	Utf32View::const_iterator end(const Utf32View& v) { return v.end(); }

	namespace detail
	{
		template < typename String_ >
		class StringImpl
		{
		public:
			BytesView Utf8Bytes() const { return BytesView(Self().Data(), Self().Size()); }
			joint::Utf32View Utf32View() const { return joint::Utf32View(Utf8Bytes()); }

		protected:
			~StringImpl() { }

		private:
			const String_& Self() const { return static_cast<const String_&>(*this); }
		};
	}

	class StringRef : public detail::StringImpl<StringRef>
	{
		friend class detail::StringImpl<StringRef>;

	private:
		const char*   _data;
		size_t        _size;

	public:
		StringRef(const char* data) // TODO: is this ok?
			: _data(data), _size(strlen(data) + 1)
		{ }

		StringRef(const char* data, size_t size)
			: _data(data), _size(size)
		{ }

	protected:
		const char* Data() const { return _data; }
		size_t Size() const { return _size; }
	};

	class String : public detail::StringImpl<String>
	{
		friend class detail::StringImpl<String>;

	private:
		std::string   _storage;

	public:
		String()
		{ }

		String(const char* value) // TODO: is this ok?
			: _storage(value)
		{ }

		explicit String(StringRef stringRef)
			: _storage(stringRef.Utf8Bytes().data(), stringRef.Utf8Bytes().size())
		{ }

		explicit String(const std::string& storage)
			: _storage(storage)
		{ }

		std::string& Storage() { return _storage; }
		const std::string& Storage() const { return _storage; }

		operator StringRef() const
		{ return StringRef(Utf8Bytes().data(), Utf8Bytes().size()); }

	protected:
		const char* Data() const { return _storage.c_str(); }
		size_t Size() const { return _storage.size() + 1; }
	};

	inline std::ostream& operator<<(std::ostream& s, const String& str)
	{ return s << str.Utf8Bytes().data(); }

	template < typename String1_, typename String2_ >
	String operator+(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{
		String result(l.Utf8Bytes().data()); // TODO: reimplement
		result.Storage() += r.Utf8Bytes().data();
		return result;
	}

	template < typename String1_, typename String2_ >
	bool operator==(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{
		BytesView lb = l.Utf8Bytes();
		BytesView rb = r.Utf8Bytes();
		return strncmp(lb.data(), rb.data(), std::min(lb.size(), rb.size())) == 0;
	}

	template < typename String1_, typename String2_ >
	bool operator!=(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{ return !(l == r); }

}

#endif
<commit_msg>Template std::ostream write operator for joint::String<commit_after>#ifndef JOINT_CPP_STRING_HPP
#define JOINT_CPP_STRING_HPP

#include <algorithm>

#include <joint.cpp/BytesView.hpp>
#include <joint.cpp/detail/Iterator.hpp>

namespace joint
{

	class Utf32View
	{
		typedef char Byte;
		typedef uint32_t value_type;

	public:
		class iterator : public detail::IteratorOps<iterator, value_type, value_type>
		{
			friend class Utf32View;
			friend class detail::IteratorOps<iterator, value_type, value_type>;

		private:
			const Byte* _begin;
			const Byte* _end;
			const Byte* _ptr;

		public:
			iterator() { }

		protected:
			iterator(const Byte* begin, const Byte* end, const Byte* ptr)
				: _begin(begin), _end(end), _ptr(ptr)
			{ }

			bool Equals(iterator other) const
			{ return _ptr == other._ptr; }

			value_type Dereference() const
			{
				Byte firstByte = *_ptr;
				value_type valueMask = 0x7F;
				size_t len = 0;
				for (; len < 4; ++len)
				{
					if ((firstByte & ~valueMask) != ~valueMask)
						break;
					valueMask >>= 1;
				}
				len = std::min(len, size_t(_end - _ptr));

				value_type result = firstByte & valueMask;
				for (size_t i = 1; i < len; ++i)
					result = (result << 6) | (*(_ptr + i) & 0x3F);

				return result;
			}

			void Increment()
			{
				while (_ptr < _end && (*(++_ptr) & 0xC0) == 0x80)
				{ }
			}

			void Decrement()
			{
				while (_ptr > _begin && (*(--_ptr) & 0xC0) == 0x80)
				{ }
			}
		};

		typedef iterator const_iterator;

	private:
		BytesView _bytes;

	public:
		explicit Utf32View(BytesView bytes)
			: _bytes(bytes)
		{ }

		const_iterator begin() const { return const_iterator(_bytes.begin(), _bytes.end(), _bytes.begin()); }
		const_iterator end() const { return const_iterator(_bytes.begin(), _bytes.end(), _bytes.end()); }
	};

	Utf32View::const_iterator begin(const Utf32View& v) { return v.begin(); }
	Utf32View::const_iterator end(const Utf32View& v) { return v.end(); }

	namespace detail
	{
		template < typename String_ >
		class StringImpl
		{
		public:
			BytesView Utf8Bytes() const { return BytesView(Self().Data(), Self().Size()); }
			joint::Utf32View Utf32View() const { return joint::Utf32View(Utf8Bytes()); }

		protected:
			~StringImpl() { }

		private:
			const String_& Self() const { return static_cast<const String_&>(*this); }
		};
	}

	class StringRef : public detail::StringImpl<StringRef>
	{
		friend class detail::StringImpl<StringRef>;

	private:
		const char*   _data;
		size_t        _size;

	public:
		StringRef(const char* data) // TODO: is this ok?
			: _data(data), _size(strlen(data) + 1)
		{ }

		StringRef(const char* data, size_t size)
			: _data(data), _size(size)
		{ }

	protected:
		const char* Data() const { return _data; }
		size_t Size() const { return _size; }
	};

	class String : public detail::StringImpl<String>
	{
		friend class detail::StringImpl<String>;

	private:
		std::string   _storage;

	public:
		String()
		{ }

		String(const char* value) // TODO: is this ok?
			: _storage(value)
		{ }

		explicit String(StringRef stringRef)
			: _storage(stringRef.Utf8Bytes().data(), stringRef.Utf8Bytes().size())
		{ }

		explicit String(const std::string& storage)
			: _storage(storage)
		{ }

		std::string& Storage() { return _storage; }
		const std::string& Storage() const { return _storage; }

		operator StringRef() const
		{ return StringRef(Utf8Bytes().data(), Utf8Bytes().size()); }

	protected:
		const char* Data() const { return _storage.c_str(); }
		size_t Size() const { return _storage.size() + 1; }
	};

	template < typename String_ >
	std::ostream& operator<<(std::ostream& s, const detail::StringImpl<String_>& str)
	{ return s << str.Utf8Bytes().data(); }

	template < typename String1_, typename String2_ >
	String operator+(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{
		String result(l.Utf8Bytes().data()); // TODO: reimplement
		result.Storage() += r.Utf8Bytes().data();
		return result;
	}

	template < typename String1_, typename String2_ >
	bool operator==(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{
		BytesView lb = l.Utf8Bytes();
		BytesView rb = r.Utf8Bytes();
		return strncmp(lb.data(), rb.data(), std::min(lb.size(), rb.size())) == 0;
	}

	template < typename String1_, typename String2_ >
	bool operator!=(const detail::StringImpl<String1_>& l, const detail::StringImpl<String2_>& r)
	{ return !(l == r); }

}

#endif
<|endoftext|>


<commit_before>// Copyright 2014 BVLC and contributors.
//
// This is a simple script that allows one to quickly test a network whose
// structure is specified by text format protocol buffers, and whose parameter
// are loaded from a pre-trained network.
// Usage:
//    test_net net_proto pretrained_net_proto iterations [CPU/GPU]

#include <cuda_runtime.h>

#include <cstring>
#include <cstdlib>
#include <vector>

#include "caffe/caffe.hpp"

using namespace caffe;  // NOLINT(build/namespaces)

int main(int argc, char** argv) {
  if (argc < 4 || argc > 6) {
    LOG(ERROR) << "test_net net_proto pretrained_net_proto iterations "
        << "[CPU/GPU] [Device ID]";
    return 1;
  }

  Caffe::set_phase(Caffe::TEST);

  if (argc >= 5 && strcmp(argv[4], "GPU") == 0) {
    Caffe::set_mode(Caffe::GPU);
    int device_id = 0;
    if (argc == 6) {
      device_id = atoi(argv[5]);
    }
    Caffe::SetDevice(device_id);
    LOG(ERROR) << "Using GPU #" << device_id;
  } else {
    LOG(ERROR) << "Using CPU";
    Caffe::set_mode(Caffe::CPU);
  }

  Net<float> caffe_test_net(argv[1]);
  NetParameter trained_net_param;
  ReadProtoFromBinaryFile(argv[2], &trained_net_param);
  caffe_test_net.CopyTrainedLayersFrom(trained_net_param);

  int total_iter = atoi(argv[3]);
  LOG(ERROR) << "Running " << total_iter << " iterations.";

  double test_accuracy = 0;
  for (int i = 0; i < total_iter; ++i) {
    const vector<Blob<float>*>& result = caffe_test_net.ForwardPrefilled();
    test_accuracy += result[0]->cpu_data()[0];
    LOG(ERROR) << "Batch " << i << ", accuracy: " << result[0]->cpu_data()[0];
  }
  test_accuracy /= total_iter;
  LOG(ERROR) << "Test accuracy: " << test_accuracy;

  return 0;
}
<commit_msg>fix test_net to upgrade params from v0 if needed<commit_after>// Copyright 2014 BVLC and contributors.
//
// This is a simple script that allows one to quickly test a network whose
// structure is specified by text format protocol buffers, and whose parameter
// are loaded from a pre-trained network.
// Usage:
//    test_net net_proto pretrained_net_proto iterations [CPU/GPU]

#include <cuda_runtime.h>

#include <cstring>
#include <cstdlib>
#include <vector>

#include "caffe/caffe.hpp"

using namespace caffe;  // NOLINT(build/namespaces)

int main(int argc, char** argv) {
  if (argc < 4 || argc > 6) {
    LOG(ERROR) << "test_net net_proto pretrained_net_proto iterations "
        << "[CPU/GPU] [Device ID]";
    return 1;
  }

  Caffe::set_phase(Caffe::TEST);

  if (argc >= 5 && strcmp(argv[4], "GPU") == 0) {
    Caffe::set_mode(Caffe::GPU);
    int device_id = 0;
    if (argc == 6) {
      device_id = atoi(argv[5]);
    }
    Caffe::SetDevice(device_id);
    LOG(ERROR) << "Using GPU #" << device_id;
  } else {
    LOG(ERROR) << "Using CPU";
    Caffe::set_mode(Caffe::CPU);
  }

  Net<float> caffe_test_net(argv[1]);
  caffe_test_net.CopyTrainedLayersFrom(argv[2]);

  int total_iter = atoi(argv[3]);
  LOG(ERROR) << "Running " << total_iter << " iterations.";

  double test_accuracy = 0;
  for (int i = 0; i < total_iter; ++i) {
    const vector<Blob<float>*>& result = caffe_test_net.ForwardPrefilled();
    test_accuracy += result[0]->cpu_data()[0];
    LOG(ERROR) << "Batch " << i << ", accuracy: " << result[0]->cpu_data()[0];
  }
  test_accuracy /= total_iter;
  LOG(ERROR) << "Test accuracy: " << test_accuracy;

  return 0;
}
<|endoftext|>


<commit_before>// A command-line tool for exercising the CCTZ library.

#include <getopt.h>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include "src/cctz.h"

// Parse() specifiers for command-line time arguments.
const char* const kFormats[] = {
  "%Y   %m   %d   %H   %M   %E*S",
  "%Y - %m - %d T %H : %M : %E*S",
  "%Y - %m - %d %H : %M : %E*S",
  "%Y - %m - %d T %H : %M",
  "%Y - %m - %d %H : %M",
  "%Y - %m - %d",
  "%a %b %d %H : %M : %E*S %Z %Y",
  "%a %e %b %Y %H : %M : %E*S",
  "%a %b %e %Y %H : %M : %E*S",
  "%e %b %Y %H : %M : %E*S",
  "%b %e %Y %H : %M : %E*S",
  "%a %e %b %Y %H : %M",
  "%a %b %e %Y %H : %M",
  "%e %b %Y %H : %M",
  "%b %e %Y %H : %M",
  "%a %e %b %Y",
  "%a %b %e %Y",
  "%e %b %Y",
  "%b %e %Y",
  nullptr
};

bool ParseTimeSpec(const std::string& args, cctz::TimeZone zone,
                   cctz::time_point* when) {
  for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) {
    const std::string format = std::string(*fmt) + " %Ez";
    cctz::time_point tp;
    if (cctz::Parse(format, args, zone, &tp)) {
      *when = tp;
      return true;
    }
  }
  return false;
}

bool ParseBreakdownSpec(const std::string& args, cctz::TimeZone zone,
                        cctz::Breakdown* when) {
  const cctz::TimeZone utc = cctz::UTCTimeZone();
  for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) {
    cctz::time_point tp;
    if (cctz::Parse(*fmt, args, utc, &tp)) {
      *when = cctz::BreakTime(tp, utc);
      return true;
    }
  }
  return false;
}

// The FormatTime() specifier for output.
const char* const kFormat = "%Y-%m-%d %H:%M:%S %Ez (%Z)";

const char* const kWeekDayNames[] = {
  "Unused", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
};

std::string FormatTimeInZone(cctz::time_point when, cctz::TimeZone zone) {
  std::ostringstream oss;
  oss << std::setw(33) << std::left << cctz::Format(kFormat, when, zone);
  cctz::Breakdown bd = cctz::BreakTime(when, zone);
  oss << " [wd=" << kWeekDayNames[bd.weekday]
      << " yd=" << std::setw(3) << std::setfill('0') << bd.yearday
      << " dst=" << (bd.is_dst ? 'T' : 'F')
      << " off=" << std::showpos << bd.offset << std::noshowpos << "]";
  return oss.str();
}

void InstantInfo(const std::string& label, cctz::time_point when,
                 cctz::TimeZone zone) {
  const cctz::TimeZone utc = cctz::UTCTimeZone();  // might == zone
  const std::string time_label = "time_t";
  const std::string utc_label = "UTC";
  const std::string zone_label = "in-tz";
  std::size_t width =
      2 + std::max(std::max(time_label.size(), utc_label.size()),
                   zone_label.size());
  std::cout << label << " {\n";
  std::cout << std::setw(width) << std::right << time_label << ": ";
  std::time_t seconds = std::chrono::system_clock::to_time_t(when);
  std::cout << std::setw(10) << seconds;
  if (seconds >= (1LL << 31)) std::cout << " [>31b]";
  std::cout << "\n";
  std::cout << std::setw(width) << std::right << utc_label << ": ";
  std::cout << FormatTimeInZone(when, utc) << "\n";
  std::cout << std::setw(width) << std::right << zone_label << ": ";
  std::cout << FormatTimeInZone(when, zone) << "\n";
  std::cout << "}\n";
}

// Report everything we know about a Breakdown (YMDHMS).
int BreakdownInfo(const cctz::Breakdown& when, cctz::TimeZone zone) {
  cctz::TimeInfo ti =
      cctz::MakeTimeInfo(when.year, when.month, when.day,
                         when.hour, when.minute, when.second, zone);
  switch (ti.kind) {
    case cctz::TimeInfo::Kind::UNIQUE: {
      std::cout << "kind: UNIQUE\n";
      InstantInfo("when", ti.pre, zone);
      break;
    }
    case cctz::TimeInfo::Kind::SKIPPED: {
      std::cout << "kind: SKIPPED\n";
      InstantInfo("post", ti.post, zone);  // might == trans-1
      InstantInfo("trans-1", ti.trans - std::chrono::seconds(1), zone);
      InstantInfo("trans", ti.trans, zone);
      InstantInfo("pre", ti.pre, zone);  // might == trans
      break;
    }
    case cctz::TimeInfo::Kind::REPEATED: {
      std::cout << "kind: REPEATED\n";
      InstantInfo("pre", ti.pre, zone);  // might == trans-1
      InstantInfo("trans-1", ti.trans - std::chrono::seconds(1), zone);
      InstantInfo("trans", ti.trans, zone);
      InstantInfo("post", ti.post, zone);  // might == trans
      break;
    }
  }
  return 0;
}

// Report everything we know about a time_point.
int TimeInfo(cctz::time_point when, cctz::TimeZone zone) {
  std::cout << "kind: UNIQUE\n";
  InstantInfo("when", when, zone);
  return 0;
}

const char* Basename(const char* p) {
  if (const char* b = strrchr(p, '/')) return ++b;
  return p;
}

// std::regex doesn't work before gcc 4.9.
bool LooksLikeNegOffset(const char* s) {
  if (s[0] == '-' && std::isdigit(s[1]) && std::isdigit(s[2])) {
    int i = (s[3] == ':') ? 4 : 3;
    if (std::isdigit(s[i]) && std::isdigit(s[i + 1])) {
      return s[i + 2] == '\0';
    }
  }
  return false;
}

int main(int argc, char** argv) {
  std::string prog = argv[0] ? Basename(argv[0]) : "time_tool";

  // Escape arguments that look like negative offsets so that they
  // don't look like flags.
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--") == 0) break;
    if (LooksLikeNegOffset(argv[i])) {
      char* buf = new char[strlen(argv[i] + 2)];
      buf[0] = ' ';  // will later be ignorned
      strcpy(buf + 1, argv[i]);
      argv[i] = buf;
    }
  }

  // Determine the time zone.
  cctz::TimeZone zone = cctz::LocalTimeZone();
  for (;;) {
    static option opts[] = {
        {"zone", required_argument, nullptr, 'z'},
        {nullptr, 0, nullptr, 0},
    };
    int c = getopt_long(argc, argv, "z:", opts, nullptr);
    if (c == -1) break;
    switch (c) {
      case 'z':
        if (!cctz::LoadTimeZone(optarg, &zone)) {
          std::cerr << optarg << ": Unrecognized time zone\n";
          return 1;
        }
        break;
      default:
        std::cerr << "Usage: " << prog << " [--zone=<zone>] [<time-spec>]\n";
        return 1;
    }
  }

  // Determine the time point.
  cctz::time_point tp = std::chrono::system_clock::now();
  std::string args;
  for (int i = optind; i < argc; ++i) {
    if (i != optind) args += " ";
    args += argv[i];
  }
  std::replace(args.begin(), args.end(), ',', ' ');
  std::replace(args.begin(), args.end(), '/', '-');
  bool have_time = ParseTimeSpec(args, zone, &tp);
  if (!have_time && !args.empty()) {
    std::string spec = args.substr((args[0] == '@') ? 1 : 0);
    if ((spec.size() > 0 && std::isdigit(spec[0])) ||
        (spec.size() > 1 && spec[0] == '-' && std::isdigit(spec[1]))) {
      std::size_t end;
      const time_t t = std::stoll(spec, &end);
      if (end == spec.size()) {
        tp = std::chrono::system_clock::from_time_t(t);
        have_time = true;
      }
    }
  }
  cctz::Breakdown when = cctz::BreakTime(tp, zone);
  bool have_break_down = !have_time && ParseBreakdownSpec(args, zone, &when);

  // Show results.
  if (have_break_down) return BreakdownInfo(when, zone);
  if (have_time || args.empty()) return TimeInfo(tp, zone);

  std::cerr << args << ": Malformed time spec\n";
  return 1;
}
<commit_msg>Use Format("%s") to display the "time_t" value for a time_point.<commit_after>// A command-line tool for exercising the CCTZ library.

#include <getopt.h>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include "src/cctz.h"

// Parse() specifiers for command-line time arguments.
const char* const kFormats[] = {
  "%Y   %m   %d   %H   %M   %E*S",
  "%Y - %m - %d T %H : %M : %E*S",
  "%Y - %m - %d %H : %M : %E*S",
  "%Y - %m - %d T %H : %M",
  "%Y - %m - %d %H : %M",
  "%Y - %m - %d",
  "%a %b %d %H : %M : %E*S %Z %Y",
  "%a %e %b %Y %H : %M : %E*S",
  "%a %b %e %Y %H : %M : %E*S",
  "%e %b %Y %H : %M : %E*S",
  "%b %e %Y %H : %M : %E*S",
  "%a %e %b %Y %H : %M",
  "%a %b %e %Y %H : %M",
  "%e %b %Y %H : %M",
  "%b %e %Y %H : %M",
  "%a %e %b %Y",
  "%a %b %e %Y",
  "%e %b %Y",
  "%b %e %Y",
  nullptr
};

bool ParseTimeSpec(const std::string& args, cctz::TimeZone zone,
                   cctz::time_point* when) {
  for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) {
    const std::string format = std::string(*fmt) + " %Ez";
    cctz::time_point tp;
    if (cctz::Parse(format, args, zone, &tp)) {
      *when = tp;
      return true;
    }
  }
  return false;
}

bool ParseBreakdownSpec(const std::string& args, cctz::TimeZone zone,
                        cctz::Breakdown* when) {
  const cctz::TimeZone utc = cctz::UTCTimeZone();
  for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) {
    cctz::time_point tp;
    if (cctz::Parse(*fmt, args, utc, &tp)) {
      *when = cctz::BreakTime(tp, utc);
      return true;
    }
  }
  return false;
}

// The FormatTime() specifier for output.
const char* const kFormat = "%Y-%m-%d %H:%M:%S %Ez (%Z)";

const char* const kWeekDayNames[] = {
  "Unused", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
};

std::string FormatTimeInZone(cctz::time_point when, cctz::TimeZone zone) {
  std::ostringstream oss;
  oss << std::setw(33) << std::left << cctz::Format(kFormat, when, zone);
  cctz::Breakdown bd = cctz::BreakTime(when, zone);
  oss << " [wd=" << kWeekDayNames[bd.weekday]
      << " yd=" << std::setw(3) << std::setfill('0') << bd.yearday
      << " dst=" << (bd.is_dst ? 'T' : 'F')
      << " off=" << std::showpos << bd.offset << std::noshowpos << "]";
  return oss.str();
}

void InstantInfo(const std::string& label, cctz::time_point when,
                 cctz::TimeZone zone) {
  const cctz::TimeZone utc = cctz::UTCTimeZone();  // might == zone
  const std::string time_label = "time_t";
  const std::string utc_label = "UTC";
  const std::string zone_label = "in-tz";
  std::size_t width =
      2 + std::max(std::max(time_label.size(), utc_label.size()),
                   zone_label.size());
  std::cout << label << " {\n";
  std::cout << std::setw(width) << std::right << time_label << ": ";
  std::cout << std::setw(10) << Format("%s", when, utc);
  std::cout << "\n";
  std::cout << std::setw(width) << std::right << utc_label << ": ";
  std::cout << FormatTimeInZone(when, utc) << "\n";
  std::cout << std::setw(width) << std::right << zone_label << ": ";
  std::cout << FormatTimeInZone(when, zone) << "\n";
  std::cout << "}\n";
}

// Report everything we know about a Breakdown (YMDHMS).
int BreakdownInfo(const cctz::Breakdown& when, cctz::TimeZone zone) {
  cctz::TimeInfo ti =
      cctz::MakeTimeInfo(when.year, when.month, when.day,
                         when.hour, when.minute, when.second, zone);
  switch (ti.kind) {
    case cctz::TimeInfo::Kind::UNIQUE: {
      std::cout << "kind: UNIQUE\n";
      InstantInfo("when", ti.pre, zone);
      break;
    }
    case cctz::TimeInfo::Kind::SKIPPED: {
      std::cout << "kind: SKIPPED\n";
      InstantInfo("post", ti.post, zone);  // might == trans-1
      InstantInfo("trans-1", ti.trans - std::chrono::seconds(1), zone);
      InstantInfo("trans", ti.trans, zone);
      InstantInfo("pre", ti.pre, zone);  // might == trans
      break;
    }
    case cctz::TimeInfo::Kind::REPEATED: {
      std::cout << "kind: REPEATED\n";
      InstantInfo("pre", ti.pre, zone);  // might == trans-1
      InstantInfo("trans-1", ti.trans - std::chrono::seconds(1), zone);
      InstantInfo("trans", ti.trans, zone);
      InstantInfo("post", ti.post, zone);  // might == trans
      break;
    }
  }
  return 0;
}

// Report everything we know about a time_point.
int TimeInfo(cctz::time_point when, cctz::TimeZone zone) {
  std::cout << "kind: UNIQUE\n";
  InstantInfo("when", when, zone);
  return 0;
}

const char* Basename(const char* p) {
  if (const char* b = strrchr(p, '/')) return ++b;
  return p;
}

// std::regex doesn't work before gcc 4.9.
bool LooksLikeNegOffset(const char* s) {
  if (s[0] == '-' && std::isdigit(s[1]) && std::isdigit(s[2])) {
    int i = (s[3] == ':') ? 4 : 3;
    if (std::isdigit(s[i]) && std::isdigit(s[i + 1])) {
      return s[i + 2] == '\0';
    }
  }
  return false;
}

int main(int argc, char** argv) {
  std::string prog = argv[0] ? Basename(argv[0]) : "time_tool";

  // Escape arguments that look like negative offsets so that they
  // don't look like flags.
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--") == 0) break;
    if (LooksLikeNegOffset(argv[i])) {
      char* buf = new char[strlen(argv[i] + 2)];
      buf[0] = ' ';  // will later be ignorned
      strcpy(buf + 1, argv[i]);
      argv[i] = buf;
    }
  }

  // Determine the time zone.
  cctz::TimeZone zone = cctz::LocalTimeZone();
  for (;;) {
    static option opts[] = {
        {"zone", required_argument, nullptr, 'z'},
        {nullptr, 0, nullptr, 0},
    };
    int c = getopt_long(argc, argv, "z:", opts, nullptr);
    if (c == -1) break;
    switch (c) {
      case 'z':
        if (!cctz::LoadTimeZone(optarg, &zone)) {
          std::cerr << optarg << ": Unrecognized time zone\n";
          return 1;
        }
        break;
      default:
        std::cerr << "Usage: " << prog << " [--zone=<zone>] [<time-spec>]\n";
        return 1;
    }
  }

  // Determine the time point.
  cctz::time_point tp = std::chrono::system_clock::now();
  std::string args;
  for (int i = optind; i < argc; ++i) {
    if (i != optind) args += " ";
    args += argv[i];
  }
  std::replace(args.begin(), args.end(), ',', ' ');
  std::replace(args.begin(), args.end(), '/', '-');
  bool have_time = ParseTimeSpec(args, zone, &tp);
  if (!have_time && !args.empty()) {
    std::string spec = args.substr((args[0] == '@') ? 1 : 0);
    if ((spec.size() > 0 && std::isdigit(spec[0])) ||
        (spec.size() > 1 && spec[0] == '-' && std::isdigit(spec[1]))) {
      std::size_t end;
      const time_t t = std::stoll(spec, &end);
      if (end == spec.size()) {
        tp = std::chrono::system_clock::from_time_t(t);
        have_time = true;
      }
    }
  }
  cctz::Breakdown when = cctz::BreakTime(tp, zone);
  bool have_break_down = !have_time && ParseBreakdownSpec(args, zone, &when);

  // Show results.
  if (have_break_down) return BreakdownInfo(when, zone);
  if (have_time || args.empty()) return TimeInfo(tp, zone);

  std::cerr << args << ": Malformed time spec\n";
  return 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * 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 <cassert>
#include <cmath>
#include <limits>

#include "support/safe_integer.h"

using namespace wasm;

bool wasm::isInteger(double x) { return fmod(x, 1) == 0; }

bool wasm::isUInteger32(double x) {
  return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint32_t>::max();
}

bool wasm::isSInteger32(double x) {
  return isInteger(x) && x >= std::numeric_limits<int32_t>::min() &&
         x <= std::numeric_limits<int32_t>::max();
}

uint32_t wasm::toUInteger32(double x) {
  assert(isUInteger32(x));
  return x < std::numeric_limits<uint32_t>::max()
             ? (uint32_t)x
             : std::numeric_limits<uint32_t>::max();
}

int32_t wasm::toSInteger32(double x) {
  assert(isSInteger32(x));
  return x > std::numeric_limits<int32_t>::min() &&
                 x < std::numeric_limits<int32_t>::max()
             ? x
             : (x < 0 ? std::numeric_limits<int32_t>::min()
                      : std::numeric_limits<int32_t>::max());
}

bool wasm::isUInteger64(double x) {
  return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint64_t>::max();
}

bool wasm::isSInteger64(double x) {
  return isInteger(x) && x >= std::numeric_limits<int64_t>::min() &&
         x <= std::numeric_limits<int64_t>::max();
}

uint64_t wasm::toUInteger64(double x) {
  assert(isUInteger64(x));
  return x < (double)std::numeric_limits<uint64_t>::max()
             ? (uint64_t)x
             : std::numeric_limits<uint64_t>::max();
}

int64_t wasm::toSInteger64(double x) {
  assert(isSInteger64(x));
  return x > (double)std::numeric_limits<int64_t>::min() &&
                 x < (double)std::numeric_limits<int64_t>::max()
             ? (int64_t)x
             : (x < 0 ? std::numeric_limits<int64_t>::min()
                      : std::numeric_limits<int64_t>::max());
}
<commit_msg>Also clean up Visual Studio build warning in wasm::toSInteger32 for double->int32_t cast.<commit_after>/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * 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 <cassert>
#include <cmath>
#include <limits>

#include "support/safe_integer.h"

using namespace wasm;

bool wasm::isInteger(double x) { return fmod(x, 1) == 0; }

bool wasm::isUInteger32(double x) {
  return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint32_t>::max();
}

bool wasm::isSInteger32(double x) {
  return isInteger(x) && x >= std::numeric_limits<int32_t>::min() &&
         x <= std::numeric_limits<int32_t>::max();
}

uint32_t wasm::toUInteger32(double x) {
  assert(isUInteger32(x));
  return x < std::numeric_limits<uint32_t>::max()
             ? (uint32_t)x
             : std::numeric_limits<uint32_t>::max();
}

int32_t wasm::toSInteger32(double x) {
  assert(isSInteger32(x));
  return x > std::numeric_limits<int32_t>::min() &&
                 x < std::numeric_limits<int32_t>::max()
             ? (int32_t)x
             : (x < 0 ? std::numeric_limits<int32_t>::min()
                      : std::numeric_limits<int32_t>::max());
}

bool wasm::isUInteger64(double x) {
  return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint64_t>::max();
}

bool wasm::isSInteger64(double x) {
  return isInteger(x) && x >= std::numeric_limits<int64_t>::min() &&
         x <= std::numeric_limits<int64_t>::max();
}

uint64_t wasm::toUInteger64(double x) {
  assert(isUInteger64(x));
  return x < (double)std::numeric_limits<uint64_t>::max()
             ? (uint64_t)x
             : std::numeric_limits<uint64_t>::max();
}

int64_t wasm::toSInteger64(double x) {
  assert(isSInteger64(x));
  return x > (double)std::numeric_limits<int64_t>::min() &&
                 x < (double)std::numeric_limits<int64_t>::max()
             ? (int64_t)x
             : (x < 0 ? std::numeric_limits<int64_t>::min()
                      : std::numeric_limits<int64_t>::max());
}
<|endoftext|>


<commit_before>#include "ModLED.h"
//TODO this is a dummy mod, remove this once the build system is up
CModLED::CModLED(void)
{
  // nothing
}

void CModLED::Begin(void)
{
  CModTemplate::Begin();
  ModGUID = 10; // GUID of this specific mod

  if (Global.HasUSB)
  {

  }
  InitiateLED();
}

void CModLED::InitiateLED(void) // this should only be called once per boot up
{
  ledPin = GetData(LED_PIN_MEM);
  if (ledPin != 255) // if LED pin is initiated
  {
    LEDCount = GetData(LED_COUNT_MEM);
    FastLED.addLeds<NEOPIXEL, LED_PIN>(LEDs, LEDCount);
    RefreshLED();
  }
}

void CModLED::RefreshLED(void)
{
  for (short i = 0; i < LEDCount; i++)
  {
    LEDs[i] = CHSV (GetData(2 + i * 2), GetData(2 + i * 2 + 1), Global.LEDBrightness);
  }
  FastLED.show();
}

void CModLED::LoadData(void)
{
  CModTemplate::LoadData();

  if (Global.HasUSB)
  {

  }
  RefreshLED();
}

void CModLED::Loop(void)
{
  CModTemplate::Loop();
  if (Animus.AsyncRefreshDelay())
  {
  }
}

void CModLED::PressCoords(byte x, byte y)
{
  CModTemplate::PressCoords(x, y);

}

void CModLED::PrePress(byte val, byte type)
{
  CModTemplate::PrePress(val, type);
  if (Global.HasUSB)
  {

  }
}
void CModLED::PressKey(byte val, byte type)
{
  CModTemplate::PressKey(val, type);
  if (type == 38) // LED brightness adjust
  {
    short adjust = val - 127;
    if (Global.LEDBrightness + adjust < 0)
    {
      Global.LEDBrightness = 0;
    }
    else if (Global.LEDBrightness + adjust > LED_MAX_BRIGHTNESS)
    {
      Global.LEDBrightness = LED_MAX_BRIGHTNESS;
    }
    else
    {
      Global.LEDBrightness = Global.LEDBrightness + adjust;
    }
    RefreshLED;
  }

}
void CModLED::ReleaseKey(byte val, byte type)
{
  CModTemplate::ReleaseKey(val, type);

}

void CModLED::SerialComms(byte mode)
{
  CModTemplate::SerialComms(mode);
}

CModLED ModLED;
<commit_msg>add: led changes<commit_after>#include "ModLED.h"
//TODO this is a dummy mod, remove this once the build system is up
CModLED::CModLED(void)
{
  // nothing
}

void CModLED::Begin(void)
{
  CModTemplate::Begin();
  ModGUID = 10; // GUID of this specific mod

  if (Global.HasUSB)
  {

  }
  InitiateLED();
}

void CModLED::InitiateLED(void) // this should only be called once per boot up
{
  uint8_t ledPin = GetData(LED_PIN_MEM);
  if (ledPin == 255) // this be janky due to hardware problems
  {
    LEDCount = GetData(LED_COUNT_MEM);
    FastLED.addLeds<NEOPIXEL, 11>(LEDs, LEDCount);
    RefreshLED();
  }
  else
  {
    LEDCount = GetData(LED_COUNT_MEM);
    FastLED.addLeds<NEOPIXEL, 26>(LEDs, LEDCount);
    RefreshLED();
  }
}

void CModLED::RefreshLED(void)
{
  for (short i = 0; i < LEDCount; i++)
  {
    LEDs[i] = CHSV (GetData(2 + i * 2), GetData(2 + i * 2 + 1), Global.LEDBrightness);
  }
  FastLED.show();
}

void CModLED::LoadData(void)
{
  CModTemplate::LoadData();

  if (Global.HasUSB)
  {

  }
  RefreshLED();
}

void CModLED::Loop(void)
{
  CModTemplate::Loop();
  if (Animus.AsyncRefreshDelay())
  {
  }
}

void CModLED::PressCoords(byte x, byte y)
{
  CModTemplate::PressCoords(x, y);

}

void CModLED::PrePress(byte val, byte type)
{
  CModTemplate::PrePress(val, type);
  if (Global.HasUSB)
  {

  }
}
void CModLED::PressKey(byte val, byte type)
{
  CModTemplate::PressKey(val, type);
  if (type == 38) // LED brightness adjust
  {
    short adjust = val - 127;
    if (Global.LEDBrightness + adjust < 0)
    {
      Global.LEDBrightness = 0;
    }
    else if (Global.LEDBrightness + adjust > LED_MAX_BRIGHTNESS)
    {
      Global.LEDBrightness = LED_MAX_BRIGHTNESS;
    }
    else
    {
      Global.LEDBrightness = Global.LEDBrightness + adjust;
    }
    RefreshLED();
  }

}
void CModLED::ReleaseKey(byte val, byte type)
{
  CModTemplate::ReleaseKey(val, type);

}

void CModLED::SerialComms(byte mode)
{
  CModTemplate::SerialComms(mode);
}

CModLED ModLED;
<|endoftext|>


<commit_before>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "lock.h"
#include "system/Error.hxx"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <inline/list.h>
#include <daemon/log.h>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct page {
    struct list_head siblings;

    unsigned num_pages;
    uint8_t *data;
};

struct shm {
    RefCount ref;

    size_t page_size;
    unsigned num_pages;

    /** this lock protects the linked list */
    struct lock lock;

    struct list_head available;
    struct page pages[1];
};

static inline unsigned
calc_header_pages(size_t page_size, unsigned num_pages)
{
    size_t header_size = sizeof(struct shm) +
        (num_pages - 1) * sizeof(struct page);
    return (header_size + page_size - 1) / page_size;
}

gcc_const
static uint8_t *
shm_at(struct shm *shm, size_t offset)
{
    return (uint8_t *)shm + offset;
}

static uint8_t *
shm_data(struct shm *shm)
{
    unsigned header_pages = calc_header_pages(shm->page_size, shm->num_pages);

    return shm_at(shm, shm->page_size * header_pages);
}

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = calc_header_pages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        throw MakeErrno("mmap() failed");

    struct shm *shm = (struct shm *)p;
    shm->ref.Init();
    shm->page_size = page_size;
    shm->num_pages = num_pages;

    lock_init(&shm->lock);

    list_init(&shm->available);
    list_add(&shm->pages[0].siblings, &shm->available);
    shm->pages[0].num_pages = num_pages;
    shm->pages[0].data = shm_data(shm);

    return shm;
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        lock_destroy(&shm->lock);

    header_pages = calc_header_pages(shm->page_size, shm->num_pages);
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

static struct page *
shm_find_available(struct shm *shm, unsigned num_pages)
{
    for (struct page *page = (struct page *)shm->available.next;
         &page->siblings != &shm->available;
         page = (struct page *)page->siblings.next)
        if (page->num_pages >= num_pages)
            return page;

    return nullptr;
}

static struct page *
shm_split_page(const struct shm *shm, struct page *page, unsigned num_pages)
{
    assert(page->num_pages > num_pages);

    page->num_pages -= num_pages;

    page[page->num_pages].data = page->data + shm->page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = num_pages;

    return page;
}

void *
shm_alloc(struct shm *shm, unsigned num_pages)
{
    assert(num_pages > 0);

    lock_lock(&shm->lock);

    struct page *page = shm_find_available(shm, num_pages);
    if (page == nullptr) {
        lock_unlock(&shm->lock);
        return nullptr;
    }

    assert(page->num_pages >= num_pages);

    page = (struct page *)shm->available.next;
    if (page->num_pages == num_pages) {
        list_remove(&page->siblings);
        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    } else {
        page = shm_split_page(shm, page, num_pages);

        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    }
}

static unsigned
shm_page_number(struct shm *shm, const void *p)
{
    ptrdiff_t difference = (const uint8_t *)p - shm_data(shm);
    unsigned page_number = difference / shm->page_size;
    assert(difference % shm->page_size == 0);

    assert(page_number < shm->num_pages);

    return page_number;
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
static void
shm_merge(struct shm *shm, struct page *page)
{
    unsigned page_number = shm_page_number(shm, page->data);

    /* merge with previous page? */

    struct page *other = (struct page *)page->siblings.prev;
    if (&other->siblings != &shm->available &&
        shm_page_number(shm, other->data) + other->num_pages == page_number) {
        other->num_pages += page->num_pages;
        list_remove(&page->siblings);
        page = other;
    }

    /* merge with next page? */

    other = (struct page *)page->siblings.next;
    if (&other->siblings != &shm->available &&
        page_number + page->num_pages == shm_page_number(shm, other->data)) {
        page->num_pages += other->num_pages;
        list_remove(&other->siblings);
    }
}

void
shm_free(struct shm *shm, const void *p)
{
    unsigned page_number = shm_page_number(shm, p);
    struct page *page = &shm->pages[page_number];
    struct page *prev;

    poison_noaccess(page->data, shm->page_size * page->num_pages);

    lock_lock(&shm->lock);

    for (prev = (struct page *)&shm->available;
         prev->siblings.next != &shm->available;
         prev = (struct page *)prev->siblings.next) {
    }

    list_add(&page->siblings, &prev->siblings);

    shm_merge(shm, page);

    lock_unlock(&shm->lock);
}
<commit_msg>shm/shm: move functions into the struct<commit_after>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "lock.h"
#include "system/Error.hxx"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <inline/list.h>
#include <daemon/log.h>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct page {
    struct list_head siblings;

    unsigned num_pages;
    uint8_t *data;
};

struct shm {
    RefCount ref;

    size_t page_size;
    unsigned num_pages;

    /** this lock protects the linked list */
    struct lock lock;

    struct list_head available;
    struct page pages[1];

    static unsigned CalcHeaderPages(size_t page_size, unsigned num_pages) {
        size_t header_size = sizeof(struct shm) +
            (num_pages - 1) * sizeof(struct page);
        return (header_size + page_size - 1) / page_size;
    }

    unsigned CalcHeaderPages() const {
        return CalcHeaderPages(page_size, num_pages);
    }

    uint8_t *At(size_t offset) {
        return (uint8_t *)this + offset;
    }

    uint8_t *GetData() {
        return At(page_size * CalcHeaderPages());
    }
};

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = shm::CalcHeaderPages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        throw MakeErrno("mmap() failed");

    struct shm *shm = (struct shm *)p;
    shm->ref.Init();
    shm->page_size = page_size;
    shm->num_pages = num_pages;

    lock_init(&shm->lock);

    list_init(&shm->available);
    list_add(&shm->pages[0].siblings, &shm->available);
    shm->pages[0].num_pages = num_pages;
    shm->pages[0].data = shm->GetData();

    return shm;
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        lock_destroy(&shm->lock);

    header_pages = shm->CalcHeaderPages();
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

static struct page *
shm_find_available(struct shm *shm, unsigned num_pages)
{
    for (struct page *page = (struct page *)shm->available.next;
         &page->siblings != &shm->available;
         page = (struct page *)page->siblings.next)
        if (page->num_pages >= num_pages)
            return page;

    return nullptr;
}

static struct page *
shm_split_page(const struct shm *shm, struct page *page, unsigned num_pages)
{
    assert(page->num_pages > num_pages);

    page->num_pages -= num_pages;

    page[page->num_pages].data = page->data + shm->page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = num_pages;

    return page;
}

void *
shm_alloc(struct shm *shm, unsigned num_pages)
{
    assert(num_pages > 0);

    lock_lock(&shm->lock);

    struct page *page = shm_find_available(shm, num_pages);
    if (page == nullptr) {
        lock_unlock(&shm->lock);
        return nullptr;
    }

    assert(page->num_pages >= num_pages);

    page = (struct page *)shm->available.next;
    if (page->num_pages == num_pages) {
        list_remove(&page->siblings);
        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    } else {
        page = shm_split_page(shm, page, num_pages);

        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    }
}

static unsigned
shm_page_number(struct shm *shm, const void *p)
{
    ptrdiff_t difference = (const uint8_t *)p - shm->GetData();
    unsigned page_number = difference / shm->page_size;
    assert(difference % shm->page_size == 0);

    assert(page_number < shm->num_pages);

    return page_number;
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
static void
shm_merge(struct shm *shm, struct page *page)
{
    unsigned page_number = shm_page_number(shm, page->data);

    /* merge with previous page? */

    struct page *other = (struct page *)page->siblings.prev;
    if (&other->siblings != &shm->available &&
        shm_page_number(shm, other->data) + other->num_pages == page_number) {
        other->num_pages += page->num_pages;
        list_remove(&page->siblings);
        page = other;
    }

    /* merge with next page? */

    other = (struct page *)page->siblings.next;
    if (&other->siblings != &shm->available &&
        page_number + page->num_pages == shm_page_number(shm, other->data)) {
        page->num_pages += other->num_pages;
        list_remove(&other->siblings);
    }
}

void
shm_free(struct shm *shm, const void *p)
{
    unsigned page_number = shm_page_number(shm, p);
    struct page *page = &shm->pages[page_number];
    struct page *prev;

    poison_noaccess(page->data, shm->page_size * page->num_pages);

    lock_lock(&shm->lock);

    for (prev = (struct page *)&shm->available;
         prev->siblings.next != &shm->available;
         prev = (struct page *)prev->siblings.next) {
    }

    list_add(&page->siblings, &prev->siblings);

    shm_merge(shm, page);

    lock_unlock(&shm->lock);
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/ToString.h"

#include <catch2/catch.hpp>

using namespace seasocks;

TEST_CASE("withIntegralTypes", "[toStringTests]") {
    CHECK(toString(static_cast<short>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned short>(1234)) == "1234");

    CHECK(toString(static_cast<int>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned int>(1234)) == "1234");

    CHECK(toString(static_cast<long>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned long>(1234)) == "1234");

    CHECK(toString(static_cast<long long>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned long long>(1234)) == "1234");
}

TEST_CASE("withFloatTypes", "[toStringTests]") {
    CHECK(toString(123.4) == "123.4");
    CHECK(toString(123.4f) == "123.4");
}

TEST_CASE("withCharType" "[toStringTests]") {
    CHECK(toString('c') == "c");
}
<commit_msg>Typo in the test case fixed.<commit_after>// Copyright (c) 2013-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/ToString.h"

#include <catch2/catch.hpp>

using namespace seasocks;

TEST_CASE("withIntegralTypes", "[toStringTests]") {
    CHECK(toString(static_cast<short>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned short>(1234)) == "1234");

    CHECK(toString(static_cast<int>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned int>(1234)) == "1234");

    CHECK(toString(static_cast<long>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned long>(1234)) == "1234");

    CHECK(toString(static_cast<long long>(1234)) == "1234");
    CHECK(toString(static_cast<unsigned long long>(1234)) == "1234");
}

TEST_CASE("withFloatTypes", "[toStringTests]") {
    CHECK(toString(123.4) == "123.4");
    CHECK(toString(123.4f) == "123.4");
}

TEST_CASE("withCharType", "[toStringTests]") {
    CHECK(toString('c') == "c");
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>
#include <hash.h>
#include <key.h>
#include <script/miniscript.h>
#include <script/script.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/strencodings.h>

namespace {

//! Context that implements naive conversion from/to script only, for roundtrip testing.
struct ScriptParserContext {
    //! For Script roundtrip we never need the key from a key hash.
    struct Key {
        bool is_hash;
        std::vector<unsigned char> data;
    };

    const std::vector<unsigned char>& ToPKBytes(const Key& key) const
    {
        assert(!key.is_hash);
        return key.data;
    }

    const std::vector<unsigned char> ToPKHBytes(const Key& key) const
    {
        if (key.is_hash) return key.data;
        const auto h = Hash160(key.data);
        return {h.begin(), h.end()};
    }

    template<typename I>
    std::optional<Key> FromPKBytes(I first, I last) const
    {
        Key key;
        key.data.assign(first, last);
        key.is_hash = false;
        return key;
    }

    template<typename I>
    std::optional<Key> FromPKHBytes(I first, I last) const
    {
        Key key;
        key.data.assign(first, last);
        key.is_hash = true;
        return key;
    }
} SCRIPT_PARSER_CONTEXT;

}

/* Fuzz tests that test parsing from a script, and roundtripping via script. */
FUZZ_TARGET(miniscript_script)
{
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
    if (!script) return;

    const auto ms = miniscript::FromScript(*script, SCRIPT_PARSER_CONTEXT);
    if (!ms) return;

    assert(ms->ToScript(SCRIPT_PARSER_CONTEXT) == *script);
}
<commit_msg>fuzz: add a Miniscript target for string representation roundtripping<commit_after>// Copyright (c) 2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>
#include <hash.h>
#include <key.h>
#include <script/miniscript.h>
#include <script/script.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/strencodings.h>

namespace {

//! Some pre-computed data for more efficient string roundtrips.
struct TestData {
    typedef CPubKey Key;

    // Precomputed public keys.
    std::vector<Key> dummy_keys;
    std::map<Key, int> dummy_key_idx_map;
    std::map<CKeyID, Key> dummy_keys_map;

    //! Set the precomputed data.
    void Init() {
        unsigned char keydata[32] = {1};
        for (size_t i = 0; i < 256; i++) {
            keydata[31] = i;
            CKey privkey;
            privkey.Set(keydata, keydata + 32, true);
            const Key pubkey = privkey.GetPubKey();

            dummy_keys.push_back(pubkey);
            dummy_key_idx_map.emplace(pubkey, i);
            dummy_keys_map.insert({pubkey.GetID(), pubkey});
        }
    }
} TEST_DATA;

/**
 * Context to parse a Miniscript node to and from Script or text representation.
 * Uses an integer (an index in the dummy keys array from the test data) as keys in order
 * to focus on fuzzing the Miniscript nodes' test representation, not the key representation.
 */
struct ParserContext {
    typedef CPubKey Key;

    std::optional<std::string> ToString(const Key& key) const
    {
        auto it = TEST_DATA.dummy_key_idx_map.find(key);
        if (it == TEST_DATA.dummy_key_idx_map.end()) return {};
        uint8_t idx = it->second;
        return HexStr(Span{&idx, 1});
    }

    template<typename I>
    std::optional<Key> FromString(I first, I last) const {
        if (last - first != 2) return {};
        auto idx = ParseHex(std::string(first, last));
        if (idx.size() != 1) return {};
        return TEST_DATA.dummy_keys[idx[0]];
    }

    template<typename I>
    std::optional<Key> FromPKBytes(I first, I last) const {
        Key key;
        key.Set(first, last);
        if (!key.IsValid()) return {};
        return key;
    }

    template<typename I>
    std::optional<Key> FromPKHBytes(I first, I last) const {
        assert(last - first == 20);
        CKeyID keyid;
        std::copy(first, last, keyid.begin());
        const auto it = TEST_DATA.dummy_keys_map.find(keyid);
        if (it == TEST_DATA.dummy_keys_map.end()) return {};
        return it->second;
    }
} PARSER_CTX;

//! Context that implements naive conversion from/to script only, for roundtrip testing.
struct ScriptParserContext {
    //! For Script roundtrip we never need the key from a key hash.
    struct Key {
        bool is_hash;
        std::vector<unsigned char> data;
    };

    const std::vector<unsigned char>& ToPKBytes(const Key& key) const
    {
        assert(!key.is_hash);
        return key.data;
    }

    const std::vector<unsigned char> ToPKHBytes(const Key& key) const
    {
        if (key.is_hash) return key.data;
        const auto h = Hash160(key.data);
        return {h.begin(), h.end()};
    }

    template<typename I>
    std::optional<Key> FromPKBytes(I first, I last) const
    {
        Key key;
        key.data.assign(first, last);
        key.is_hash = false;
        return key;
    }

    template<typename I>
    std::optional<Key> FromPKHBytes(I first, I last) const
    {
        Key key;
        key.data.assign(first, last);
        key.is_hash = true;
        return key;
    }
} SCRIPT_PARSER_CONTEXT;

} // namespace

void FuzzInit()
{
    ECC_Start();
    TEST_DATA.Init();
}

/* Fuzz tests that test parsing from a string, and roundtripping via string. */
FUZZ_TARGET_INIT(miniscript_string, FuzzInit)
{
    FuzzedDataProvider provider(buffer.data(), buffer.size());
    auto str = provider.ConsumeRemainingBytesAsString();
    auto parsed = miniscript::FromString(str, PARSER_CTX);
    if (!parsed) return;

    const auto str2 = parsed->ToString(PARSER_CTX);
    assert(str2);
    auto parsed2 = miniscript::FromString(*str2, PARSER_CTX);
    assert(parsed2);
    assert(*parsed == *parsed2);
}

/* Fuzz tests that test parsing from a script, and roundtripping via script. */
FUZZ_TARGET(miniscript_script)
{
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
    if (!script) return;

    const auto ms = miniscript::FromScript(*script, SCRIPT_PARSER_CONTEXT);
    if (!ms) return;

    assert(ms->ToScript(SCRIPT_PARSER_CONTEXT) == *script);
}
<|endoftext|>


<commit_before>/*
 * benchmarks/benchmark-dense-solve.C
 *
 * Copyright (C) 2019 The LinBox group
 * Author: J-G Dumas
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox 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
 * ========LICENCE========
 */

/**\file benchmarks/benchmark-dense-solve.C
\brief Solving dense linear system over Q or Zp.
\ingroup benchmarks
*/

#include "linbox/linbox-config.h"
#include <iostream>

#include <givaro/modular.h>
#include "linbox/util/args-parser.h"
#include "linbox/matrix/sparse-matrix.h"
#include "linbox/solutions/solve.h"
#include "linbox/util/matrix-stream.h"
#include "linbox/solutions/methods.h"

#ifdef _DEBUG
#define _BENCHMARKS_DEBUG_
#endif

using namespace LinBox;
typedef Givaro::ZRing<Givaro::Integer> Ints;

int main (int argc, char **argv)
{
    Givaro::Integer q = -1 ;
    size_t n = 500 ;
    size_t bits = 10;
//     size_t p = 0;

    Argument as[] = {
        { 'q', "-q Q", "Set the field characteristic (-1 for rationals).", TYPE_INTEGER , &q },
        { 'n', "-n N", "Set the matrix dimension.",      TYPE_INT , &n },
        { 'b', "-b B", "bit size", TYPE_INT , &bits },
//         { 'p', "-p P", "0 for sequential, 1 for 2D iterative, 2 for 2D rec, 3 for 2D rec adaptive, 4 for 3D rec in-place, 5 for 3D rec, 6 for 3D rec adaptive.", TYPE_INT , &p },
        END_OF_ARGUMENTS
    };

    LinBox::parseArguments(argc,argv,as);

    bool ModComp = false;
    if (q > 0) ModComp = true;

    Timer chrono;

    if (ModComp) {

        typedef Givaro::Modular<double> Field;
        Field F(q);
	Field::RandIter G(F);

#ifdef _BENCHMARKS_DEBUG_
	std::clog << "Setting A ... " << std::endl;
#endif
        chrono.start();
        DenseMatrix<Field> A(F,n,n);
	PAR_BLOCK { FFLAS::pfrand(F,G, n,n,A.getPointer(),n); }
        chrono.stop();
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "... A is " << A.rowdim() << " by " << A.coldim() << ", " << chrono << std::endl;
	if (A.rowdim() <= 20 && A.coldim() <= 20) A.write(std::clog <<"A:=",Tag::FileFormat::Maple) << ';' << std::endl;
#endif
        DenseVector<Field> X(F, A.coldim()),B(F, A.rowdim());
	for(auto it=B.begin(); it != B.end(); ++it)
		if (drand48() <0.5)
			F.assign(*it,F.mOne);
                else
			F.assign(*it,F.one);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "B is [";
	for(const auto& it: B)
            F.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif

            // DenseElimination
        chrono.start();
        PAR_BLOCK { solve (X, A, B, Method::DenseElimination()); }
        chrono.stop();

#ifdef _BENCHMARKS_DEBUG_
        std::clog << "(DenseElimination) Solution is [";
        for(const auto& it: X)
            F.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif
        std::cout << "Time: " << chrono.usertime()
		  << " Bitsize: " << Givaro::logtwo(GIVMAX(X.front(), 1));
	FFLAS::writeCommandString(std::cout, as) << std::endl;
    } else {

        typedef Ints Integers;
        Integers ZZ;
	Integers::RandIter G(ZZ,bits);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "Reading A ... " << std::endl;
        chrono.start();
#endif
        DenseMatrix<Integers> A(ZZ, n, n);
	PAR_BLOCK { FFLAS::pfrand(ZZ,G, n,n,A.getPointer(),n); }
#ifdef _BENCHMARKS_DEBUG_
	chrono.stop();
        std::clog << "... A is " << A.rowdim() << " by " << A.coldim() << ", " << chrono << std::endl;
	if (A.rowdim() <= 20 && A.coldim() <= 20) A.write(std::clog <<"A:=",Tag::FileFormat::Maple) << ';' << std::endl;
#endif
        Givaro::IntegerDom::Element d;

        DenseVector<Integers> X(ZZ, A.coldim()),B(ZZ, A.rowdim());

	for(auto it=B.begin(); it != B.end(); ++it)
		if (drand48() <0.5)
			ZZ.assign(*it,ZZ.mOne);
                else
			ZZ.assign(*it,ZZ.one);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "B is [";
	for(const auto& it: B)
            ZZ.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif

            // DenseElimination
        chrono.start();
        solve (X, d, A, B, RingCategories::IntegerTag(), Method::DenseElimination());
        chrono.stop();

#ifdef _BENCHMARKS_DEBUG_
        std::clog << "(DenseElimination) Solution is [";
        for(const auto& it: X) ZZ.write(std::clog, it) << ' ';
        ZZ.write(std::clog << "] / ", d)<< std::endl;
#endif

        std::cout << "Time: " << chrono.usertime()
		  << " Bitsize: " << Givaro::logtwo(d);
	FFLAS::writeCommandString(std::cout, as) << std::endl;
    }

    return 0;
}
<commit_msg>no par yet<commit_after>/*
 * benchmarks/benchmark-dense-solve.C
 *
 * Copyright (C) 2019 The LinBox group
 * Author: J-G Dumas
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox 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
 * ========LICENCE========
 */

/**\file benchmarks/benchmark-dense-solve.C
\brief Solving dense linear system over Q or Zp.
\ingroup benchmarks
*/

#include "linbox/linbox-config.h"
#include <iostream>

#include <givaro/modular.h>
#include "linbox/util/args-parser.h"
#include "linbox/matrix/sparse-matrix.h"
#include "linbox/solutions/solve.h"
#include "linbox/util/matrix-stream.h"
#include "linbox/solutions/methods.h"

#ifdef _DEBUG
#define _BENCHMARKS_DEBUG_
#endif

using namespace LinBox;
typedef Givaro::ZRing<Givaro::Integer> Ints;

int main (int argc, char **argv)
{
    Givaro::Integer q = -1 ;
    size_t n = 500 ;
    size_t bits = 10;
//     size_t p = 0;

    Argument as[] = {
        { 'q', "-q Q", "Set the field characteristic (-1 for rationals).", TYPE_INTEGER , &q },
        { 'n', "-n N", "Set the matrix dimension.",      TYPE_INT , &n },
        { 'b', "-b B", "bit size", TYPE_INT , &bits },
//         { 'p', "-p P", "0 for sequential, 1 for 2D iterative, 2 for 2D rec, 3 for 2D rec adaptive, 4 for 3D rec in-place, 5 for 3D rec, 6 for 3D rec adaptive.", TYPE_INT , &p },
        END_OF_ARGUMENTS
    };

    LinBox::parseArguments(argc,argv,as);

    bool ModComp = false;
    if (q > 0) ModComp = true;

    Timer chrono;

    if (ModComp) {

        typedef Givaro::Modular<double> Field;
        Field F(q);
	Field::RandIter G(F);

#ifdef _BENCHMARKS_DEBUG_
	std::clog << "Setting A ... " << std::endl;
#endif
        chrono.start();
        DenseMatrix<Field> A(F,n,n);
	PAR_BLOCK { FFLAS::pfrand(F,G, n,n,A.getPointer(),n); }
        chrono.stop();
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "... A is " << A.rowdim() << " by " << A.coldim() << ", " << chrono << std::endl;
	if (A.rowdim() <= 20 && A.coldim() <= 20) A.write(std::clog <<"A:=",Tag::FileFormat::Maple) << ';' << std::endl;
#endif
        DenseVector<Field> X(F, A.coldim()),B(F, A.rowdim());
	for(auto it=B.begin(); it != B.end(); ++it)
		if (drand48() <0.5)
			F.assign(*it,F.mOne);
                else
			F.assign(*it,F.one);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "B is [";
	for(const auto& it: B)
            F.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif

            // DenseElimination
        chrono.start();
        solve (X, A, B, Method::DenseElimination());
        chrono.stop();

#ifdef _BENCHMARKS_DEBUG_
        std::clog << "(DenseElimination) Solution is [";
        for(const auto& it: X)
            F.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif
        std::cout << "Time: " << chrono.usertime()
		  << " Bitsize: " << Givaro::logtwo(GIVMAX(X.front(), 1));
	FFLAS::writeCommandString(std::cout, as) << std::endl;
    } else {

        typedef Ints Integers;
        Integers ZZ;
	Integers::RandIter G(ZZ,bits);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "Reading A ... " << std::endl;
        chrono.start();
#endif
        DenseMatrix<Integers> A(ZZ, n, n);
	PAR_BLOCK { FFLAS::pfrand(ZZ,G, n,n,A.getPointer(),n); }
#ifdef _BENCHMARKS_DEBUG_
	chrono.stop();
        std::clog << "... A is " << A.rowdim() << " by " << A.coldim() << ", " << chrono << std::endl;
	if (A.rowdim() <= 20 && A.coldim() <= 20) A.write(std::clog <<"A:=",Tag::FileFormat::Maple) << ';' << std::endl;
#endif
        Givaro::IntegerDom::Element d;

        DenseVector<Integers> X(ZZ, A.coldim()),B(ZZ, A.rowdim());

	for(auto it=B.begin(); it != B.end(); ++it)
		if (drand48() <0.5)
			ZZ.assign(*it,ZZ.mOne);
                else
			ZZ.assign(*it,ZZ.one);
#ifdef _BENCHMARKS_DEBUG_
        std::clog << "B is [";
	for(const auto& it: B)
            ZZ.write(std::clog, it) << ' ';
        std::clog << ']' << std::endl;
#endif

            // DenseElimination
        chrono.start();
        solve (X, d, A, B, RingCategories::IntegerTag(), Method::DenseElimination());
        chrono.stop();

#ifdef _BENCHMARKS_DEBUG_
        std::clog << "(DenseElimination) Solution is [";
        for(const auto& it: X) ZZ.write(std::clog, it) << ' ';
        ZZ.write(std::clog << "] / ", d)<< std::endl;
#endif

        std::cout << "Time: " << chrono.usertime()
		  << " Bitsize: " << Givaro::logtwo(d);
	FFLAS::writeCommandString(std::cout, as) << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_DEFAULT_TRAITS
#define MJOLNIR_DEFAULT_TRAITS
#include <mjolnir/math/Vector.hpp>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
struct SimulatorTraits
{
    using real_type       = realT;
    using coordinate_type = math::Vector<real_type, 3>;
    template<std::size_t N, std::size_t M>
    using matrix_type = math::Matrix<real_type, N, M>;

    using boundary_type = boundaryT<real_type, coordinate_type>;
};

} // mjolnir
#endif /* MJOLNIR_DEFAULT_TRAITS */
<commit_msg>refactor: restrict matrix_type to 3x3 or 4x4<commit_after>#ifndef MJOLNIR_DEFAULT_TRAITS
#define MJOLNIR_DEFAULT_TRAITS
#include <mjolnir/math/Vector.hpp>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
struct SimulatorTraits
{
    using real_type       = realT;
    using coordinate_type = math::Vector<real_type, 3>;

    using matrix33_type = math::Matrix<real_type, 3, 3>;
    using matrix44_type = math::Matrix<real_type, 4, 4>;

    using boundary_type = boundaryT<real_type, coordinate_type>;
};

} // mjolnir
#endif /* MJOLNIR_DEFAULT_TRAITS */
<|endoftext|>