<commit_before>/* $Id$ */

/*
 * Copyright (c) 2013 Roland van Rijswijk-Deij
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 AUTHOR ``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 AUTHOR 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.
 */

/*****************************************************************************
 silvia_keygen.cpp

 Issuer key generation utility
 *****************************************************************************/

#include "config.h"
#include "silvia_issuer_keygen.h"
#include "silvia_parameters.h"
#include "silvia_macros.h"
#include <string>
#include <unistd.h>

// Default modulus size for new keys
#define DEFAULT_BITSIZE 2048

void version(void)
{
	printf("The Simple Library for Verifying and Issuing Attributes (silvia)\n");
	printf("\n");
	printf("Issuer key generation utility version %s\n", VERSION);
	printf("\n");
	printf("Copyright (c) 2013 Roland van Rijswijk-Deij\n\n");
	printf("Use, modification and redistribution of this software is subject to the terms\n");
	printf("of the license agreement. This software is licensed under a 2-clause BSD-style\n");
	printf("license a copy of which is included as the file LICENSE in the distribution.\n");
}

void usage(void)
{
	printf("Silvia issuer key generation utility %s\n\n", VERSION);
	printf("Usage:\n");
	printf("\tsilvia_keygen -a <#-attribs> [-n <bits>] [-p <file>] [-P <file>]\n");
	printf("\tsilvia_keygen -h\n");
	printf("\tsilvia_keygen -v\n");
	printf("\n");
	printf("\t-a <#-attribs> Generate a key-pair supporting credentials with at most\n");
	printf("\t               <#-attribs> attributes per credentials\n");
	printf("\t-n <bits>      Generate a key-pair with a <bits>-bit modulus (defaults\n");
	printf("\t               to %d)\n", DEFAULT_BITSIZE);
	printf("\t-p <file>      Output the public key to <file> (defaults to stdout)\n");
	printf("\t-P <file>      Output the private key to <file> (defaults to stdout)\n");
	printf("\n");
	printf("\t-h             Print this help message\n");
	printf("\n");
	printf("\t-v             Print the version number\n");
}

int generate_key_pair(FILE* pub_key_file, FILE* priv_key_file, size_t num_attribs, size_t bit_size)
{
	printf("Generating %zd-bit issuer key pair for %zd attributes ... ", bit_size, num_attribs); fflush(stdout);

	// Set key size
	silvia_system_parameters::i()->set_l_n(bit_size);

	// Generate key-pair
	silvia_pub_key* pub_key;
	silvia_priv_key* priv_key;

	silvia_issuer_keyfactory::i()->generate_keypair(num_attribs, &pub_key, &priv_key);

	printf("OK\n");

	// Output the public key
	fprintf(pub_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(pub_key_file, "<IssuerPublicKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPublicKey.xsd\">\n");
	fprintf(pub_key_file, "  <References>\n");
    fprintf(pub_key_file, "    <GroupParameters>http://www.zurich.ibm.com/security/idmx/v2/gp.xml</GroupParameters>\n");
	fprintf(pub_key_file, "  </References>\n");
	fprintf(pub_key_file, "  <Elements>\n");
    fprintf(pub_key_file, "    <S>"); fprintmpzdec(pub_key_file, pub_key->get_S()); fprintf(pub_key_file, "</S>\n");
    fprintf(pub_key_file, "    <Z>"); fprintmpzdec(pub_key_file, pub_key->get_Z()); fprintf(pub_key_file, "</Z>\n");
    fprintf(pub_key_file, "    <n>"); fprintmpzdec(pub_key_file, pub_key->get_n()); fprintf(pub_key_file, "</n>\n");
    fprintf(pub_key_file, "    <Bases num=\"%zd\">\n", num_attribs);

    for (size_t i = 0; i < num_attribs; i++)
    {
		fprintf(pub_key_file, "      <Base_%zd>", i); fprintmpzdec(pub_key_file, pub_key->get_R()[i]); fprintf(pub_key_file, "</Base_%zd>\n", i);
	}

    fprintf(pub_key_file, "    </Bases>\n");
	fprintf(pub_key_file, "  </Elements>\n");
	fprintf(pub_key_file, "  <Features>\n");
    fprintf(pub_key_file, "    <Epoch length=\"432000\"/>\n");
	fprintf(pub_key_file, "  </Features>\n");
	fprintf(pub_key_file, "</IssuerPublicKey>\n");

	// Output the private key
	fprintf(priv_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(priv_key_file, "<IssuerPrivateKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPrivateKey.xsd\">\n");
	fprintf(priv_key_file, "  <References>\n");
    fprintf(priv_key_file, "    <IssuerPublicKey>http://www.issuer.com/ipk.xml</IssuerPublicKey>\n");
	fprintf(priv_key_file, "  </References>\n");
	fprintf(priv_key_file, "  <Elements>\n");
    fprintf(priv_key_file, "    <n>"); fprintmpzdec(priv_key_file, pub_key->get_n()); fprintf(priv_key_file, "</n>\n");
    fprintf(priv_key_file, "
"); fprintmpzdec(priv_key_file, priv_key->get_p()); fprintf(priv_key_file, "
\n");
    fprintf(priv_key_file, "    <pPrime>"); fprintmpzdec(priv_key_file, priv_key->get_p_prime()); fprintf(priv_key_file, "</pPrime>\n");
    fprintf(priv_key_file, "    <q>"); fprintmpzdec(priv_key_file, priv_key->get_q()); fprintf(priv_key_file, "</q>\n");
    fprintf(priv_key_file, "    <qPrime>"); fprintmpzdec(priv_key_file, priv_key->get_q_prime()); fprintf(priv_key_file, "</qPrime>\n");
	fprintf(priv_key_file, "  </Elements>\n");
	fprintf(priv_key_file, "</IssuerPrivateKey>\n");

	return 1;
}

int main(int argc, char* argv[])
{
	// Program parameters
	size_t bit_size = DEFAULT_BITSIZE;
	size_t num_attribs = 0;
	std::string pub_key_filename;
	std::string priv_key_filename;
	int c = 0;

	while ((c = getopt(argc, argv, "a:n:p:P:hv")) != -1)
	{
		switch (c)
		{
		case 'h':
			usage();
			return 0;
		case 'v':
			version();
			return 0;
		case 'a':
			num_attribs = atoi(optarg);
			break;
		case 'n':
			bit_size = atoi(optarg);
			break;
		case 'p':
			pub_key_filename = std::string(optarg);
			break;
		case 'P':
			priv_key_filename = std::string(optarg);
			break;
		}
	}

	if (num_attribs <= 0)
	{
		fprintf(stderr, "Missing argument -a; please specify a number of attributes\n");

		return -1;
	}

	FILE* pub_key_file = stdout;
	FILE* priv_key_file = stdout;

	if (!pub_key_filename.empty())
	{
		pub_key_file = fopen(pub_key_filename.c_str(), "w");

		if (pub_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", pub_key_filename.c_str());

			return -1;
		}

		printf("Writing public key to %s\n", pub_key_filename.c_str());
	}

	if (!priv_key_filename.empty())
	{
		priv_key_file = fopen(priv_key_filename.c_str(), "w");

		if (priv_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", priv_key_filename.c_str());

			return -1;
		}

		printf("Writing private key to %s\n", priv_key_filename.c_str());
	}

	generate_key_pair(pub_key_file, priv_key_file, num_attribs, bit_size);

	if (!pub_key_filename.empty()) fclose(pub_key_file);
	if (!priv_key_filename.empty()) fclose(priv_key_file);

	return 0;
}
<commit_msg>Corrected an off-by-one error, with n attributes n+1 bases are needed<commit_after>/* $Id$ */

/*
 * Copyright (c) 2013 Roland van Rijswijk-Deij
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 AUTHOR ``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 AUTHOR 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.
 */

/*****************************************************************************
 silvia_keygen.cpp

 Issuer key generation utility
 *****************************************************************************/

#include "config.h"
#include "silvia_issuer_keygen.h"
#include "silvia_parameters.h"
#include "silvia_macros.h"
#include <string>
#include <unistd.h>

// Default modulus size for new keys
#define DEFAULT_BITSIZE 2048

void version(void)
{
	printf("The Simple Library for Verifying and Issuing Attributes (silvia)\n");
	printf("\n");
	printf("Issuer key generation utility version %s\n", VERSION);
	printf("\n");
	printf("Copyright (c) 2013 Roland van Rijswijk-Deij\n\n");
	printf("Use, modification and redistribution of this software is subject to the terms\n");
	printf("of the license agreement. This software is licensed under a 2-clause BSD-style\n");
	printf("license a copy of which is included as the file LICENSE in the distribution.\n");
}

void usage(void)
{
	printf("Silvia issuer key generation utility %s\n\n", VERSION);
	printf("Usage:\n");
	printf("\tsilvia_keygen -a <#-attribs> [-n <bits>] [-p <file>] [-P <file>]\n");
	printf("\tsilvia_keygen -h\n");
	printf("\tsilvia_keygen -v\n");
	printf("\n");
	printf("\t-a <#-attribs> Generate a key-pair supporting credentials with at most\n");
	printf("\t               <#-attribs> attributes per credentials\n");
	printf("\t-n <bits>      Generate a key-pair with a <bits>-bit modulus (defaults\n");
	printf("\t               to %d)\n", DEFAULT_BITSIZE);
	printf("\t-p <file>      Output the public key to <file> (defaults to stdout)\n");
	printf("\t-P <file>      Output the private key to <file> (defaults to stdout)\n");
	printf("\n");
	printf("\t-h             Print this help message\n");
	printf("\n");
	printf("\t-v             Print the version number\n");
}

int generate_key_pair(FILE* pub_key_file, FILE* priv_key_file, size_t num_attribs, size_t bit_size)
{
	printf("Generating %zd-bit issuer key pair for %zd attributes ... ", bit_size, num_attribs); fflush(stdout);

	// Set key size
	silvia_system_parameters::i()->set_l_n(bit_size);

	// Generate key-pair
	silvia_pub_key* pub_key;
	silvia_priv_key* priv_key;

	silvia_issuer_keyfactory::i()->generate_keypair(num_attribs + 1, &pub_key, &priv_key);

	printf("OK\n");

	// Output the public key
	fprintf(pub_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(pub_key_file, "<IssuerPublicKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPublicKey.xsd\">\n");
	fprintf(pub_key_file, "  <References>\n");
    fprintf(pub_key_file, "    <GroupParameters>http://www.zurich.ibm.com/security/idmx/v2/gp.xml</GroupParameters>\n");
	fprintf(pub_key_file, "  </References>\n");
	fprintf(pub_key_file, "  <Elements>\n");
    fprintf(pub_key_file, "    <S>"); fprintmpzdec(pub_key_file, pub_key->get_S()); fprintf(pub_key_file, "</S>\n");
    fprintf(pub_key_file, "    <Z>"); fprintmpzdec(pub_key_file, pub_key->get_Z()); fprintf(pub_key_file, "</Z>\n");
    fprintf(pub_key_file, "    <n>"); fprintmpzdec(pub_key_file, pub_key->get_n()); fprintf(pub_key_file, "</n>\n");
    fprintf(pub_key_file, "    <Bases num=\"%zd\">\n", num_attribs);

    for (size_t i = 0; i < num_attribs; i++)
    {
		fprintf(pub_key_file, "      <Base_%zd>", i); fprintmpzdec(pub_key_file, pub_key->get_R()[i]); fprintf(pub_key_file, "</Base_%zd>\n", i);
	}

    fprintf(pub_key_file, "    </Bases>\n");
	fprintf(pub_key_file, "  </Elements>\n");
	fprintf(pub_key_file, "  <Features>\n");
    fprintf(pub_key_file, "    <Epoch length=\"432000\"/>\n");
	fprintf(pub_key_file, "  </Features>\n");
	fprintf(pub_key_file, "</IssuerPublicKey>\n");

	// Output the private key
	fprintf(priv_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(priv_key_file, "<IssuerPrivateKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPrivateKey.xsd\">\n");
	fprintf(priv_key_file, "  <References>\n");
    fprintf(priv_key_file, "    <IssuerPublicKey>http://www.issuer.com/ipk.xml</IssuerPublicKey>\n");
	fprintf(priv_key_file, "  </References>\n");
	fprintf(priv_key_file, "  <Elements>\n");
    fprintf(priv_key_file, "    <n>"); fprintmpzdec(priv_key_file, pub_key->get_n()); fprintf(priv_key_file, "</n>\n");
    fprintf(priv_key_file, "
"); fprintmpzdec(priv_key_file, priv_key->get_p()); fprintf(priv_key_file, "
\n");
    fprintf(priv_key_file, "    <pPrime>"); fprintmpzdec(priv_key_file, priv_key->get_p_prime()); fprintf(priv_key_file, "</pPrime>\n");
    fprintf(priv_key_file, "    <q>"); fprintmpzdec(priv_key_file, priv_key->get_q()); fprintf(priv_key_file, "</q>\n");
    fprintf(priv_key_file, "    <qPrime>"); fprintmpzdec(priv_key_file, priv_key->get_q_prime()); fprintf(priv_key_file, "</qPrime>\n");
	fprintf(priv_key_file, "  </Elements>\n");
	fprintf(priv_key_file, "</IssuerPrivateKey>\n");

	return 1;
}

int main(int argc, char* argv[])
{
	// Program parameters
	size_t bit_size = DEFAULT_BITSIZE;
	size_t num_attribs = 0;
	std::string pub_key_filename;
	std::string priv_key_filename;
	int c = 0;

	while ((c = getopt(argc, argv, "a:n:p:P:hv")) != -1)
	{
		switch (c)
		{
		case 'h':
			usage();
			return 0;
		case 'v':
			version();
			return 0;
		case 'a':
			num_attribs = atoi(optarg);
			break;
		case 'n':
			bit_size = atoi(optarg);
			break;
		case 'p':
			pub_key_filename = std::string(optarg);
			break;
		case 'P':
			priv_key_filename = std::string(optarg);
			break;
		}
	}

	if (num_attribs <= 0)
	{
		fprintf(stderr, "Missing argument -a; please specify a number of attributes\n");

		return -1;
	}

	FILE* pub_key_file = stdout;
	FILE* priv_key_file = stdout;

	if (!pub_key_filename.empty())
	{
		pub_key_file = fopen(pub_key_filename.c_str(), "w");

		if (pub_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", pub_key_filename.c_str());

			return -1;
		}

		printf("Writing public key to %s\n", pub_key_filename.c_str());
	}

	if (!priv_key_filename.empty())
	{
		priv_key_file = fopen(priv_key_filename.c_str(), "w");

		if (priv_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", priv_key_filename.c_str());

			return -1;
		}

		printf("Writing private key to %s\n", priv_key_filename.c_str());
	}

	generate_key_pair(pub_key_file, priv_key_file, num_attribs, bit_size);

	if (!pub_key_filename.empty()) fclose(pub_key_file);
	if (!priv_key_filename.empty()) fclose(priv_key_file);

	return 0;
}
<|endoftext|>


<commit_before>#include <mysql_priv.h>
#include <mysql/plugin.h>
#include <groonga.h>
#include "ha_groonga.h"

grn_ctx *mrn_ctx_sys;
const char *mrn_log_name="groonga.log";
static FILE *mrn_log_file = NULL;

void mrn_logger_func(int level, const char *time, const char *title,
		     const char *msg, const char *location, void *func_arg)
{
  const char slev[] = " EACewnid-";
  if (mrn_log_file) {
    fprintf(mrn_log_file, "%s|%c|%u|%s %s\n", time,
	    *(slev + level), (uint)pthread_self(), location, msg);
    fflush(mrn_log_file);
  }
}

grn_logger_info mrn_logger_info = {
  GRN_LOG_DUMP,
  GRN_LOG_TIME|GRN_LOG_MESSAGE|GRN_LOG_LOCATION,
  mrn_logger_func,
  NULL
};

#ifdef __cplusplus
extern "C" {
#endif

static int mrn_init(void *p);
static int mrn_fin(void *p);
static handler *mrn_handler_create(handlerton *hton,
				   TABLE_SHARE *share,
				   MEM_ROOT *root);

struct st_mysql_storage_engine storage_engine_structure =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

mysql_declare_plugin(groonga)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &storage_engine_structure,
  "Groonga",
  "Tetsuro IKEDA",
  "An Embeddable Fulltext Search Engine",
  PLUGIN_LICENSE_GPL,
  mrn_init,
  mrn_fin,
  0x0001,
  NULL,
  NULL,
  NULL
}
mysql_declare_plugin_end;

ha_groonga::ha_groonga(handlerton *hton, TABLE_SHARE *share)
  :handler(hton, share)
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

ha_groonga::~ha_groonga()
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

const char *ha_groonga::table_type() const
{
  MRN_ENTER;
  MRN_RETURN_S("Groonga");
}

static const char*ha_groonga_exts[] = {
  NullS
};
const char **ha_groonga::bas_ext() const
{
  MRN_ENTER;
  MRN_RETURN_P(ha_groonga_exts);
}

ulonglong ha_groonga::table_flags() const
{
  MRN_ENTER;
  MRN_RETURN(0);
}

ulong ha_groonga::index_flags(uint idx, uint part, bool all_parts) const
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::create(const char *name, TABLE *form, HA_CREATE_INFO *info)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::open(const char *name, int mode, uint test_if_locked)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::close()
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::info(uint flag)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

THR_LOCK_DATA **ha_groonga::store_lock(THD *thd,
				    THR_LOCK_DATA **to,
				    enum thr_lock_type lock_type)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::rnd_init(bool scan)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::rnd_next(uchar *buf)
{
  MRN_ENTER;
  MRN_RETURN(HA_ERR_END_OF_FILE);
}

int ha_groonga::rnd_pos(uchar *buf, uchar *pos)
{
  MRN_ENTER;
  MRN_RETURN(HA_ERR_WRONG_COMMAND);
}

void ha_groonga::position(const uchar *record)
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

bool mrn_flush_logs(handlerton *hton)
{
  MRN_ENTER;
  MRN_LOG(GRN_LOG_NOTICE, "logfile closed by FLUSH LOGS");
  fflush(mrn_log_file);
  fclose(mrn_log_file);
  mrn_log_file = fopen(mrn_log_name, "a");
  MRN_LOG(GRN_LOG_NOTICE, "logfile re-opened by FLUSH LOGS");
  MRN_RETURN(true);
}

static int mrn_init(void *p)
{
  MRN_ENTER;
  handlerton *hton;
  hton = (handlerton *)p;
  hton->state = SHOW_OPTION_YES;
  hton->create = mrn_handler_create;
  hton->flush_logs = mrn_flush_logs;
  hton->flags = 0;
  grn_init();
  mrn_ctx_sys = (grn_ctx *) malloc(sizeof (grn_ctx));
  grn_ctx_init(mrn_ctx_sys, GRN_CTX_USE_DB, GRN_ENC_UTF8);
  if (!(mrn_log_file = fopen(mrn_log_name, "a"))) {
    MRN_RETURN(-1);
  }
  grn_logger_info_set(mrn_ctx_sys, &mrn_logger_info);
  MRN_LOG(GRN_LOG_NOTICE, "gronnga engine started");
  MRN_RETURN(0);
}

static int mrn_fin(void *p)
{
  MRN_ENTER;
  MRN_LOG(GRN_LOG_NOTICE, "stopping groonga engine");
  fflush(mrn_log_file);
  fclose(mrn_log_file);
  grn_fin();
  MRN_RETURN(0);
}

static handler *mrn_handler_create(handlerton *hton,
				    TABLE_SHARE *share,
				    MEM_ROOT *root)
{
  MRN_ENTER;
  MRN_RETURN_P(new (root) ha_groonga(hton, share));
}

#ifdef __cplusplus
}
#endif

<commit_msg>added global mutex object added mutex-lock on mrn_flush_logs 	modified:   src/ha_groonga.cc<commit_after>#include <mysql_priv.h>
#include <mysql/plugin.h>
#include <groonga.h>
#include "ha_groonga.h"
#include <pthread.h>

pthread_mutex_t mrn_mutex_sys;
grn_ctx *mrn_ctx_sys;
const char *mrn_log_name="groonga.log";
static FILE *mrn_log_file = NULL;

void mrn_logger_func(int level, const char *time, const char *title,
		     const char *msg, const char *location, void *func_arg)
{
  const char slev[] = " EACewnid-";
  if (mrn_log_file) {
    fprintf(mrn_log_file, "%s|%c|%u|%s %s\n", time,
	    *(slev + level), (uint)pthread_self(), location, msg);
    fflush(mrn_log_file);
  }
}

grn_logger_info mrn_logger_info = {
  GRN_LOG_DUMP,
  GRN_LOG_TIME|GRN_LOG_MESSAGE|GRN_LOG_LOCATION,
  mrn_logger_func,
  NULL
};

#ifdef __cplusplus
extern "C" {
#endif

static int mrn_init(void *p);
static int mrn_fin(void *p);
static handler *mrn_handler_create(handlerton *hton,
				   TABLE_SHARE *share,
				   MEM_ROOT *root);

struct st_mysql_storage_engine storage_engine_structure =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

mysql_declare_plugin(groonga)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &storage_engine_structure,
  "Groonga",
  "Tetsuro IKEDA",
  "An Embeddable Fulltext Search Engine",
  PLUGIN_LICENSE_GPL,
  mrn_init,
  mrn_fin,
  0x0001,
  NULL,
  NULL,
  NULL
}
mysql_declare_plugin_end;

ha_groonga::ha_groonga(handlerton *hton, TABLE_SHARE *share)
  :handler(hton, share)
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

ha_groonga::~ha_groonga()
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

const char *ha_groonga::table_type() const
{
  MRN_ENTER;
  MRN_RETURN_S("Groonga");
}

static const char*ha_groonga_exts[] = {
  NullS
};
const char **ha_groonga::bas_ext() const
{
  MRN_ENTER;
  MRN_RETURN_P(ha_groonga_exts);
}

ulonglong ha_groonga::table_flags() const
{
  MRN_ENTER;
  MRN_RETURN(0);
}

ulong ha_groonga::index_flags(uint idx, uint part, bool all_parts) const
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::create(const char *name, TABLE *form, HA_CREATE_INFO *info)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::open(const char *name, int mode, uint test_if_locked)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::close()
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::info(uint flag)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

THR_LOCK_DATA **ha_groonga::store_lock(THD *thd,
				    THR_LOCK_DATA **to,
				    enum thr_lock_type lock_type)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::rnd_init(bool scan)
{
  MRN_ENTER;
  MRN_RETURN(0);
}

int ha_groonga::rnd_next(uchar *buf)
{
  MRN_ENTER;
  MRN_RETURN(HA_ERR_END_OF_FILE);
}

int ha_groonga::rnd_pos(uchar *buf, uchar *pos)
{
  MRN_ENTER;
  MRN_RETURN(HA_ERR_WRONG_COMMAND);
}

void ha_groonga::position(const uchar *record)
{
  MRN_ENTER;
  MRN_RETURN_VOID;
}

bool mrn_flush_logs(handlerton *hton)
{
  MRN_ENTER;
  pthread_mutex_lock(&mrn_mutex_sys);
  MRN_LOG(GRN_LOG_NOTICE, "logfile closed by FLUSH LOGS");
  fflush(mrn_log_file);
  fclose(mrn_log_file);
  mrn_log_file = fopen(mrn_log_name, "a");
  MRN_LOG(GRN_LOG_NOTICE, "logfile re-opened by FLUSH LOGS");
  pthread_mutex_unlock(&mrn_mutex_sys);
  MRN_RETURN(true);
}

static int mrn_init(void *p)
{
  MRN_ENTER;
  handlerton *hton;
  hton = (handlerton *)p;
  hton->state = SHOW_OPTION_YES;
  hton->create = mrn_handler_create;
  hton->flush_logs = mrn_flush_logs;
  hton->flags = 0;

  pthread_mutex_init(&mrn_mutex_sys, MY_MUTEX_INIT_FAST);

  grn_init();
  mrn_ctx_sys = (grn_ctx *) malloc(sizeof (grn_ctx));
  grn_ctx_init(mrn_ctx_sys, GRN_CTX_USE_DB, GRN_ENC_UTF8);

  if (!(mrn_log_file = fopen(mrn_log_name, "a"))) {
    MRN_RETURN(-1);
  }
  grn_logger_info_set(mrn_ctx_sys, &mrn_logger_info);

  MRN_LOG(GRN_LOG_NOTICE, "gronnga engine started");
  MRN_RETURN(0);
}

static int mrn_fin(void *p)
{
  MRN_ENTER;
  MRN_LOG(GRN_LOG_NOTICE, "stopping groonga engine");
  fflush(mrn_log_file);
  fclose(mrn_log_file);
  grn_fin();
  MRN_RETURN(0);
}

static handler *mrn_handler_create(handlerton *hton,
				    TABLE_SHARE *share,
				    MEM_ROOT *root)
{
  MRN_ENTER;
  MRN_RETURN_P(new (root) ha_groonga(hton, share));
}

#ifdef __cplusplus
}
#endif

<|endoftext|>


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

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <compat.h>
#include <util/time.h>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <tinyformat.h>

#include <atomic>
#include <ctime>
#include <thread>

void UninterruptibleSleep(const std::chrono::microseconds &n) {
    std::this_thread::sleep_for(n);
}

//! For unit testing
static std::atomic<int64_t> nMockTime(0);

int64_t GetTime() {
    int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
    if (mocktime) {
        return mocktime;
    }

    time_t now = time(nullptr);
    assert(now > 0);
    return now;
}

bool ChronoSanityCheck() {
    // std::chrono::system_clock.time_since_epoch and time_t(0) are not
    // guaranteed to use the Unix epoch timestamp, prior to C++20, but in
    // practice they almost certainly will. Any differing behavior will be
    // assumed to be an error, unless certain platforms prove to consistently
    // deviate, at which point we'll cope with it by adding offsets.

    // Create a new clock from time_t(0) and make sure that it represents 0
    // seconds from the system_clock's time_since_epoch. Then convert that back
    // to a time_t and verify that it's the same as before.
    const time_t time_t_epoch{};
    auto clock = std::chrono::system_clock::from_time_t(time_t_epoch);
    if (std::chrono::duration_cast<std::chrono::seconds>(
            clock.time_since_epoch())
            .count() != 0) {
        return false;
    }

    time_t time_val = std::chrono::system_clock::to_time_t(clock);
    if (time_val != time_t_epoch) {
        return false;
    }

    // Check that the above zero time is actually equal to the known unix
    // timestamp.
    struct tm epoch;
#ifdef _WIN32
    if (gmtime_s(&epoch, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &epoch) == nullptr) {
#endif
        return false;
    }

    if ((epoch.tm_sec != 0) || (epoch.tm_min != 0) || (epoch.tm_hour != 0) ||
        (epoch.tm_mday != 1) || (epoch.tm_mon != 0) || (epoch.tm_year != 70)) {
        return false;
    }
    return true;
}

template <typename T> T GetTime() {
    const std::chrono::seconds mocktime{
        nMockTime.load(std::memory_order_relaxed)};

    return std::chrono::duration_cast<T>(
        mocktime.count() ? mocktime
                         : std::chrono::microseconds{GetTimeMicros()});
}
template std::chrono::seconds GetTime();
template std::chrono::milliseconds GetTime();
template std::chrono::microseconds GetTime();

template <typename T> static T GetSystemTime() {
    const auto now = std::chrono::duration_cast<T>(
        std::chrono::system_clock::now().time_since_epoch());
    assert(now.count() > 0);
    return now;
}

void SetMockTime(int64_t nMockTimeIn) {
    assert(nMockTimeIn >= 0);
    nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}

int64_t GetMockTime() {
    return nMockTime.load(std::memory_order_relaxed);
}

int64_t GetTimeMillis() {
    return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
}

int64_t GetTimeMicros() {
    return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
}

int64_t GetTimeSeconds() {
    return int64_t{GetSystemTime<std::chrono::seconds>().count()};
}

std::string FormatISO8601DateTime(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _WIN32
    if (gmtime_s(&ts, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &ts) == nullptr) {
#endif
        return {};
    }
    return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900,
                     ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min,
                     ts.tm_sec);
}

std::string FormatISO8601Date(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _WIN32
    if (gmtime_s(&ts, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &ts) == nullptr) {
#endif
        return {};
    }
    return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1,
                     ts.tm_mday);
}

int64_t ParseISO8601DateTime(const std::string &str) {
    static const boost::posix_time::ptime epoch =
        boost::posix_time::from_time_t(0);
    static const std::locale loc(
        std::locale::classic(),
        new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
    std::istringstream iss(str);
    iss.imbue(loc);
    boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
    iss >> ptime;
    if (ptime.is_not_a_date_time() || epoch > ptime) {
        return 0;
    }
    return (ptime - epoch).total_seconds();
}

struct timeval MillisToTimeval(int64_t nTimeout) {
    struct timeval timeout;
    timeout.tv_sec = nTimeout / 1000;
    timeout.tv_usec = (nTimeout % 1000) * 1000;
    return timeout;
}

struct timeval MillisToTimeval(std::chrono::milliseconds ms) {
    return MillisToTimeval(count_milliseconds(ms));
}
<commit_msg>Simplify GetTime<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <compat.h>
#include <util/time.h>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <tinyformat.h>

#include <atomic>
#include <ctime>
#include <thread>

void UninterruptibleSleep(const std::chrono::microseconds &n) {
    std::this_thread::sleep_for(n);
}

//! For unit testing
static std::atomic<int64_t> nMockTime(0);

bool ChronoSanityCheck() {
    // std::chrono::system_clock.time_since_epoch and time_t(0) are not
    // guaranteed to use the Unix epoch timestamp, prior to C++20, but in
    // practice they almost certainly will. Any differing behavior will be
    // assumed to be an error, unless certain platforms prove to consistently
    // deviate, at which point we'll cope with it by adding offsets.

    // Create a new clock from time_t(0) and make sure that it represents 0
    // seconds from the system_clock's time_since_epoch. Then convert that back
    // to a time_t and verify that it's the same as before.
    const time_t time_t_epoch{};
    auto clock = std::chrono::system_clock::from_time_t(time_t_epoch);
    if (std::chrono::duration_cast<std::chrono::seconds>(
            clock.time_since_epoch())
            .count() != 0) {
        return false;
    }

    time_t time_val = std::chrono::system_clock::to_time_t(clock);
    if (time_val != time_t_epoch) {
        return false;
    }

    // Check that the above zero time is actually equal to the known unix
    // timestamp.
    struct tm epoch;
#ifdef _WIN32
    if (gmtime_s(&epoch, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &epoch) == nullptr) {
#endif
        return false;
    }

    if ((epoch.tm_sec != 0) || (epoch.tm_min != 0) || (epoch.tm_hour != 0) ||
        (epoch.tm_mday != 1) || (epoch.tm_mon != 0) || (epoch.tm_year != 70)) {
        return false;
    }
    return true;
}

template <typename T> T GetTime() {
    const std::chrono::seconds mocktime{
        nMockTime.load(std::memory_order_relaxed)};

    const auto ret{
        mocktime.count()
            ? mocktime
            : std::chrono::duration_cast<T>(
                  std::chrono::system_clock::now().time_since_epoch())};
    assert(ret > 0s);
    return ret;
}
template std::chrono::seconds GetTime();
template std::chrono::milliseconds GetTime();
template std::chrono::microseconds GetTime();

template <typename T> static T GetSystemTime() {
    const auto now = std::chrono::duration_cast<T>(
        std::chrono::system_clock::now().time_since_epoch());
    assert(now.count() > 0);
    return now;
}

void SetMockTime(int64_t nMockTimeIn) {
    assert(nMockTimeIn >= 0);
    nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}

int64_t GetMockTime() {
    return nMockTime.load(std::memory_order_relaxed);
}

int64_t GetTimeMillis() {
    return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
}

int64_t GetTimeMicros() {
    return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
}

int64_t GetTimeSeconds() {
    return int64_t{GetSystemTime<std::chrono::seconds>().count()};
}

int64_t GetTime() {
    return GetTime<std::chrono::seconds>().count();
}

std::string FormatISO8601DateTime(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _WIN32
    if (gmtime_s(&ts, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &ts) == nullptr) {
#endif
        return {};
    }
    return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900,
                     ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min,
                     ts.tm_sec);
}

std::string FormatISO8601Date(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _WIN32
    if (gmtime_s(&ts, &time_val) != 0) {
#else
    if (gmtime_r(&time_val, &ts) == nullptr) {
#endif
        return {};
    }
    return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1,
                     ts.tm_mday);
}

int64_t ParseISO8601DateTime(const std::string &str) {
    static const boost::posix_time::ptime epoch =
        boost::posix_time::from_time_t(0);
    static const std::locale loc(
        std::locale::classic(),
        new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
    std::istringstream iss(str);
    iss.imbue(loc);
    boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
    iss >> ptime;
    if (ptime.is_not_a_date_time() || epoch > ptime) {
        return 0;
    }
    return (ptime - epoch).total_seconds();
}

struct timeval MillisToTimeval(int64_t nTimeout) {
    struct timeval timeout;
    timeout.tv_sec = nTimeout / 1000;
    timeout.tv_usec = (nTimeout % 1000) * 1000;
    return timeout;
}

struct timeval MillisToTimeval(std::chrono::milliseconds ms) {
    return MillisToTimeval(count_milliseconds(ms));
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <mutex>
#include <math.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
#include <nix/util/util.hpp>

using namespace std;

namespace nix {
namespace util {

// default id base (16 or 32)
const int    ID_BASE = 32;
// Base32hex alphabet (RFC 4648)
const char*  ID_ALPHABET = "0123456789abcdefghijklmnopqrstuv";
// Unit scaling, SI only, substitutions for micro and ohm...
const string  PREFIXES = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|u|n|p|f|a|z|y)";
const string  UNITS = "(m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L|Ohm|%|dB)";
const string  POWER = "(\\^[+-]?[1-9]\\d*)";

const map<string, double> PREFIX_FACTORS = {{"y", 1.0e-24}, {"z", 1.0e-21}, {"a", 1.0e-18}, {"f", 1.0e-15},
    {"p", 1.0e-12}, {"n",1.0e-9}, {"u", 1.0e-6}, {"m", 1.0e-3}, {"c", 1.0e-2}, {"d",1.0e-1}, {"da", 1.0e1}, {"h", 1.0e2},
    {"k", 1.0e3}, {"M",1.0e6}, {"G", 1.0e9}, {"T", 1.0e12}, {"P", 1.0e15}, {"E",1.0e18}, {"Z", 1.0e21}, {"Y", 1.0e24}};

string createId(string prefix, int length) {
    static std::once_flag rand_init;
    std::call_once(rand_init, []() { srand(static_cast<unsigned int>(time(0))); });

    string id;
    if (prefix.length() > 0) {
        id.append(prefix);
        id.append("_");
    }
    for (int i = 0; i < length; i++) {
        char c = ID_ALPHABET[(size_t) (((double) (rand())) / RAND_MAX * ID_BASE)];
        id.push_back(c);
    }
    return id;
}

string timeToStr(time_t time) {
    using namespace boost::posix_time;
    ptime timetmp = from_time_t(time);
    return to_iso_string(timetmp);
}

time_t strToTime(const string &time) {
    using namespace boost::posix_time;
    ptime timetmp(from_iso_string(time));
    ptime epoch(boost::gregorian::date(1970, 1, 1));
    return (timetmp - epoch).total_seconds();
}

time_t getTime() {
    return time(NULL);
}

void deblankString(std::string &str) {
    typedef std::string::value_type char_type;

    str.erase(std::remove_if(str.begin(),
                             str.end(),
                             [](char_type c) { return std::isblank(c); }),
              str.end());
}

std::string deblankString(const std::string &str) {
    std::string str_copy = str;
    deblankString(str_copy);
    return str_copy;
}

std::string unitSanitizer(const std::string &unit) {
     std::string new_unit = deblankString(unit);
     while (new_unit.find("mu") != string::npos) {
          size_t pos = new_unit.find("mu");
          new_unit = new_unit.replace(pos, 2, "u");

     }
     while (new_unit.find("µ") != string::npos) {
          size_t pos = new_unit.find("µ");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     return new_unit;
}

void splitUnit(const string &combinedUnit, string &prefix, string &unit, string &power) {
    boost::regex prefix_and_unit_and_power(PREFIXES + UNITS + POWER);
    boost::regex prefix_and_unit(PREFIXES + UNITS);
    boost::regex unit_and_power(UNITS + POWER);
    boost::regex unit_only(UNITS);
    boost::regex prefix_only(PREFIXES);

    if (boost::regex_match(combinedUnit, prefix_and_unit_and_power)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        string suffix = m.suffix();
        boost::regex_search(suffix, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, unit_and_power)) {
        prefix = "";
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, prefix_and_unit)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        unit = m.suffix();
        power = "";
    } else {
        unit = combinedUnit;
        prefix = "";
        power = "";
    }
}

void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits) {
    string s = compoundUnit;
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    boost::regex separator("(\\*|/)");
    boost::match_results<std::string::const_iterator> m;

    while (boost::regex_search(s, m, opt_prefix_and_unit_and_power) && (m.suffix().length() > 0)) {
        string suffix = m.suffix();
        atomicUnits.push_back(m[0]);
        s = suffix.substr(1);
    }
    atomicUnits.push_back(m[0]);
}

bool isSIUnit(const string &unit) {
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    return boost::regex_match(unit, opt_prefix_and_unit_and_power);
}

bool isCompoundSIUnit(const string &unit) {
    string atomic_unit = PREFIXES + "?" + UNITS + POWER + "?";
    boost::regex compound_unit("(" + atomic_unit + "(\\*|/))+"+ atomic_unit);
    return boost::regex_match(unit, compound_unit);
}

bool isScalable(const string &unitA, const string &unitB) {
    if (!(isSIUnit(unitA) && isSIUnit(unitB))) {
        return false;
    }
    string a_unit, a_prefix, a_power;
    string b_unit, b_prefix, b_power;
    splitUnit(unitA, a_prefix, a_unit, a_power);
    splitUnit(unitB, b_prefix, b_unit, b_power);
    if (!(a_unit == b_unit) || !(a_power == b_power) ) {
        return false;
    }
    return true;
}

double getSIScaling(const string &originUnit, const string &destinationUnit) {
    double scaling = 1.0;
    if (!isScalable(originUnit, destinationUnit)) {
        throw nix::InvalidUnit("Origin unit and destination unit are not scalable versions of the same SI unit!",
                               "nix::util::getSIScaling");
    }

    string org_unit, org_prefix, org_power;
    string dest_unit, dest_prefix, dest_power;
    splitUnit(originUnit, org_prefix, org_unit, org_power);
    splitUnit(destinationUnit, dest_prefix, dest_unit, dest_power);

    if ((org_prefix == dest_prefix) && (org_power == dest_power)) {
        return scaling;
    }
    if (dest_prefix.empty() && !org_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix);
    } else if (org_prefix.empty() && !dest_prefix.empty()) {
        scaling = 1.0 / PREFIX_FACTORS.at(dest_prefix);
    } else if (!org_prefix.empty() && !dest_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix) / PREFIX_FACTORS.at(dest_prefix);
    }
    if (!org_power.empty()) {
        int power = std::stoi(org_power);
        scaling = pow(scaling, power);
    }
    return scaling;
}

} // namespace util
} // namespace nix
<commit_msg>Moved function bodies of "convertTo*" functions from util.hpp to cpp<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <mutex>
#include <math.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
#include <nix/util/util.hpp>

using namespace std;

namespace nix {
namespace util {

// default id base (16 or 32)
const int    ID_BASE = 32;
// Base32hex alphabet (RFC 4648)
const char*  ID_ALPHABET = "0123456789abcdefghijklmnopqrstuv";
// Unit scaling, SI only, substitutions for micro and ohm...
const string  PREFIXES = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|u|n|p|f|a|z|y)";
const string  UNITS = "(m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L|Ohm|%|dB)";
const string  POWER = "(\\^[+-]?[1-9]\\d*)";

const map<string, double> PREFIX_FACTORS = {{"y", 1.0e-24}, {"z", 1.0e-21}, {"a", 1.0e-18}, {"f", 1.0e-15},
    {"p", 1.0e-12}, {"n",1.0e-9}, {"u", 1.0e-6}, {"m", 1.0e-3}, {"c", 1.0e-2}, {"d",1.0e-1}, {"da", 1.0e1}, {"h", 1.0e2},
    {"k", 1.0e3}, {"M",1.0e6}, {"G", 1.0e9}, {"T", 1.0e12}, {"P", 1.0e15}, {"E",1.0e18}, {"Z", 1.0e21}, {"Y", 1.0e24}};

string createId(string prefix, int length) {
    static std::once_flag rand_init;
    std::call_once(rand_init, []() { srand(static_cast<unsigned int>(time(0))); });

    string id;
    if (prefix.length() > 0) {
        id.append(prefix);
        id.append("_");
    }
    for (int i = 0; i < length; i++) {
        char c = ID_ALPHABET[(size_t) (((double) (rand())) / RAND_MAX * ID_BASE)];
        id.push_back(c);
    }
    return id;
}

string timeToStr(time_t time) {
    using namespace boost::posix_time;
    ptime timetmp = from_time_t(time);
    return to_iso_string(timetmp);
}

time_t strToTime(const string &time) {
    using namespace boost::posix_time;
    ptime timetmp(from_iso_string(time));
    ptime epoch(boost::gregorian::date(1970, 1, 1));
    return (timetmp - epoch).total_seconds();
}

time_t getTime() {
    return time(NULL);
}

void deblankString(std::string &str) {
    typedef std::string::value_type char_type;

    str.erase(std::remove_if(str.begin(),
                             str.end(),
                             [](char_type c) { return std::isblank(c); }),
              str.end());
}

std::string deblankString(const std::string &str) {
    std::string str_copy = str;
    deblankString(str_copy);
    return str_copy;
}

std::string unitSanitizer(const std::string &unit) {
     std::string new_unit = deblankString(unit);
     while (new_unit.find("mu") != string::npos) {
          size_t pos = new_unit.find("mu");
          new_unit = new_unit.replace(pos, 2, "u");

     }
     while (new_unit.find("µ") != string::npos) {
          size_t pos = new_unit.find("µ");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     return new_unit;
}

void splitUnit(const string &combinedUnit, string &prefix, string &unit, string &power) {
    boost::regex prefix_and_unit_and_power(PREFIXES + UNITS + POWER);
    boost::regex prefix_and_unit(PREFIXES + UNITS);
    boost::regex unit_and_power(UNITS + POWER);
    boost::regex unit_only(UNITS);
    boost::regex prefix_only(PREFIXES);

    if (boost::regex_match(combinedUnit, prefix_and_unit_and_power)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        string suffix = m.suffix();
        boost::regex_search(suffix, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, unit_and_power)) {
        prefix = "";
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, prefix_and_unit)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        unit = m.suffix();
        power = "";
    } else {
        unit = combinedUnit;
        prefix = "";
        power = "";
    }
}

void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits) {
    string s = compoundUnit;
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    boost::regex separator("(\\*|/)");
    boost::match_results<std::string::const_iterator> m;

    while (boost::regex_search(s, m, opt_prefix_and_unit_and_power) && (m.suffix().length() > 0)) {
        string suffix = m.suffix();
        atomicUnits.push_back(m[0]);
        s = suffix.substr(1);
    }
    atomicUnits.push_back(m[0]);
}

template <typename T>
NIXAPI T convertToSeconds(const std::string &unit, T value) {
     T seconds;
     if (unit == "min") {
          seconds = value * 60;
     } else if (unit == "h") {
          std::string new_unit = "min";
          seconds = convertToSeconds(new_unit, value * 60);
     } else if (unit == "s") {
         seconds = value;
     } else {
          std::cerr <<  "[nix::util::convertToSeconds] Warning: given unit is not supported!" << std::endl;
          seconds = value;
     }
     return seconds;
}

template<typename T>
NIXAPI T convertToKelvin(const std::string &unit, T value) {
     T temperature;
     if (unit == "°C" || unit == "C") {
          temperature = value + 273.15;
     } else if (unit == "°F" || unit == "F") {
          double temp = (value - 32) * 5.0/9 + 273.15;
          temperature = std::is_integral<T>::value ? std::round(temp) : temp;
     } else if (unit == "°K" || unit == "K") {
         temperature = value;
     } else {
          std::cerr << "[nix::util::convertToKelvin] Warning: given unit is not supported" << std::endl;
          temperature = value;
     }
     return temperature;
}

bool isSIUnit(const string &unit) {
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    return boost::regex_match(unit, opt_prefix_and_unit_and_power);
}

bool isCompoundSIUnit(const string &unit) {
    string atomic_unit = PREFIXES + "?" + UNITS + POWER + "?";
    boost::regex compound_unit("(" + atomic_unit + "(\\*|/))+"+ atomic_unit);
    return boost::regex_match(unit, compound_unit);
}

bool isScalable(const string &unitA, const string &unitB) {
    if (!(isSIUnit(unitA) && isSIUnit(unitB))) {
        return false;
    }
    string a_unit, a_prefix, a_power;
    string b_unit, b_prefix, b_power;
    splitUnit(unitA, a_prefix, a_unit, a_power);
    splitUnit(unitB, b_prefix, b_unit, b_power);
    if (!(a_unit == b_unit) || !(a_power == b_power) ) {
        return false;
    }
    return true;
}

double getSIScaling(const string &originUnit, const string &destinationUnit) {
    double scaling = 1.0;
    if (!isScalable(originUnit, destinationUnit)) {
        throw nix::InvalidUnit("Origin unit and destination unit are not scalable versions of the same SI unit!",
                               "nix::util::getSIScaling");
    }

    string org_unit, org_prefix, org_power;
    string dest_unit, dest_prefix, dest_power;
    splitUnit(originUnit, org_prefix, org_unit, org_power);
    splitUnit(destinationUnit, dest_prefix, dest_unit, dest_power);

    if ((org_prefix == dest_prefix) && (org_power == dest_power)) {
        return scaling;
    }
    if (dest_prefix.empty() && !org_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix);
    } else if (org_prefix.empty() && !dest_prefix.empty()) {
        scaling = 1.0 / PREFIX_FACTORS.at(dest_prefix);
    } else if (!org_prefix.empty() && !dest_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix) / PREFIX_FACTORS.at(dest_prefix);
    }
    if (!org_power.empty()) {
        int power = std::stoi(org_power);
        scaling = pow(scaling, power);
    }
    return scaling;
}

} // namespace util
} // namespace nix
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. 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 <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include <chartsql/expressions/math.h>

namespace csql {
namespace expressions {

void addExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for add. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() + rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() + rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() + rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() + rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  *out = SValue(lhs->toString() + rhs->toString());
}

void subExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for sub. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() - rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() - rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() - rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() - rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't subtract %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void mulExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for mul. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() * rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() * rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() * rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() * rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't multiply %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void divExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for div. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() / rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() / rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() / rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() / rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't divide %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void modExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for mod. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() % rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue(fmod(lhs->getInteger(), rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue(fmod(lhs->getFloat(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue(fmod(lhs->getFloat(), rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't modulo %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void powExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for pow. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) pow(lhs->getInteger(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) pow(lhs->getInteger(), rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) pow(lhs->getFloat(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) pow(lhs->getFloat(), rhs->getFloat()));
          return;
        default:
          break;
      }
      break;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't pow %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

}
}
<commit_msg>handle NULL in math expressions<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. 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 <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include <chartsql/expressions/math.h>

namespace csql {
namespace expressions {

void addExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for add. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() + rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() + rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() + rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() + rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  *out = SValue(lhs->toString() + rhs->toString());
}

void subExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for sub. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() - rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() - rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() - rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() - rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't subtract %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void mulExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for mul. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() * rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() * rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() * rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() * rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't multiply %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void divExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for div. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() / rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getInteger() / rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) (lhs->getFloat() / rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) (lhs->getFloat() / rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't divide %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void modExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for mod. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) (lhs->getInteger() % rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue(fmod(lhs->getInteger(), rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue(fmod(lhs->getFloat(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue(fmod(lhs->getFloat(), rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't modulo %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

void powExpr(int argc, SValue* argv, SValue* out) {
  if (argc != 2) {
    RAISE(
        kRuntimeError,
        "wrong number of arguments for pow. expected: 2, got: %i", argc);
  }

  SValue* lhs = argv;
  SValue* rhs = argv + 1;

  switch(lhs->testTypeWithNumericConversion()) {
    case SValue::T_INTEGER:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((int64_t) pow(lhs->getInteger(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) pow(lhs->getInteger(), rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_FLOAT:
      switch(rhs->testTypeWithNumericConversion()) {
        case SValue::T_INTEGER:
          *out = SValue((double) pow(lhs->getFloat(), rhs->getInteger()));
          return;
        case SValue::T_FLOAT:
          *out = SValue((double) pow(lhs->getFloat(), rhs->getFloat()));
          return;
        case SValue::T_NULL:
          *out = SValue();
          return;
        default:
          break;
      }
      break;
    case SValue::T_NULL:
      *out = SValue();
      return;
    default:
      break;
  }

  RAISE(kRuntimeError, "can't pow %s and %s",
      lhs->getTypeName(),
      rhs->getTypeName());
}

}
}
<|endoftext|>


<commit_before>/* See LICENSE file for copyright and license details. */

#include <QPoint>
#include <utility>
#include <algorithm>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsDropShadowEffect>
#include <iostream>
#include <QMetaProperty>
#include <QDebug>

#include "scene.hpp"
#include "graphicsnode.hpp"
#include "socket.hpp"

#include "edge.hpp"

    using namespace std;

    GraphicsDirectedEdge::GraphicsDirectedEdge(QPoint start, QPoint stop,
                                            qreal factor)
            :_effect(new QGraphicsDropShadowEffect()),
            _start(start),
            _stop(stop),
            _factor(factor),
            _label(new EditableLabel(this)) {

        //setFlag(QGraphicsItem::ItemIsSelectable);

        _pen.setWidth(2);
        setZValue(-1);

        _effect->setBlurRadius(15.0);
        _effect->setColor(QColor("#99050505"));
        setGraphicsEffect(_effect);

        _label->setDefaultTextColor(QColor("#888888"));
        //qWarning() << "[G] Created edge";

}

    GraphicsDirectedEdge::GraphicsDirectedEdge()
        : GraphicsDirectedEdge(QPoint(0, 0), QPoint(0, 0)) {}

    GraphicsDirectedEdge::~GraphicsDirectedEdge() {

        delete _label;
        delete _effect;

        //if (_connection.expired())
        //    qWarning() << "[G] Edge deleted (connection already dead)";
        //else
        //    qWarning() << "[G] Edge deleted (connection "
        //            << QString::fromStdString(_connection.lock()->name) << ")";
    }

    void GraphicsDirectedEdge::mousePressEvent(QGraphicsSceneMouseEvent* event) {
        QGraphicsPathItem::mousePressEvent(event);
    }

    void GraphicsDirectedEdge::set_start(QPoint p) {
        _start = p;
        this->update_path();
        placeLabel();
    }

    void GraphicsDirectedEdge::set_stop(QPoint p) {
        _stop = p;
        update_path();
        placeLabel();
    }

    void GraphicsDirectedEdge::connect(GraphicsNode* source_node,
                                       Port* source_port,
                                       GraphicsNode* sink_node,
                                       Port* sink_port) {
    connect_source(source_node->getPort(source_port).get());  // non-owning access to the socket
    connect_sink(sink_node->getPort(sink_port).get());  // non-owning access to the socket
}

void GraphicsDirectedEdge::establishConnection() {

        emit connectionEstablished(shared_from_this());

        if(_connection.use_count() == 0)
            throw std::logic_error("At that point, the edge should have its underlying connection set!!");

        _label->setPlainText(QString::fromStdString(_connection.lock()->name));
        QObject::connect(_label, &EditableLabel::contentUpdated,
                         this, &GraphicsDirectedEdge::setConnectionName);

}

void GraphicsDirectedEdge::connect_sink(GraphicsNodeSocket* sink) {
    if (_sink == sink) return;

    if (_sink) disconnect_sink();

    _sink = sink;
    if (_sink) _sink->connect_edge(shared_from_this());

    if (_source) establishConnection();
}

void GraphicsDirectedEdge::connect_source(GraphicsNodeSocket* source) {
    if (_source == source) return;

    if (_source) disconnect_source();

    _source = source;
    if (_source) _source->connect_edge(shared_from_this());

    if (_sink) establishConnection();
}

void GraphicsDirectedEdge::disconnect() {
    disconnect_source();
    disconnect_sink();
}

void GraphicsDirectedEdge::disconnect_sink() {
    if (_sink && _source &&
        _sink->is_connected_to(shared_from_this()) && _source->is_connected_to(shared_from_this()))
        emit connectionDisrupted(shared_from_this());

    if (_sink) _sink->disconnect_edge(shared_from_this());
}

void GraphicsDirectedEdge::disconnect_source() {
    if (_sink && _source &&
        _sink->is_connected_to(shared_from_this()) && _source->is_connected_to(shared_from_this()))
        emit connectionDisrupted(shared_from_this());

    if (_source) _source->disconnect_edge(shared_from_this());
}

void GraphicsDirectedEdge::placeLabel() {
    QPointF corner{_start + (_stop - _start)/2};
    _label->setPos(corner);
}

void GraphicsDirectedEdge::setConnectionName(const QString& name) {
    _connection.lock()->name = name.toStdString();
}

void GraphicsBezierEdge::update_path() {
    QPoint c1, c2;
    QPainterPath path(_start);

    // compute anchor point offsets
    const qreal min_dist = 0.f;
    // const qreal max_dist = 250.f;
    qreal dist = 0;
    if (_start.x() <= _stop.x()) {
        dist = std::max(min_dist, (_stop.x() - _start.x()) * _factor);
    } else {
        dist = std::max(min_dist, (_start.x() - _stop.x()) * _factor);
    }

    // dist = std::min(dist, max_dist);
    c1.setX(_start.x() + dist);
    c1.setY(_start.y());

    c2.setX(_stop.x() - dist);
    c2.setY(_stop.y());

    path.cubicTo(c1, c2, _stop);
    setPath(path);
}

void GraphicsBezierEdge::paint(QPainter* painter,
                               const QStyleOptionGraphicsItem* /*option*/,
                               QWidget* /*widget*/) {
    painter->setPen(_pen);
    painter->drawPath(path());
}
<commit_msg>Set edge label width<commit_after>/* See LICENSE file for copyright and license details. */

#include <QPoint>
#include <utility>
#include <algorithm>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsDropShadowEffect>
#include <iostream>
#include <QMetaProperty>
#include <QDebug>

#include "scene.hpp"
#include "graphicsnode.hpp"
#include "socket.hpp"

#include "edge.hpp"

    using namespace std;

    GraphicsDirectedEdge::GraphicsDirectedEdge(QPoint start, QPoint stop,
                                            qreal factor)
            :_effect(new QGraphicsDropShadowEffect()),
            _start(start),
            _stop(stop),
            _factor(factor),
            _label(new EditableLabel(this)) {

        //setFlag(QGraphicsItem::ItemIsSelectable);

        _pen.setWidth(2);
        setZValue(-1);

        _effect->setBlurRadius(15.0);
        _effect->setColor(QColor("#99050505"));
        setGraphicsEffect(_effect);

        _label->setDefaultTextColor(QColor("#888888"));
        _label->setTextWidth(100);
        //qWarning() << "[G] Created edge";

}

    GraphicsDirectedEdge::GraphicsDirectedEdge()
        : GraphicsDirectedEdge(QPoint(0, 0), QPoint(0, 0)) {}

    GraphicsDirectedEdge::~GraphicsDirectedEdge() {

        delete _label;
        delete _effect;

        //if (_connection.expired())
        //    qWarning() << "[G] Edge deleted (connection already dead)";
        //else
        //    qWarning() << "[G] Edge deleted (connection "
        //            << QString::fromStdString(_connection.lock()->name) << ")";
    }

    void GraphicsDirectedEdge::mousePressEvent(QGraphicsSceneMouseEvent* event) {
        QGraphicsPathItem::mousePressEvent(event);
    }

    void GraphicsDirectedEdge::set_start(QPoint p) {
        _start = p;
        this->update_path();
        placeLabel();
    }

    void GraphicsDirectedEdge::set_stop(QPoint p) {
        _stop = p;
        update_path();
        placeLabel();
    }

    void GraphicsDirectedEdge::connect(GraphicsNode* source_node,
                                       Port* source_port,
                                       GraphicsNode* sink_node,
                                       Port* sink_port) {
    connect_source(source_node->getPort(source_port).get());  // non-owning access to the socket
    connect_sink(sink_node->getPort(sink_port).get());  // non-owning access to the socket
}

void GraphicsDirectedEdge::establishConnection() {

        emit connectionEstablished(shared_from_this());

        if(_connection.use_count() == 0)
            throw std::logic_error("At that point, the edge should have its underlying connection set!!");

        _label->setPlainText(QString::fromStdString(_connection.lock()->name));
        QObject::connect(_label, &EditableLabel::contentUpdated,
                         this, &GraphicsDirectedEdge::setConnectionName);

}

void GraphicsDirectedEdge::connect_sink(GraphicsNodeSocket* sink) {
    if (_sink == sink) return;

    if (_sink) disconnect_sink();

    _sink = sink;
    if (_sink) _sink->connect_edge(shared_from_this());

    if (_source) establishConnection();
}

void GraphicsDirectedEdge::connect_source(GraphicsNodeSocket* source) {
    if (_source == source) return;

    if (_source) disconnect_source();

    _source = source;
    if (_source) _source->connect_edge(shared_from_this());

    if (_sink) establishConnection();
}

void GraphicsDirectedEdge::disconnect() {
    disconnect_source();
    disconnect_sink();
}

void GraphicsDirectedEdge::disconnect_sink() {
    if (_sink && _source &&
        _sink->is_connected_to(shared_from_this()) && _source->is_connected_to(shared_from_this()))
        emit connectionDisrupted(shared_from_this());

    if (_sink) _sink->disconnect_edge(shared_from_this());
}

void GraphicsDirectedEdge::disconnect_source() {
    if (_sink && _source &&
        _sink->is_connected_to(shared_from_this()) && _source->is_connected_to(shared_from_this()))
        emit connectionDisrupted(shared_from_this());

    if (_source) _source->disconnect_edge(shared_from_this());
}

void GraphicsDirectedEdge::placeLabel() {
    QPointF corner{_start + (_stop - _start)/2};
    _label->setPos(corner);
}

void GraphicsDirectedEdge::setConnectionName(const QString& name) {
    _connection.lock()->name = name.toStdString();
}

void GraphicsBezierEdge::update_path() {
    QPoint c1, c2;
    QPainterPath path(_start);

    // compute anchor point offsets
    const qreal min_dist = 0.f;
    // const qreal max_dist = 250.f;
    qreal dist = 0;
    if (_start.x() <= _stop.x()) {
        dist = std::max(min_dist, (_stop.x() - _start.x()) * _factor);
    } else {
        dist = std::max(min_dist, (_start.x() - _stop.x()) * _factor);
    }

    // dist = std::min(dist, max_dist);
    c1.setX(_start.x() + dist);
    c1.setY(_start.y());

    c2.setX(_stop.x() - dist);
    c2.setY(_stop.y());

    path.cubicTo(c1, c2, _stop);
    setPath(path);
}

void GraphicsBezierEdge::paint(QPainter* painter,
                               const QStyleOptionGraphicsItem* /*option*/,
                               QWidget* /*widget*/) {
    painter->setPen(_pen);
    painter->drawPath(path());
}
<|endoftext|>