<commit_before>/*
Copyright (c) 2013, 2014, 2015, Maxim Konakov
 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 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 "test_messages.h"
#include <string.h>
#include <stdexcept>

// FIX message for tests
static
void validate_message(const struct fix_message* pm)
{
	const fix_parser* const parser = (const fix_parser*) ((const char*)pm - offsetof(fix_parser, message));

	ensure_buffer(parser->buffer);
	validate_simple_message(pm);
}

static
void basic_test()
{
	fix_parser* parser = create_fix_parser(get_dummy_classifier);
	const fix_message* pm = get_first_fix_message(parser, simple_message, simple_message_size);

	ensure(pm != nullptr);
	ensure(!get_fix_parser_error(parser));

	validate_message(pm);

	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

static
void splitter_test()
{
	std::string s(copy_simple_message(4));
	fix_parser* parser = create_fix_parser(get_dummy_classifier);

	ensure(parser != nullptr);

	const size_t n = 100;
	size_t counter = 0;
	const char* p = s.c_str();
	const char* const end = p + s.size();

	for(; p < end; p += n)
	{
		for(const fix_message* pm = get_first_fix_message(parser, p, std::min(n, (size_t)(end - p))); pm; pm = get_next_fix_message(parser))
		{
			ensure(!get_fix_parser_error(parser));
			validate_message(pm);
			++counter;
		}
	}

	free_fix_parser(parser);
	ensure(counter == 4);
}

static
void invalid_message_test()
{
	const char m[] = "8=FIX.4.4\x01" "9=122\x01" "35=D\x02";

	fix_parser* parser = create_fix_parser(get_dummy_classifier);
	const fix_message* pm = get_first_fix_message(parser, m, sizeof(m) - 1);

	ensure(!pm);
	ensure(strcmp(get_fix_parser_error(parser), "Unexpected byte 0x2 in FIX message") == 0);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// message to play with
const char m[] = "8=FIX.4.2\x01" "9=42\x01" "35=0\x01" "49=A\x01" "56=B\x01" "34=12\x01" "52=20100304-07:59:30\x01";

MESSAGE(m_message_spec)
	VALID_TAGS(m_message_spec)
		TAG(49)
		TAG(56)
		TAG(34)
		TAG(52)
	END_VALID_TAGS

	NO_DATA_TAGS(m_message_spec)
	NO_GROUPS(m_message_spec)
END_NODE(m_message_spec);

static
const struct fix_tag_classifier* m_message_classifier(fix_message_version version, const char* msg_type)
{
	return (version == FIX_4_2 && msg_type[0] == '0' && msg_type[1] == 0) ? PARSER_TABLE_ADDRESS(m_message_spec) : NULL;
}

static
void validate_m_message(const fix_message* pm)
{
	ensure(pm->version == FIX_4_2);
	ensure(pm->type[0] == '0' && pm->type[1] == 0);

	const fix_group_node* const node = get_fix_message_root_node(pm);

	ensure(node != nullptr);
	ensure(get_fix_node_size(node) == 4);
	ensure_tag(node, 49, "A");
	ensure_tag(node, 56, "B");
	ensure_tag(node, 34, "12");
	ensure_tag_as_utc_timestamp(node, 52, "20100304-07:59:30.000");
}

// test driver
static
void test_for_error(void (*modifier)(std::string&), void (*validator)(const fix_message*))
{
	std::string msg(m, sizeof(m) - 1);

	if(modifier)
		modifier(msg);

	msg = make_fix_message(msg.c_str());

	fix_parser* const parser = create_fix_parser(m_message_classifier);
	const fix_message* const pm = get_first_fix_message(parser, msg.c_str(), msg.size());

	ensure(pm);
	validator(pm);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// unexpected tag in message body
static
void unexpected_tag_modifier(std::string& msg)
{
	msg[msg.find("56=")] = '7';
}

static
void unexpected_tag_validator(const fix_message* pm)
{
	ensure(strcmp(pm->error, "FIX message (version 'FIX.4.2', type '0') error: Unexpected tag 76") == 0);
}

// duplicate tag in message body
static
void duplicate_tag_modifier(std::string& msg)
{
	msg.append("56=B\x01");
}

static
void duplicate_tag_validator(const fix_message* pm)
{
	ensure(strcmp(pm->error, "FIX message (version 'FIX.4.2', type '0') error: Duplicate tag 56 in a message node") == 0);
}

static
void invalid_message_test2()
{
	test_for_error(nullptr, validate_m_message);
	test_for_error(unexpected_tag_modifier, unexpected_tag_validator);
	test_for_error(duplicate_tag_modifier, duplicate_tag_validator);
}

// binary tag test
MESSAGE(mb_message_spec)
	VALID_TAGS(mb_message_spec)
		TAG(49)
		TAG(56)
		TAG(34)
		TAG(52)
		TAG(354)
		TAG(355)
	END_VALID_TAGS

	DATA_TAGS(mb_message_spec)
		DATA_TAG(354, 355)
	END_DATA_TAGS

	NO_GROUPS(mb_message_spec)
END_NODE(mb_message_spec);

static
const struct fix_tag_classifier* mb_message_classifier(fix_message_version version, const char* msg_type)
{
	return (version == FIX_4_2 && msg_type[0] == '0' && msg_type[1] == 0) ? PARSER_TABLE_ADDRESS(mb_message_spec) : NULL;
}

static
void validate_mb_message(const fix_message* pm)
{
	ensure(pm->version == FIX_4_2);
	ensure(pm->type[0] == '0' && pm->type[1] == 0);

	const fix_group_node* const node = get_fix_message_root_node(pm);

	ensure(node != nullptr);
	ensure(get_fix_node_size(node) == 5);
	ensure_tag(node, 49, "A");
	ensure_tag(node, 56, "B");
	ensure_tag(node, 34, "12");
	ensure_tag_as_utc_timestamp(node, 52, "20100304-07:59:30.000");
	ensure_tag(node, 355, "XYZ");
	ensure(!get_fix_tag(node, 354));
}

static
void test_binary_tag()
{
	std::string msg(m, sizeof(m) - 1);

	msg += "354=3\x01" "355=XYZ\x01";
	msg = make_fix_message(msg.c_str());

	fix_parser* const parser = create_fix_parser(mb_message_classifier);
	const fix_message* const pm = get_first_fix_message(parser, msg.c_str(), msg.size());

	ensure(pm);
	validate_mb_message(pm);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// speed test
static
void speed_test()
{
	test_for_speed("Simple message", simple_message_classifier, copy_simple_message, validate_simple_message);
}

// batch
void all_simple_tests()
{
	basic_test();
	splitter_test();
	invalid_message_test();
	invalid_message_test2();
	test_binary_tag();
	speed_test();
}
<commit_msg>Minor test improvement and trailing whitespace removal.<commit_after>/*
Copyright (c) 2013, 2014, 2015, Maxim Konakov
 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 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 "test_messages.h"
#include <string.h>
#include <stdexcept>

// FIX message for tests
static
void validate_message(const struct fix_message* pm)
{
	const fix_parser* const parser = (const fix_parser*) ((const char*)pm - offsetof(fix_parser, message));

	ensure(!pm->error);
	ensure_buffer(parser->buffer);
	validate_simple_message(pm);
}

static
void basic_test()
{
	fix_parser* parser = create_fix_parser(get_dummy_classifier);
	const fix_message* pm = get_first_fix_message(parser, simple_message, simple_message_size);

	ensure(pm != nullptr);
	ensure(!get_fix_parser_error(parser));

	validate_message(pm);

	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

static
void splitter_test()
{
	std::string s(copy_simple_message(4));
	fix_parser* parser = create_fix_parser(get_dummy_classifier);

	ensure(parser != nullptr);

	const size_t n = 100;
	size_t counter = 0;
	const char* p = s.c_str();
	const char* const end = p + s.size();

	for(; p < end; p += n)
	{
		for(const fix_message* pm = get_first_fix_message(parser, p, std::min(n, (size_t)(end - p))); pm; pm = get_next_fix_message(parser))
		{
			validate_message(pm);
			++counter;
		}

		ensure(!get_fix_parser_error(parser));
	}

	free_fix_parser(parser);
	ensure(counter == 4);
}

static
void invalid_message_test()
{
	const char m[] = "8=FIX.4.4\x01" "9=122\x01" "35=D\x02";

	fix_parser* parser = create_fix_parser(get_dummy_classifier);
	const fix_message* pm = get_first_fix_message(parser, m, sizeof(m) - 1);

	ensure(!pm);
	ensure(strcmp(get_fix_parser_error(parser), "Unexpected byte 0x2 in FIX message") == 0);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// message to play with
const char m[] = "8=FIX.4.2\x01" "9=42\x01" "35=0\x01" "49=A\x01" "56=B\x01" "34=12\x01" "52=20100304-07:59:30\x01";

MESSAGE(m_message_spec)
	VALID_TAGS(m_message_spec)
		TAG(49)
		TAG(56)
		TAG(34)
		TAG(52)
	END_VALID_TAGS

	NO_DATA_TAGS(m_message_spec)
	NO_GROUPS(m_message_spec)
END_NODE(m_message_spec);

static
const struct fix_tag_classifier* m_message_classifier(fix_message_version version, const char* msg_type)
{
	return (version == FIX_4_2 && msg_type[0] == '0' && msg_type[1] == 0) ? PARSER_TABLE_ADDRESS(m_message_spec) : NULL;
}

static
void validate_m_message(const fix_message* pm)
{
	ensure(pm->version == FIX_4_2);
	ensure(pm->type[0] == '0' && pm->type[1] == 0);

	const fix_group_node* const node = get_fix_message_root_node(pm);

	ensure(node != nullptr);
	ensure(get_fix_node_size(node) == 4);
	ensure_tag(node, 49, "A");
	ensure_tag(node, 56, "B");
	ensure_tag(node, 34, "12");
	ensure_tag_as_utc_timestamp(node, 52, "20100304-07:59:30.000");
}

// test driver
static
void test_for_error(void (*modifier)(std::string&), void (*validator)(const fix_message*))
{
	std::string msg(m, sizeof(m) - 1);

	if(modifier)
		modifier(msg);

	msg = make_fix_message(msg.c_str());

	fix_parser* const parser = create_fix_parser(m_message_classifier);
	const fix_message* const pm = get_first_fix_message(parser, msg.c_str(), msg.size());

	ensure(pm);
	validator(pm);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// unexpected tag in message body
static
void unexpected_tag_modifier(std::string& msg)
{
	msg[msg.find("56=")] = '7';
}

static
void unexpected_tag_validator(const fix_message* pm)
{
	ensure(strcmp(pm->error, "FIX message (version 'FIX.4.2', type '0') error: Unexpected tag 76") == 0);
}

// duplicate tag in message body
static
void duplicate_tag_modifier(std::string& msg)
{
	msg.append("56=B\x01");
}

static
void duplicate_tag_validator(const fix_message* pm)
{
	ensure(strcmp(pm->error, "FIX message (version 'FIX.4.2', type '0') error: Duplicate tag 56 in a message node") == 0);
}

static
void invalid_message_test2()
{
	test_for_error(nullptr, validate_m_message);
	test_for_error(unexpected_tag_modifier, unexpected_tag_validator);
	test_for_error(duplicate_tag_modifier, duplicate_tag_validator);
}

// binary tag test
MESSAGE(mb_message_spec)
	VALID_TAGS(mb_message_spec)
		TAG(49)
		TAG(56)
		TAG(34)
		TAG(52)
		TAG(354)
		TAG(355)
	END_VALID_TAGS

	DATA_TAGS(mb_message_spec)
		DATA_TAG(354, 355)
	END_DATA_TAGS

	NO_GROUPS(mb_message_spec)
END_NODE(mb_message_spec);

static
const struct fix_tag_classifier* mb_message_classifier(fix_message_version version, const char* msg_type)
{
	return (version == FIX_4_2 && msg_type[0] == '0' && msg_type[1] == 0) ? PARSER_TABLE_ADDRESS(mb_message_spec) : NULL;
}

static
void validate_mb_message(const fix_message* pm)
{
	ensure(pm->version == FIX_4_2);
	ensure(pm->type[0] == '0' && pm->type[1] == 0);

	const fix_group_node* const node = get_fix_message_root_node(pm);

	ensure(node != nullptr);
	ensure(get_fix_node_size(node) == 5);
	ensure_tag(node, 49, "A");
	ensure_tag(node, 56, "B");
	ensure_tag(node, 34, "12");
	ensure_tag_as_utc_timestamp(node, 52, "20100304-07:59:30.000");
	ensure_tag(node, 355, "XYZ");
	ensure(!get_fix_tag(node, 354));
}

static
void test_binary_tag()
{
	std::string msg(m, sizeof(m) - 1);

	msg += "354=3\x01" "355=XYZ\x01";
	msg = make_fix_message(msg.c_str());

	fix_parser* const parser = create_fix_parser(mb_message_classifier);
	const fix_message* const pm = get_first_fix_message(parser, msg.c_str(), msg.size());

	ensure(pm);
	validate_mb_message(pm);
	ensure(!get_next_fix_message(parser));
	free_fix_parser(parser);
}

// speed test
static
void speed_test()
{
	test_for_speed("Simple message", simple_message_classifier, copy_simple_message, validate_simple_message);
}

// batch
void all_simple_tests()
{
	basic_test();
	splitter_test();
	invalid_message_test();
	invalid_message_test2();
	test_binary_tag();
	speed_test();
}
<|endoftext|>


<commit_before>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  libtest
 *
 *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 3 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
 */

#pragma once

#include <cerrno>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <syslog.h>

#define UTIL_MAX_ERROR_SIZE 2048

namespace datadifferential {
namespace util {

/** Verbosity levels.
 */
enum verbose_t
{
  // Logging this will cause shutdown
  VERBOSE_FATAL= LOG_EMERG, // syslog:LOG_EMERG

  VERBOSE_ALERT= LOG_ALERT, // syslog:LOG_ALERT
  VERBOSE_CRITICAL= LOG_CRIT, //  syslog:LOG_CRIT

  VERBOSE_ERROR= LOG_ERR, // syslog:LOG_ERR

  VERBOSE_WARN= LOG_WARNING, // syslog:LOG_WARNING

  VERBOSE_NOTICE= LOG_NOTICE, // syslog:LOG_NOTICE

  VERBOSE_INFO= LOG_INFO, // syslog:LOG_INFO

  VERBOSE_DEBUG= LOG_DEBUG // syslog:LOG_DEBUG
};

struct log_info_st
{
  std::string name;
  std::string filename;
  int fd;
  bool opt_syslog;
  bool opt_file;
  bool init_success;

  log_info_st(const std::string& name_arg, const std::string &filename_arg, bool syslog_arg) :
    name(name_arg),
    filename(filename_arg),
    fd(-1),
    opt_syslog(syslog_arg),
    opt_file(false),
    init_success(false)
  {
    if (opt_syslog)
    {
      openlog(name.c_str(), LOG_PID | LOG_NDELAY, LOG_USER);
    }

    init();
  }

  void init()
  {
    if (filename.size())
    {
      if (filename.compare("stderr") == 0)
      {
        fd= STDERR_FILENO;
      }
      else
      {
        fd= open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644);
        if (fd == -1)
        {
          if (opt_syslog)
          {
            char buffer[1024];
            (void)getcwd(buffer, sizeof(buffer));
            syslog(LOG_ERR, "Could not open log file \"%.*s\", from \"%s\", open failed with (%s)",
                   int(filename.size()), filename.c_str(),
                   buffer,
                   strerror(errno));
          }
          std::cerr << "Could not open log file for writing, switching to stderr." << std::endl;

          fd= STDERR_FILENO;
        }
      }

      opt_file= true;
    }

    init_success= true;
  }

  bool initialized() const
  {
    return init_success;
  }

  int file() const
  {
    return fd;
  }

  void write(verbose_t verbose, const char *mesg)
  {
    if (opt_file)
    {
      char buffer[UTIL_MAX_ERROR_SIZE];
      int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %s\n", verbose_name(verbose), mesg);
      if (::write(file(), buffer, buffer_length) == -1)
      {
        std::cerr << "Could not write to log file." << std::endl;
        syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno));
      }

    }

    if (opt_syslog)
    {
      syslog(int(verbose), "%7s %s", verbose_name(verbose), mesg);
    }
  }

  ~log_info_st()
  {
    if (fd != -1 and fd != STDERR_FILENO)
    {
      close(fd);
    }

    if (opt_syslog)
    {
      closelog();
    }
  }

private:
  const char *verbose_name(verbose_t verbose)
  {
    switch (verbose)
    {
    case VERBOSE_FATAL:
      return "FATAL";

    case VERBOSE_ALERT:
      return "ALERT";

    case VERBOSE_CRITICAL:
      return "CRITICAL";

    case VERBOSE_ERROR:
      return "ERROR";

    case VERBOSE_WARN:
      return "WARNING";

    case VERBOSE_NOTICE:
      return "NOTICE";

    case VERBOSE_INFO:
      return "INFO";

    case VERBOSE_DEBUG:
      return "DEBUG";

    default:
      break;
    }

    return "UNKNOWN";
  }
};

} // namespace util
} // namespace datadifferential
<commit_msg>Fix for Ubuntu.<commit_after>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  libtest
 *
 *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 3 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
 */

#pragma once

#include <cerrno>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <syslog.h>

#define UTIL_MAX_ERROR_SIZE 2048

namespace datadifferential {
namespace util {

/** Verbosity levels.
 */
enum verbose_t
{
  // Logging this will cause shutdown
  VERBOSE_FATAL= LOG_EMERG, // syslog:LOG_EMERG

  VERBOSE_ALERT= LOG_ALERT, // syslog:LOG_ALERT
  VERBOSE_CRITICAL= LOG_CRIT, //  syslog:LOG_CRIT

  VERBOSE_ERROR= LOG_ERR, // syslog:LOG_ERR

  VERBOSE_WARN= LOG_WARNING, // syslog:LOG_WARNING

  VERBOSE_NOTICE= LOG_NOTICE, // syslog:LOG_NOTICE

  VERBOSE_INFO= LOG_INFO, // syslog:LOG_INFO

  VERBOSE_DEBUG= LOG_DEBUG // syslog:LOG_DEBUG
};

struct log_info_st
{
  std::string name;
  std::string filename;
  int fd;
  bool opt_syslog;
  bool opt_file;
  bool init_success;

  log_info_st(const std::string& name_arg, const std::string &filename_arg, bool syslog_arg) :
    name(name_arg),
    filename(filename_arg),
    fd(-1),
    opt_syslog(syslog_arg),
    opt_file(false),
    init_success(false)
  {
    if (opt_syslog)
    {
      openlog(name.c_str(), LOG_PID | LOG_NDELAY, LOG_USER);
    }

    init();
  }

  void init()
  {
    if (filename.size())
    {
      if (filename.compare("stderr") == 0)
      {
        fd= STDERR_FILENO;
      }
      else
      {
        fd= open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644);
        if (fd == -1)
        {
          if (opt_syslog)
          {
            char buffer[1024];
            char *getcwd_ret= getcwd(buffer, sizeof(buffer));
            syslog(LOG_ERR, "Could not open log file \"%.*s\", from \"%s\", open failed with (%s)",
                   int(filename.size()), filename.c_str(),
                   getcwd_ret,
                   strerror(errno));
          }
          std::cerr << "Could not open log file for writing, switching to stderr." << std::endl;

          fd= STDERR_FILENO;
        }
      }

      opt_file= true;
    }

    init_success= true;
  }

  bool initialized() const
  {
    return init_success;
  }

  int file() const
  {
    return fd;
  }

  void write(verbose_t verbose, const char *mesg)
  {
    if (opt_file)
    {
      char buffer[UTIL_MAX_ERROR_SIZE];
      int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %s\n", verbose_name(verbose), mesg);
      if (::write(file(), buffer, buffer_length) == -1)
      {
        std::cerr << "Could not write to log file." << std::endl;
        syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno));
      }

    }

    if (opt_syslog)
    {
      syslog(int(verbose), "%7s %s", verbose_name(verbose), mesg);
    }
  }

  ~log_info_st()
  {
    if (fd != -1 and fd != STDERR_FILENO)
    {
      close(fd);
    }

    if (opt_syslog)
    {
      closelog();
    }
  }

private:
  const char *verbose_name(verbose_t verbose)
  {
    switch (verbose)
    {
    case VERBOSE_FATAL:
      return "FATAL";

    case VERBOSE_ALERT:
      return "ALERT";

    case VERBOSE_CRITICAL:
      return "CRITICAL";

    case VERBOSE_ERROR:
      return "ERROR";

    case VERBOSE_WARN:
      return "WARNING";

    case VERBOSE_NOTICE:
      return "NOTICE";

    case VERBOSE_INFO:
      return "INFO";

    case VERBOSE_DEBUG:
      return "DEBUG";

    default:
      break;
    }

    return "UNKNOWN";
  }
};

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


<commit_before>/******************************************************************************
 *  Copyright (c) 2014 Jamis Hoo
 *  Distributed under the MIT license
 *  (See accompanying file LICENSE or copy at http://opensource.org/licenses/MIT)
 *
 *  Project:
 *  Filename: sqlfile_test.cc
 *  Version: 1.0
 *  Author: Jamis Hoo
 *  E-mail: hjm211324@gmail.com
 *  Date: Dec. 09, 2014
 *  Time: 21:43:46
 *  Description:
 *****************************************************************************/
#include <iostream>
#include <regex>
#include "../src/db_query.h"
#include "../src/db_interface.h"

int main() {
    using namespace Database;

    DBQuery query;
    DBInterface ui;

    std::string str;
    std::clog << "yoursql> " << std::flush;
    while (std::getline(std::cin, str)) {
        ui.feed(str + '\n');
        while (ui.ready())
            query.execute(ui.get());
        if (ui.emptyBuff())
            std::clog << "yoursql> " << std::flush;
        else
            std::clog << "       > " << std::flush;
    }
    std::clog << std::endl;

}
<commit_msg>stdin mode and file mode<commit_after>/******************************************************************************
 *  Copyright (c) 2014 Jamis Hoo
 *  Distributed under the MIT license
 *  (See accompanying file LICENSE or copy at http://opensource.org/licenses/MIT)
 *
 *  Project:
 *  Filename: sqlfile_test.cc
 *  Version: 1.0
 *  Author: Jamis Hoo
 *  E-mail: hjm211324@gmail.com
 *  Date: Dec. 09, 2014
 *  Time: 21:43:46
 *  Description:
 *****************************************************************************/
#include <iostream>
#include <fstream>
#include <regex>
#include "../src/db_query.h"
#include "../src/db_interface.h"

int main(int argc, char** argv) {
    using namespace Database;

    // argc == 1, stdin
    // argc == 2, read from file
    if (argc > 2) return 1;

    DBQuery query;
    DBInterface ui;

    std::ifstream fin;
    // open file
    if (argc == 2)
        fin.open(argv[1]);

    // if stdin mode, output prompt
    if (argc == 1) std::clog << "yoursql> " << std::flush;

    std::string str;
    while (std::getline(argc == 1? std::cin: fin, str)) {
        // read a line
        ui.feed(str + '\n');

        // fetch commands and execute
        while (ui.ready()) query.execute(ui.get());

        // if stdin mode, output prompt
        if (argc == 1) {
            if (ui.emptyBuff()) std::clog << "yoursql> " << std::flush;
            else std::clog << "       > " << std::flush;
        }
    }
    if (argc == 1) std::clog << std::endl;

}
<|endoftext|>


<commit_before>/*
 *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "./psnr.h"  // NOLINT

#ifdef _OPENMP
#include <omp.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>  // For __cpuid()
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef unsigned int uint32;  // NOLINT
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
#else  // COMPILER_MSVC
#if defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
typedef unsigned long uint64;  // NOLINT
#else  // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
typedef unsigned long long uint64;  // NOLINT
#endif  // __LP64__
#endif  // _MSC_VER

// libyuv provides this function when linking library for jpeg support.
#if !defined(HAVE_JPEG)

#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \
    !defined(__aarch64__)
#define HAS_SUMSQUAREERROR_NEON
static uint32 SumSquareError_NEON(const uint8* src_a,
                                  const uint8* src_b, int count) {
  volatile uint32 sse;
  asm volatile (
    "vmov.u8    q7, #0                         \n"
    "vmov.u8    q9, #0                         \n"
    "vmov.u8    q8, #0                         \n"
    "vmov.u8    q10, #0                        \n"

  "1:                                          \n"
    "vld1.u8    {q0}, [%0]!                    \n"
    "vld1.u8    {q1}, [%1]!                    \n"
    "vsubl.u8   q2, d0, d2                     \n"
    "vsubl.u8   q3, d1, d3                     \n"
    "vmlal.s16  q7, d4, d4                     \n"
    "vmlal.s16  q8, d6, d6                     \n"
    "vmlal.s16  q8, d5, d5                     \n"
    "vmlal.s16  q10, d7, d7                    \n"
    "subs       %2, %2, #16                    \n"
    "bhi        1b                             \n"

    "vadd.u32   q7, q7, q8                     \n"
    "vadd.u32   q9, q9, q10                    \n"
    "vadd.u32   q10, q7, q9                    \n"
    "vpaddl.u32 q1, q10                        \n"
    "vadd.u64   d0, d2, d3                     \n"
    "vmov.32    %3, d0[0]                      \n"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "memory", "cc", "q0", "q1", "q2", "q3", "q7", "q8", "q9", "q10");
  return sse;
}
#elif !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
#define HAS_SUMSQUAREERROR_NEON
static uint32 SumSquareError_NEON(const uint8* src_a,
                                  const uint8* src_b, int count) {
  volatile uint32 sse;
  asm volatile (
    "eor        v16.16b, v16.16b, v16.16b      \n"
    "eor        v18.16b, v18.16b, v18.16b      \n"
    "eor        v17.16b, v17.16b, v17.16b      \n"
    "eor        v19.16b, v19.16b, v19.16b      \n"

  "1:                                          \n"
    "ld1        {v0.16b}, [%0], #16            \n"
    "ld1        {v1.16b}, [%1], #16            \n"
    "subs       %2, %2, #16                    \n"
    "usubl      v2.8h, v0.8b, v1.8b            \n"
    "usubl2     v3.8h, v0.16b, v1.16b          \n"
    "smlal      v16.4s, v2.4h, v2.4h           \n"
    "smlal      v17.4s, v3.4h, v3.4h           \n"
    "smlal2     v18.4s, v2.8h, v2.8h           \n"
    "smlal2     v19.4s, v3.8h, v3.8h           \n"
    "b.gt       1b                             \n"

    "add        v16.4s, v16.4s, v17.4s         \n"
    "add        v18.4s, v18.4s, v19.4s         \n"
    "add        v19.4s, v16.4s, v18.4s         \n"
    "addv       s0, v19.4s                     \n"
    "fmov       %w3, s0                        \n"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19");
  return sse;
}
#elif !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER)
#define HAS_SUMSQUAREERROR_SSE2
__declspec(naked)
static uint32 SumSquareError_SSE2(const uint8* /*src_a*/,
                                  const uint8* /*src_b*/, int /*count*/) {
  __asm {
    mov        eax, [esp + 4]    // src_a
    mov        edx, [esp + 8]    // src_b
    mov        ecx, [esp + 12]   // count
    pxor       xmm0, xmm0
    pxor       xmm5, xmm5
    sub        edx, eax

  wloop:
    movdqu     xmm1, [eax]
    movdqu     xmm2, [eax + edx]
    lea        eax,  [eax + 16]
    movdqu     xmm3, xmm1
    psubusb    xmm1, xmm2
    psubusb    xmm2, xmm3
    por        xmm1, xmm2
    movdqu     xmm2, xmm1
    punpcklbw  xmm1, xmm5
    punpckhbw  xmm2, xmm5
    pmaddwd    xmm1, xmm1
    pmaddwd    xmm2, xmm2
    paddd      xmm0, xmm1
    paddd      xmm0, xmm2
    sub        ecx, 16
    ja         wloop

    pshufd     xmm1, xmm0, 0EEh
    paddd      xmm0, xmm1
    pshufd     xmm1, xmm0, 01h
    paddd      xmm0, xmm1
    movd       eax, xmm0
    ret
  }
}
#elif !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
#define HAS_SUMSQUAREERROR_SSE2
static uint32 SumSquareError_SSE2(const uint8* src_a,
                                  const uint8* src_b, int count) {
  uint32 sse;
  asm volatile (  // NOLINT
    "pxor      %%xmm0,%%xmm0                   \n"
    "pxor      %%xmm5,%%xmm5                   \n"
    "sub       %0,%1                           \n"

  "1:                                          \n"
    "movdqu    (%0),%%xmm1                     \n"
    "movdqu    (%0,%1,1),%%xmm2                \n"
    "lea       0x10(%0),%0                     \n"
    "movdqu    %%xmm1,%%xmm3                   \n"
    "psubusb   %%xmm2,%%xmm1                   \n"
    "psubusb   %%xmm3,%%xmm2                   \n"
    "por       %%xmm2,%%xmm1                   \n"
    "movdqu    %%xmm1,%%xmm2                   \n"
    "punpcklbw %%xmm5,%%xmm1                   \n"
    "punpckhbw %%xmm5,%%xmm2                   \n"
    "pmaddwd   %%xmm1,%%xmm1                   \n"
    "pmaddwd   %%xmm2,%%xmm2                   \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "paddd     %%xmm2,%%xmm0                   \n"
    "sub       $0x10,%2                        \n"
    "ja        1b                              \n"

    "pshufd    $0xee,%%xmm0,%%xmm1             \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "pshufd    $0x1,%%xmm0,%%xmm1              \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "movd      %%xmm0,%3                       \n"

  : "+r"(src_a),      // %0
    "+r"(src_b),      // %1
    "+r"(count),      // %2
    "=g"(sse)         // %3
  :
  : "memory", "cc"
#if defined(__SSE2__)
    , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"
#endif
  );  // NOLINT
  return sse;
}
#endif  // LIBYUV_DISABLE_X86 etc

#if defined(HAS_SUMSQUAREERROR_SSE2)
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
static __inline void __cpuid(int cpu_info[4], int info_type) {
  asm volatile (  // NOLINT
    "mov %%ebx, %%edi                          \n"
    "cpuid                                     \n"
    "xchg %%edi, %%ebx                         \n"
    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
    : "a"(info_type));
}
// For gcc/clang but not clangcl.
#elif (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
static __inline void __cpuid(int cpu_info[4], int info_type) {
  asm volatile (  // NOLINT
    "cpuid                                     \n"
    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
    : "a"(info_type));
}
#endif

static int CpuHasSSE2() {
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)
  int cpu_info[4];
  __cpuid(cpu_info, 1);
  if (cpu_info[3] & 0x04000000) {
    return 1;
  }
#endif
  return 0;
}
#endif  // HAS_SUMSQUAREERROR_SSE2

static uint32 SumSquareError_C(const uint8* src_a,
                               const uint8* src_b, int count) {
  uint32 sse = 0u;
  for (int x = 0; x < count; ++x) {
    int diff = src_a[x] - src_b[x];
    sse += static_cast<uint32>(diff * diff);
  }
  return sse;
}

double ComputeSumSquareError(const uint8* src_a,
                             const uint8* src_b, int count) {
  uint32 (*SumSquareError)(const uint8* src_a,
                           const uint8* src_b, int count) = SumSquareError_C;
#if defined(HAS_SUMSQUAREERROR_NEON)
  SumSquareError = SumSquareError_NEON;
#endif
#if defined(HAS_SUMSQUAREERROR_SSE2)
  if (CpuHasSSE2()) {
    SumSquareError = SumSquareError_SSE2;
  }
#endif
  const int kBlockSize = 1 << 15;
  uint64 sse = 0;
#ifdef _OPENMP
#pragma omp parallel for reduction(+: sse)
#endif
  for (int i = 0; i < (count - (kBlockSize - 1)); i += kBlockSize) {
    sse += SumSquareError(src_a + i, src_b + i, kBlockSize);
  }
  src_a += count & ~(kBlockSize - 1);
  src_b += count & ~(kBlockSize - 1);
  int remainder = count & (kBlockSize - 1) & ~15;
  if (remainder) {
    sse += SumSquareError(src_a, src_b, remainder);
    src_a += remainder;
    src_b += remainder;
  }
  remainder = count & 15;
  if (remainder) {
    sse += SumSquareError_C(src_a, src_b, remainder);
  }
  return static_cast<double>(sse);
}
#endif

// PSNR formula: psnr = 10 * log10 (Peak Signal^2 * size / sse)
// Returns 128.0 (kMaxPSNR) if sse is 0 (perfect match).
double ComputePSNR(double sse, double size) {
  const double kMINSSE = 255.0 * 255.0 * size / pow(10.0, kMaxPSNR / 10.0);
  if (sse <= kMINSSE)
    sse = kMINSSE;  // Produces max PSNR of 128
  return 10.0 * log10(255.0 * 255.0 * size / sse);
}

#ifdef __cplusplus
}  // extern "C"
#endif
<commit_msg>psnr tool, work around for ios 64 bit compiler where int passed into assembly needs to be explicitely cast to 'w' register. BUG=437 TESTED=untested R=bcornell@google.com<commit_after>/*
 *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "./psnr.h"  // NOLINT

#ifdef _OPENMP
#include <omp.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>  // For __cpuid()
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef unsigned int uint32;  // NOLINT
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
#else  // COMPILER_MSVC
#if defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
typedef unsigned long uint64;  // NOLINT
#else  // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
typedef unsigned long long uint64;  // NOLINT
#endif  // __LP64__
#endif  // _MSC_VER

// libyuv provides this function when linking library for jpeg support.
#if !defined(HAVE_JPEG)

#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \
    !defined(__aarch64__)
#define HAS_SUMSQUAREERROR_NEON
static uint32 SumSquareError_NEON(const uint8* src_a,
                                  const uint8* src_b, int count) {
  volatile uint32 sse;
  asm volatile (
    "vmov.u8    q7, #0                         \n"
    "vmov.u8    q9, #0                         \n"
    "vmov.u8    q8, #0                         \n"
    "vmov.u8    q10, #0                        \n"

  "1:                                          \n"
    "vld1.u8    {q0}, [%0]!                    \n"
    "vld1.u8    {q1}, [%1]!                    \n"
    "vsubl.u8   q2, d0, d2                     \n"
    "vsubl.u8   q3, d1, d3                     \n"
    "vmlal.s16  q7, d4, d4                     \n"
    "vmlal.s16  q8, d6, d6                     \n"
    "vmlal.s16  q8, d5, d5                     \n"
    "vmlal.s16  q10, d7, d7                    \n"
    "subs       %2, %2, #16                    \n"
    "bhi        1b                             \n"

    "vadd.u32   q7, q7, q8                     \n"
    "vadd.u32   q9, q9, q10                    \n"
    "vadd.u32   q10, q7, q9                    \n"
    "vpaddl.u32 q1, q10                        \n"
    "vadd.u64   d0, d2, d3                     \n"
    "vmov.32    %3, d0[0]                      \n"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "memory", "cc", "q0", "q1", "q2", "q3", "q7", "q8", "q9", "q10");
  return sse;
}
#elif !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
#define HAS_SUMSQUAREERROR_NEON
static uint32 SumSquareError_NEON(const uint8* src_a,
                                  const uint8* src_b, int count) {
  volatile uint32 sse;
  asm volatile (
    "eor        v16.16b, v16.16b, v16.16b      \n"
    "eor        v18.16b, v18.16b, v18.16b      \n"
    "eor        v17.16b, v17.16b, v17.16b      \n"
    "eor        v19.16b, v19.16b, v19.16b      \n"

  "1:                                          \n"
    "ld1        {v0.16b}, [%0], #16            \n"
    "ld1        {v1.16b}, [%1], #16            \n"
    "subs       %w2, %w2, #16                  \n"
    "usubl      v2.8h, v0.8b, v1.8b            \n"
    "usubl2     v3.8h, v0.16b, v1.16b          \n"
    "smlal      v16.4s, v2.4h, v2.4h           \n"
    "smlal      v17.4s, v3.4h, v3.4h           \n"
    "smlal2     v18.4s, v2.8h, v2.8h           \n"
    "smlal2     v19.4s, v3.8h, v3.8h           \n"
    "b.gt       1b                             \n"

    "add        v16.4s, v16.4s, v17.4s         \n"
    "add        v18.4s, v18.4s, v19.4s         \n"
    "add        v19.4s, v16.4s, v18.4s         \n"
    "addv       s0, v19.4s                     \n"
    "fmov       %w3, s0                        \n"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19");
  return sse;
}
#elif !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER)
#define HAS_SUMSQUAREERROR_SSE2
__declspec(naked)
static uint32 SumSquareError_SSE2(const uint8* /*src_a*/,
                                  const uint8* /*src_b*/, int /*count*/) {
  __asm {
    mov        eax, [esp + 4]    // src_a
    mov        edx, [esp + 8]    // src_b
    mov        ecx, [esp + 12]   // count
    pxor       xmm0, xmm0
    pxor       xmm5, xmm5
    sub        edx, eax

  wloop:
    movdqu     xmm1, [eax]
    movdqu     xmm2, [eax + edx]
    lea        eax,  [eax + 16]
    movdqu     xmm3, xmm1
    psubusb    xmm1, xmm2
    psubusb    xmm2, xmm3
    por        xmm1, xmm2
    movdqu     xmm2, xmm1
    punpcklbw  xmm1, xmm5
    punpckhbw  xmm2, xmm5
    pmaddwd    xmm1, xmm1
    pmaddwd    xmm2, xmm2
    paddd      xmm0, xmm1
    paddd      xmm0, xmm2
    sub        ecx, 16
    ja         wloop

    pshufd     xmm1, xmm0, 0EEh
    paddd      xmm0, xmm1
    pshufd     xmm1, xmm0, 01h
    paddd      xmm0, xmm1
    movd       eax, xmm0
    ret
  }
}
#elif !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
#define HAS_SUMSQUAREERROR_SSE2
static uint32 SumSquareError_SSE2(const uint8* src_a,
                                  const uint8* src_b, int count) {
  uint32 sse;
  asm volatile (  // NOLINT
    "pxor      %%xmm0,%%xmm0                   \n"
    "pxor      %%xmm5,%%xmm5                   \n"
    "sub       %0,%1                           \n"

  "1:                                          \n"
    "movdqu    (%0),%%xmm1                     \n"
    "movdqu    (%0,%1,1),%%xmm2                \n"
    "lea       0x10(%0),%0                     \n"
    "movdqu    %%xmm1,%%xmm3                   \n"
    "psubusb   %%xmm2,%%xmm1                   \n"
    "psubusb   %%xmm3,%%xmm2                   \n"
    "por       %%xmm2,%%xmm1                   \n"
    "movdqu    %%xmm1,%%xmm2                   \n"
    "punpcklbw %%xmm5,%%xmm1                   \n"
    "punpckhbw %%xmm5,%%xmm2                   \n"
    "pmaddwd   %%xmm1,%%xmm1                   \n"
    "pmaddwd   %%xmm2,%%xmm2                   \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "paddd     %%xmm2,%%xmm0                   \n"
    "sub       $0x10,%2                        \n"
    "ja        1b                              \n"

    "pshufd    $0xee,%%xmm0,%%xmm1             \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "pshufd    $0x1,%%xmm0,%%xmm1              \n"
    "paddd     %%xmm1,%%xmm0                   \n"
    "movd      %%xmm0,%3                       \n"

  : "+r"(src_a),      // %0
    "+r"(src_b),      // %1
    "+r"(count),      // %2
    "=g"(sse)         // %3
  :
  : "memory", "cc"
#if defined(__SSE2__)
    , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"
#endif
  );  // NOLINT
  return sse;
}
#endif  // LIBYUV_DISABLE_X86 etc

#if defined(HAS_SUMSQUAREERROR_SSE2)
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
static __inline void __cpuid(int cpu_info[4], int info_type) {
  asm volatile (  // NOLINT
    "mov %%ebx, %%edi                          \n"
    "cpuid                                     \n"
    "xchg %%edi, %%ebx                         \n"
    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
    : "a"(info_type));
}
// For gcc/clang but not clangcl.
#elif (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
static __inline void __cpuid(int cpu_info[4], int info_type) {
  asm volatile (  // NOLINT
    "cpuid                                     \n"
    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
    : "a"(info_type));
}
#endif

static int CpuHasSSE2() {
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)
  int cpu_info[4];
  __cpuid(cpu_info, 1);
  if (cpu_info[3] & 0x04000000) {
    return 1;
  }
#endif
  return 0;
}
#endif  // HAS_SUMSQUAREERROR_SSE2

static uint32 SumSquareError_C(const uint8* src_a,
                               const uint8* src_b, int count) {
  uint32 sse = 0u;
  for (int x = 0; x < count; ++x) {
    int diff = src_a[x] - src_b[x];
    sse += static_cast<uint32>(diff * diff);
  }
  return sse;
}

double ComputeSumSquareError(const uint8* src_a,
                             const uint8* src_b, int count) {
  uint32 (*SumSquareError)(const uint8* src_a,
                           const uint8* src_b, int count) = SumSquareError_C;
#if defined(HAS_SUMSQUAREERROR_NEON)
  SumSquareError = SumSquareError_NEON;
#endif
#if defined(HAS_SUMSQUAREERROR_SSE2)
  if (CpuHasSSE2()) {
    SumSquareError = SumSquareError_SSE2;
  }
#endif
  const int kBlockSize = 1 << 15;
  uint64 sse = 0;
#ifdef _OPENMP
#pragma omp parallel for reduction(+: sse)
#endif
  for (int i = 0; i < (count - (kBlockSize - 1)); i += kBlockSize) {
    sse += SumSquareError(src_a + i, src_b + i, kBlockSize);
  }
  src_a += count & ~(kBlockSize - 1);
  src_b += count & ~(kBlockSize - 1);
  int remainder = count & (kBlockSize - 1) & ~15;
  if (remainder) {
    sse += SumSquareError(src_a, src_b, remainder);
    src_a += remainder;
    src_b += remainder;
  }
  remainder = count & 15;
  if (remainder) {
    sse += SumSquareError_C(src_a, src_b, remainder);
  }
  return static_cast<double>(sse);
}
#endif

// PSNR formula: psnr = 10 * log10 (Peak Signal^2 * size / sse)
// Returns 128.0 (kMaxPSNR) if sse is 0 (perfect match).
double ComputePSNR(double sse, double size) {
  const double kMINSSE = 255.0 * 255.0 * size / pow(10.0, kMaxPSNR / 10.0);
  if (sse <= kMINSSE)
    sse = kMINSSE;  // Produces max PSNR of 128
  return 10.0 * log10(255.0 * 255.0 * size / sse);
}

#ifdef __cplusplus
}  // extern "C"
#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <net/tcp.hpp>
#include <vector>
#include <info>

using namespace net;
using namespace std::chrono; // For timers and MSL
using Connection_ptr = std::shared_ptr<TCP::Connection>;
std::unique_ptr<Inet4<VirtioNet>> inet;
std::shared_ptr<TCP::Connection> client;

/*
	TEST VARIABLES
*/
TCP::Port
	TEST1{8081}, TEST2{8082}, TEST3{8083}, TEST4{8084}, TEST5{8085};

using HostAddress = std::pair<std::string, TCP::Port>;
HostAddress
	TEST_ADDR_TIME{"india.colorado.edu", 13};

std::string
	small, big, huge;

int
	S{150}, B{1500}, H{15000};

std::string
	TEST_STR {"1337"};

size_t bufstore_capacity{0};

// Default MSL is 30s. Timeout 2*MSL.
// To reduce test duration, lower MSL to 5s.
milliseconds MSL_TEST = 5s;

/*
	TEST: Release of resources/clean up.
*/
void FINISH_TEST() {
	INFO("TEST", "Started 3 x MSL timeout.");
	hw::PIT::instance().onTimeout(3 * MSL_TEST, [] {
		INFO("TEST", "Verify release of resources");
		CHECK(inet->tcp().activeConnections() == 0, "tcp.activeConnections() == 0");
		CHECK(inet->available_capacity() == bufstore_capacity,
			"inet.available_capacity() == bufstore_capacity");
		printf("# TEST DONE #\n");
	});
}

/*
	TEST: Outgoing Internet Connection
*/
void OUTGOING_TEST_INTERNET(const HostAddress& address) {
	auto port = address.second;
	INFO("TEST", "Outgoing Internet Connection (%s:%u)", address.first.c_str(), address.second);
	inet->resolve(address.first, [port](auto&, auto&, auto ip_address) {
		CHECK(ip_address != 0, "Resolved host");

		if(ip_address != 0) {
			inet->tcp().connect(ip_address, port)
			->onConnect([](Connection_ptr) {
				CHECK(true, "Connected");
			})
			.onReceive([](Connection_ptr conn, bool) {
				CHECK(true, "Received data: %s", conn->read().c_str());
			})
			.onError([](Connection_ptr, TCP::TCPException err) {
				CHECK(false, "Error occured: %s", err.what());
			});
		}
	});
}

/*
	TEST: Outgoing Connection to Host
*/
void OUTGOING_TEST(TCP::Socket outgoing) {
	INFO("TEST", "Outgoing Connection (%s)", outgoing.to_string().c_str());
	inet->tcp().connect(outgoing)
		->onConnect([](Connection_ptr conn) {
			conn->write(small);
		})
		.onReceive([](Connection_ptr conn, bool) {
			CHECK(conn->read() == small, "conn->read() == small");
		})
		.onDisconnect([](Connection_ptr, std::string) {
			CHECK(true, "Connection closed by server");

			OUTGOING_TEST_INTERNET(TEST_ADDR_TIME);
		});
}

// Used to send big data
struct Buffer {
	size_t written, read;
	char* data;
	const size_t size;

	Buffer(size_t length) :
		written(0), read(0), data(new char[length]), size(length) {}

	~Buffer() { delete[] data; }

	std::string str() { return {data, size};}
};

void Service::start()
{
	for(int i = 0; i < S; i++) small += TEST_STR;
	for(int i = 0; i < B; i++) big += TEST_STR;
	for(int i = 0; i < H; i++) huge += TEST_STR;

	hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();
  inet = std::make_unique<Inet4<VirtioNet>>(eth0);

  inet->network_config( {{ 10,0,0,42 }},      // IP
			{{ 255,255,255,0 }},  // Netmask
			{{ 10,0,0,1 }},       // Gateway
			{{ 8,8,8,8 }} );      // DNS

 	bufstore_capacity = inet->available_capacity();
 	auto& tcp = inet->tcp();
 	// this is default
 	tcp.set_buffer_limit(10);
 	// reduce test duration
 	tcp.set_MSL(MSL_TEST);

	/*
		TEST: Send and receive small string.
	*/
	INFO("TEST", "Listeners and connections allocation.");

	/*
		TEST: Nothing should be allocated.
	*/
	CHECK(tcp.openPorts() == 0, "tcp.openPorts() == 0");
	CHECK(tcp.activeConnections() == 0, "tcp.activeConnections() == 0");

	tcp.bind(TEST1).onConnect([](Connection_ptr conn) {
		INFO("TEST", "SMALL string");
		conn->onReceive([](Connection_ptr conn, bool) {
			CHECK(conn->read() == small, "conn.read() == small");
			conn->close();
		});
		conn->write(small);
	});

	/*
		TEST: Server should be bound.
	*/
	CHECK(tcp.openPorts() == 1, "tcp.openPorts() == 1");

	/*
		TEST: Send and receive big string.
	*/
	tcp.bind(TEST2).onConnect([](Connection_ptr conn) {
		INFO("TEST", "BIG string");
		auto response = std::make_shared<std::string>();
		conn->onReceive([response](Connection_ptr conn, bool) {
			*response += conn->read();
			if(response->size() == big.size()) {
				bool OK = (*response == big);
				CHECK(OK, "conn.read() == big");
				conn->close();
			}
		});
		conn->write(big);
	});

	/*
		TEST: Send and receive huge string.
	*/
	tcp.bind(TEST3).onConnect([](Connection_ptr conn) {
		INFO("TEST", "HUGE string");
		auto buffer = std::make_shared<Buffer>(huge.size());
		conn->onReceive([buffer](Connection_ptr conn, bool) {
			// if not all expected data is read
			if(buffer->read < huge.size())
				buffer->read += conn->read(buffer->data+buffer->read, conn->receive_buffer().data_size());
			// if not all expected data is written
			if(buffer->written < huge.size()) {
				buffer->written += conn->write(huge.data()+buffer->written, huge.size() - buffer->written);
			}
			// when all expected data is read
			if(buffer->read == huge.size()) {
				bool OK = (buffer->str() == huge);
				CHECK(OK, "conn.read() == huge");
				conn->close();
			}
		});
		buffer->written += conn->write(huge.data(), huge.size());
	});

	/*
		TEST: More servers should be bound.
	*/
	CHECK(tcp.openPorts() == 3, "tcp.openPorts() == 3");

	/*
		TEST: Connection (Status etc.) and Active Close
	*/
	tcp.bind(TEST4).onConnect([](Connection_ptr conn) {
		INFO("TEST","Connection");
		// There should be at least one connection.
		CHECK(inet->tcp().activeConnections() > 0, "tcp.activeConnections() > 0");
		// Test if connected.
		CHECK(conn->is_connected(), "conn.is_connected()");
		// Test if writable.
		CHECK(conn->is_writable(), "conn.is_writable()");
		// Test if state is ESTABLISHED.
		CHECK(conn->is_state({"ESTABLISHED"}), "conn.is_state(ESTABLISHED)");

		INFO("TEST", "Active close");
		// Test for active close.
		conn->close();
		CHECK(!conn->is_writable(), "!conn->is_writable()");
		CHECK(conn->is_state({"FIN-WAIT-1"}), "conn.is_state(FIN-WAIT-1)");
	})
	.onDisconnect([](Connection_ptr conn, std::string) {
		CHECK(conn->is_state({"FIN-WAIT-2"}), "conn.is_state(FIN-WAIT-2)");
		hw::PIT::instance().onTimeout(1s,[conn]{
			CHECK(conn->is_state({"TIME-WAIT"}), "conn.is_state(TIME-WAIT)");

			OUTGOING_TEST({inet->router(), TEST5});
		});

		hw::PIT::instance().onTimeout(5s, [] { FINISH_TEST(); });
	});

}
<commit_msg>test: tcp - verbose string length<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <net/tcp.hpp>
#include <vector>
#include <info>

using namespace net;
using namespace std::chrono; // For timers and MSL
using Connection_ptr = std::shared_ptr<TCP::Connection>;
std::unique_ptr<Inet4<VirtioNet>> inet;
std::shared_ptr<TCP::Connection> client;

/*
	TEST VARIABLES
*/
TCP::Port
	TEST1{8081}, TEST2{8082}, TEST3{8083}, TEST4{8084}, TEST5{8085};

using HostAddress = std::pair<std::string, TCP::Port>;
HostAddress
	TEST_ADDR_TIME{"india.colorado.edu", 13};

std::string
	small, big, huge;

int
	S{150}, B{1500}, H{15000};

std::string
	TEST_STR {"1337"};

size_t bufstore_capacity{0};

// Default MSL is 30s. Timeout 2*MSL.
// To reduce test duration, lower MSL to 5s.
milliseconds MSL_TEST = 5s;

/*
	TEST: Release of resources/clean up.
*/
void FINISH_TEST() {
	INFO("TEST", "Started 3 x MSL timeout.");
	hw::PIT::instance().onTimeout(3 * MSL_TEST, [] {
		INFO("TEST", "Verify release of resources");
		CHECK(inet->tcp().activeConnections() == 0, "tcp.activeConnections() == 0");
		CHECK(inet->available_capacity() == bufstore_capacity,
			"inet.available_capacity() == bufstore_capacity");
		printf("# TEST DONE #\n");
	});
}

/*
	TEST: Outgoing Internet Connection
*/
void OUTGOING_TEST_INTERNET(const HostAddress& address) {
	auto port = address.second;
	INFO("TEST", "Outgoing Internet Connection (%s:%u)", address.first.c_str(), address.second);
	inet->resolve(address.first, [port](auto&, auto&, auto ip_address) {
		CHECK(ip_address != 0, "Resolved host");

		if(ip_address != 0) {
			inet->tcp().connect(ip_address, port)
			->onConnect([](Connection_ptr) {
				CHECK(true, "Connected");
			})
			.onReceive([](Connection_ptr conn, bool) {
				CHECK(true, "Received data: %s", conn->read().c_str());
			})
			.onError([](Connection_ptr, TCP::TCPException err) {
				CHECK(false, "Error occured: %s", err.what());
			});
		}
	});
}

/*
	TEST: Outgoing Connection to Host
*/
void OUTGOING_TEST(TCP::Socket outgoing) {
	INFO("TEST", "Outgoing Connection (%s)", outgoing.to_string().c_str());
	inet->tcp().connect(outgoing)
		->onConnect([](Connection_ptr conn) {
			conn->write(small);
		})
		.onReceive([](Connection_ptr conn, bool) {
			CHECK(conn->read() == small, "conn->read() == small");
		})
		.onDisconnect([](Connection_ptr, std::string) {
			CHECK(true, "Connection closed by server");

			OUTGOING_TEST_INTERNET(TEST_ADDR_TIME);
		});
}

// Used to send big data
struct Buffer {
	size_t written, read;
	char* data;
	const size_t size;

	Buffer(size_t length) :
		written(0), read(0), data(new char[length]), size(length) {}

	~Buffer() { delete[] data; }

	std::string str() { return {data, size};}
};

void Service::start()
{
	for(int i = 0; i < S; i++) small += TEST_STR;
	for(int i = 0; i < B; i++) big += TEST_STR;
	for(int i = 0; i < H; i++) huge += TEST_STR;

	hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();
  inet = std::make_unique<Inet4<VirtioNet>>(eth0);

  inet->network_config( {{ 10,0,0,42 }},      // IP
			{{ 255,255,255,0 }},  // Netmask
			{{ 10,0,0,1 }},       // Gateway
			{{ 8,8,8,8 }} );      // DNS

 	bufstore_capacity = inet->available_capacity();
 	auto& tcp = inet->tcp();
 	// this is default
 	tcp.set_buffer_limit(10);
 	// reduce test duration
 	tcp.set_MSL(MSL_TEST);

	/*
		TEST: Send and receive small string.
	*/
	INFO("TEST", "Listeners and connections allocation.");

	/*
		TEST: Nothing should be allocated.
	*/
	CHECK(tcp.openPorts() == 0, "tcp.openPorts() == 0");
	CHECK(tcp.activeConnections() == 0, "tcp.activeConnections() == 0");

	tcp.bind(TEST1).onConnect([](Connection_ptr conn) {
		INFO("TEST", "SMALL string (%u)", small.size());
		conn->onReceive([](Connection_ptr conn, bool) {
			CHECK(conn->read() == small, "conn.read() == small");
			conn->close();
		});
		conn->write(small);
	});

	/*
		TEST: Server should be bound.
	*/
	CHECK(tcp.openPorts() == 1, "tcp.openPorts() == 1");

	/*
		TEST: Send and receive big string.
	*/
	tcp.bind(TEST2).onConnect([](Connection_ptr conn) {
		INFO("TEST", "BIG string (%u)", big.size());
		auto response = std::make_shared<std::string>();
		conn->onReceive([response](Connection_ptr conn, bool) {
			*response += conn->read();
			if(response->size() == big.size()) {
				bool OK = (*response == big);
				CHECK(OK, "conn.read() == big");
				conn->close();
			}
		});
		conn->write(big);
	});

	/*
		TEST: Send and receive huge string.
	*/
	tcp.bind(TEST3).onConnect([](Connection_ptr conn) {
		INFO("TEST", "HUGE string (%u)", huge.size());
		auto buffer = std::make_shared<Buffer>(huge.size());
		conn->onReceive([buffer](Connection_ptr conn, bool) {
			// if not all expected data is read
			if(buffer->read < huge.size())
				buffer->read += conn->read(buffer->data+buffer->read, conn->receive_buffer().data_size());
			// if not all expected data is written
			if(buffer->written < huge.size()) {
				buffer->written += conn->write(huge.data()+buffer->written, huge.size() - buffer->written);
			}
			// when all expected data is read
			if(buffer->read == huge.size()) {
				bool OK = (buffer->str() == huge);
				CHECK(OK, "conn.read() == huge");
				conn->close();
			}
		});
		buffer->written += conn->write(huge.data(), huge.size());
	});

	/*
		TEST: More servers should be bound.
	*/
	CHECK(tcp.openPorts() == 3, "tcp.openPorts() == 3");

	/*
		TEST: Connection (Status etc.) and Active Close
	*/
	tcp.bind(TEST4).onConnect([](Connection_ptr conn) {
		INFO("TEST","Connection");
		// There should be at least one connection.
		CHECK(inet->tcp().activeConnections() > 0, "tcp.activeConnections() > 0");
		// Test if connected.
		CHECK(conn->is_connected(), "conn.is_connected()");
		// Test if writable.
		CHECK(conn->is_writable(), "conn.is_writable()");
		// Test if state is ESTABLISHED.
		CHECK(conn->is_state({"ESTABLISHED"}), "conn.is_state(ESTABLISHED)");

		INFO("TEST", "Active close");
		// Test for active close.
		conn->close();
		CHECK(!conn->is_writable(), "!conn->is_writable()");
		CHECK(conn->is_state({"FIN-WAIT-1"}), "conn.is_state(FIN-WAIT-1)");
	})
	.onDisconnect([](Connection_ptr conn, std::string) {
		CHECK(conn->is_state({"FIN-WAIT-2"}), "conn.is_state(FIN-WAIT-2)");
		hw::PIT::instance().onTimeout(1s,[conn]{
			CHECK(conn->is_state({"TIME-WAIT"}), "conn.is_state(TIME-WAIT)");

			OUTGOING_TEST({inet->router(), TEST5});
		});

		hw::PIT::instance().onTimeout(5s, [] { FINISH_TEST(); });
	});

}
<|endoftext|>


<commit_before>#include "utils.hpp"
#include <cstring>
#include <boost/filesystem.hpp>

namespace bf = boost::filesystem;

static std::string makepath(bf::path, RdbAttrs);
// Get the key for the given path.
static bool getkey(bf::path, std::string&);
static bf::path keyfile(const std::string&);
static void touch(bf::path);

std::string pathfor(const char *root, RdbAttrs keys) {
	bool used[keys.size()];
	memset(used, 0, sizeof(*used) * keys.size());

	bf::path path(root);
	std::string curkey;
	while (keys.size() > 0) {
		if (bf::exists(path)) {
			if (!bf::is_directory(path))
				fatal("%s is not a directory\n", path.string().c_str());
			if (!getkey(path, curkey))
				return makepath(path.string().c_str(), keys);
			path /= keys[curkey];
			keys.erase(curkey);
		} else {
			return makepath(path.string().c_str(), keys);
		}
	}

	return path.string();
}

static std::string makepath(bf::path root, RdbAttrs keys) {
	while (keys.size() > 0) {
		if (!bf::exists(root) && keys.size() > 1)
			bf::create_directory(root);

		const std::string &key = keys.begin()->first;
		const std::string &vl = keys.begin()->second;
		touch(root / keyfile(key));

		bf::create_directory(vl);
		root /= vl;
	}

	return root.string();
}

static bool getkey(bf::path p, std::string &key) {
	for (bf::directory_iterator it(p); it != bf::directory_iterator(); it++) {
		const char *fname = it->string().c_str();
		if (strstr(fname, "KEY=") == fname) {
			key = fname + strlen("KEY=");
			return true;
		}
	}
	return false;
}

static bf::path keyfile(const std::string &key) {
	return bf::path(std::string("KEY=") + key);
}

static void touch(bf::path p) {
	FILE *touch = fopen(p.string().c_str(), "w");
	if (!touch)
		fatalx(errno, "Failed to touch keyfile %s\n", p.string().c_str());
	fclose(touch);
}<commit_msg>rdb: make some value parameters reference parameters instead.<commit_after>#include "utils.hpp"
#include <cstring>
#include <boost/filesystem.hpp>

namespace bf = boost::filesystem;

static std::string makepath(bf::path, RdbAttrs);
// Get the key for the given path.
static bool getkey(const bf::path&, std::string&);
static bf::path keyfile(const std::string&);
static void touch(const bf::path&);

std::string pathfor(const char *root, RdbAttrs keys) {
	bool used[keys.size()];
	memset(used, 0, sizeof(*used) * keys.size());

	bf::path path(root);
	std::string curkey;
	while (keys.size() > 0) {
		if (bf::exists(path)) {
			if (!bf::is_directory(path))
				fatal("%s is not a directory\n", path.string().c_str());
			if (!getkey(path, curkey))
				return makepath(path.string().c_str(), keys);
			path /= keys[curkey];
			keys.erase(curkey);
		} else {
			return makepath(path.string().c_str(), keys);
		}
	}

	return path.string();
}

static std::string makepath(bf::path root, RdbAttrs keys) {
	while (keys.size() > 0) {
		if (!bf::exists(root) && keys.size() > 1)
			bf::create_directory(root);

		const std::string &key = keys.begin()->first;
		const std::string &vl = keys.begin()->second;
		touch(root / keyfile(key));

		bf::create_directory(vl);
		root /= vl;
	}

	return root.string();
}

static bool getkey(const bf::path &p, std::string &key) {
	for (bf::directory_iterator it(p); it != bf::directory_iterator(); it++) {
		const char *fname = it->string().c_str();
		if (strstr(fname, "KEY=") == fname) {
			key = fname + strlen("KEY=");
			return true;
		}
	}
	return false;
}

static bf::path keyfile(const std::string &key) {
	return bf::path(std::string("KEY=") + key);
}

static void touch(const bf::path &p) {
	FILE *touch = fopen(p.string().c_str(), "w");
	if (!touch)
		fatalx(errno, "Failed to touch keyfile %s\n", p.string().c_str());
	fclose(touch);
}<|endoftext|>


<commit_before>/**
 * File: /testUtility.cpp
 * Project: test
 * Created Date: Wednesday, October 18th 2017, 8:15:32 am
 * Author: Harikrishnan
 */

#include "Utility.h"
#include "catch.hpp"

#include <emmintrin.h>
#include <thread>
#include <memory>

using namespace SmallAlloc;

TEST_CASE("Freelist Test", "[utility]")
{
	struct FLNode : public FreeList::Node
	{
		long val;

		FLNode() : val(0)
		{}

		FLNode(long v) : val(v)
		{}
	};

	FreeList fl;

	FLNode n1{1};
	FLNode n2{2};
	FLNode n3{3};

	fl.push(&n1);
	fl.push(&n2);
	fl.push(&n3);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(fl.empty() == false);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);

	fl.push(&n3);
	fl.push(&n2);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 1);
	REQUIRE(fl.empty() == true);

	FLNode n4{4};
	FLNode n5{5};

	fl.push(&n4);
	fl.push(&n5);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 5);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 4);
	REQUIRE(fl.empty() == true);
}

TEST_CASE("List Test", "[utility]")
{
	struct ListNode : public List::Node
	{
		long val;

		ListNode() : val(0)
		{}

		ListNode(long v) : val(v)
		{}
	};

	List list;

	ListNode n1{1};
	ListNode n2{2};
	ListNode n3{3};

	list.push_front(&n1);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 1);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 1);

	list.push_front(&n2);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 1);

	list.push_back(&n3);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 3);
	REQUIRE(list.empty() == false);

	REQUIRE(static_cast<ListNode *>(list.pop_front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.pop_back())->val == 3);
	REQUIRE(static_cast<ListNode *>(list.pop_back())->val == 1);
	REQUIRE(list.empty() == true);

	ListNode n4{4};
	ListNode n5{5};

	list.push_back(&n4);
	list.push_back(&n5);
	list.move_front(&n5);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 5);
	list.move_front(&n4);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 4);
	list.move_back(&n4);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 4);
	list.move_back(&n5);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 5);
}

TEST_CASE("Forward List Test", "[utility]")
{
	struct ListNode : public ForwardList::Node
	{
		long val;

		ListNode() : val(0)
		{}

		ListNode(long v) : val(v)
		{}
	};

	ForwardList list;

	ListNode n1{1};
	ListNode n2{2};
	ListNode n3{3};

	list.push(&n1);
	list.push(&n2);
	list.push(&n3);
	REQUIRE(!list.empty());

	REQUIRE(static_cast<ListNode *>(list.pop())->val == 3);
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 1);
	REQUIRE(list.empty());

	ListNode n4{4};
	ListNode n5{5};

	list.push(&n4);
	list.push(&n5);
	REQUIRE(!list.empty());
	list.remove(&n4);
	REQUIRE(!list.empty());
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 5);
	REQUIRE(list.empty());
}

TEST_CASE("FreelistAtomic Test", "[utility]")
{
	using namespace SmallAlloc;

	struct FLNode : public FreeListAtomic::Node
	{
		long val;

		FLNode() : val(0)
		{}

		FLNode(long v) : val(v)
		{}
	};

	FreeListAtomic fl;

	FLNode n1{1};
	FLNode n2{2};
	FLNode n3{3};

	fl.push(&n1);
	fl.push(&n2);
	fl.push(&n3);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(fl.empty() == false);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);

	fl.push(&n3);
	fl.push(&n2);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 1);
	REQUIRE(fl.empty() == true);

	FLNode n4{4};
	FLNode n5{5};

	fl.push(&n4);
	fl.push(&n5);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 5);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 4);
	REQUIRE(fl.empty() == true);

	constexpr int MAX_THREADS = 8;
	std::vector<std::thread> workers;
	std::atomic_bool quit(0);
	uint64_t popcount = 0;
	uint32_t node_count = 600 * 1000;
	uint64_t expected_popcount = uint64_t{node_count} * (MAX_THREADS - 1);

	std::unique_ptr<std::vector<FLNode>[]> node_vectors = std::make_unique<std::vector<FLNode>[]>
														  (MAX_THREADS - 1);

	auto thread_safety_test_pusher = [&](std::vector<FLNode>& nodes)
	{
		for (FLNode &node : nodes)
			fl.push(&node);
	};

	auto thread_safety_test_popper = [&]()
	{
		popcount = 0;

		while (!quit.load())
		{
			if (fl.pop())
			{
				popcount++;
			}
			else
			{
				for (int i = 0; i < 100; i++)
					_mm_pause();
			}
		}

		while (fl.pop())
			popcount++;
	};

	for (int i = 0; i < MAX_THREADS - 1; i++)
	{
		auto &nodes = node_vectors[i];
		nodes.reserve(node_count);

		for (uint32_t j = 0; j < node_count; j++)
			nodes.push_back(FLNode(j * long(i)));
	}

	for (int i = 0; i < MAX_THREADS; i++)
	{
		if (i == MAX_THREADS - 1)
		{
			workers.push_back(std::thread(thread_safety_test_popper));
		}
		else
		{
			workers.push_back(std::thread(thread_safety_test_pusher, std::ref(node_vectors[i])));
		}
	}

	for (int i = 0; i < MAX_THREADS - 1; i++)
		workers[i].join();

	quit.store(true);
	workers[MAX_THREADS - 1].join();

	REQUIRE(popcount == expected_popcount);
}
<commit_msg>Modify FreelistAtomic Test node_count to 100K<commit_after>/**
 * File: /testUtility.cpp
 * Project: test
 * Created Date: Wednesday, October 18th 2017, 8:15:32 am
 * Author: Harikrishnan
 */

#include "Utility.h"
#include "catch.hpp"

#include <emmintrin.h>
#include <thread>
#include <memory>

using namespace SmallAlloc;

TEST_CASE("Freelist Test", "[utility]")
{
	struct FLNode : public FreeList::Node
	{
		long val;

		FLNode() : val(0)
		{}

		FLNode(long v) : val(v)
		{}
	};

	FreeList fl;

	FLNode n1{1};
	FLNode n2{2};
	FLNode n3{3};

	fl.push(&n1);
	fl.push(&n2);
	fl.push(&n3);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(fl.empty() == false);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);

	fl.push(&n3);
	fl.push(&n2);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 1);
	REQUIRE(fl.empty() == true);

	FLNode n4{4};
	FLNode n5{5};

	fl.push(&n4);
	fl.push(&n5);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 5);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 4);
	REQUIRE(fl.empty() == true);
}

TEST_CASE("List Test", "[utility]")
{
	struct ListNode : public List::Node
	{
		long val;

		ListNode() : val(0)
		{}

		ListNode(long v) : val(v)
		{}
	};

	List list;

	ListNode n1{1};
	ListNode n2{2};
	ListNode n3{3};

	list.push_front(&n1);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 1);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 1);

	list.push_front(&n2);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 1);

	list.push_back(&n3);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 3);
	REQUIRE(list.empty() == false);

	REQUIRE(static_cast<ListNode *>(list.pop_front())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.pop_back())->val == 3);
	REQUIRE(static_cast<ListNode *>(list.pop_back())->val == 1);
	REQUIRE(list.empty() == true);

	ListNode n4{4};
	ListNode n5{5};

	list.push_back(&n4);
	list.push_back(&n5);
	list.move_front(&n5);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 5);
	list.move_front(&n4);
	REQUIRE(static_cast<ListNode *>(list.front())->val == 4);
	list.move_back(&n4);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 4);
	list.move_back(&n5);
	REQUIRE(static_cast<ListNode *>(list.back())->val == 5);
}

TEST_CASE("Forward List Test", "[utility]")
{
	struct ListNode : public ForwardList::Node
	{
		long val;

		ListNode() : val(0)
		{}

		ListNode(long v) : val(v)
		{}
	};

	ForwardList list;

	ListNode n1{1};
	ListNode n2{2};
	ListNode n3{3};

	list.push(&n1);
	list.push(&n2);
	list.push(&n3);
	REQUIRE(!list.empty());

	REQUIRE(static_cast<ListNode *>(list.pop())->val == 3);
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 2);
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 1);
	REQUIRE(list.empty());

	ListNode n4{4};
	ListNode n5{5};

	list.push(&n4);
	list.push(&n5);
	REQUIRE(!list.empty());
	list.remove(&n4);
	REQUIRE(!list.empty());
	REQUIRE(static_cast<ListNode *>(list.pop())->val == 5);
	REQUIRE(list.empty());
}

TEST_CASE("FreelistAtomic Test", "[utility]")
{
	using namespace SmallAlloc;

	struct FLNode : public FreeListAtomic::Node
	{
		long val;

		FLNode() : val(0)
		{}

		FLNode(long v) : val(v)
		{}
	};

	FreeListAtomic fl;

	FLNode n1{1};
	FLNode n2{2};
	FLNode n3{3};

	fl.push(&n1);
	fl.push(&n2);
	fl.push(&n3);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(fl.empty() == false);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);

	fl.push(&n3);
	fl.push(&n2);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 2);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 3);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 1);
	REQUIRE(fl.empty() == true);

	FLNode n4{4};
	FLNode n5{5};

	fl.push(&n4);
	fl.push(&n5);

	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 5);
	REQUIRE(static_cast<FLNode *>(fl.pop())->val == 4);
	REQUIRE(fl.empty() == true);

	constexpr int MAX_THREADS = 8;
	std::vector<std::thread> workers;
	std::atomic_bool quit(0);
	uint64_t popcount = 0;
	uint32_t node_count = 100 * 1000;
	uint64_t expected_popcount = uint64_t{node_count} * (MAX_THREADS - 1);

	std::unique_ptr<std::vector<FLNode>[]> node_vectors = std::make_unique<std::vector<FLNode>[]>
														  (MAX_THREADS - 1);

	auto thread_safety_test_pusher = [&](std::vector<FLNode>& nodes)
	{
		for (FLNode &node : nodes)
			fl.push(&node);
	};

	auto thread_safety_test_popper = [&]()
	{
		popcount = 0;

		while (!quit.load())
		{
			if (fl.pop())
			{
				popcount++;
			}
			else
			{
				for (int i = 0; i < 100; i++)
					_mm_pause();
			}
		}

		while (fl.pop())
			popcount++;
	};

	for (int i = 0; i < MAX_THREADS - 1; i++)
	{
		auto &nodes = node_vectors[i];
		nodes.reserve(node_count);

		for (uint32_t j = 0; j < node_count; j++)
			nodes.push_back(FLNode(j * long(i)));
	}

	for (int i = 0; i < MAX_THREADS; i++)
	{
		if (i == MAX_THREADS - 1)
		{
			workers.push_back(std::thread(thread_safety_test_popper));
		}
		else
		{
			workers.push_back(std::thread(thread_safety_test_pusher, std::ref(node_vectors[i])));
		}
	}

	for (int i = 0; i < MAX_THREADS - 1; i++)
		workers[i].join();

	quit.store(true);
	workers[MAX_THREADS - 1].join();

	REQUIRE(popcount == expected_popcount);
}
<|endoftext|>


<commit_before>/*
	Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin
	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.
    * Neither the name of Rasterbar Software nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 <cassert>
#include <boost/timer.hpp>
#include <iostream>
#include <vector>
#include <utility>
#include <set>

#include "libtorrent/buffer.hpp"
#include "libtorrent/chained_buffer.hpp"
#include "libtorrent/socket.hpp"

#include "test.hpp"

using libtorrent::buffer;
using libtorrent::chained_buffer;

/*
template<class T>
T const& min_(T const& x, T const& y)
{
	return x < y ? x : y;
}

void test_speed()
{
	buffer b;

	char data[32];

	srand(0);

	boost::timer t;

	int const iterations = 5000000;
	int const step = iterations / 20;

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			b.insert(data, data + n);
		}
		else
		{
			b.erase(min_(b.size(), n));
		}
	}

	float t1 = t.elapsed();
	std::cerr << "buffer elapsed: " << t.elapsed() << "\n";

	std::vector<char> v;

	srand(0);
	t.restart();

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			v.insert(v.end(), data, data + n);
		}
		else
		{
			v.erase(v.begin(), v.begin() + min_(v.size(), n));
		}
	}

	float t2 = t.elapsed();
	std::cerr << "std::vector elapsed: " << t.elapsed() << "\n";

	assert(t1 < t2);
}
*/

// -- test buffer --

void test_buffer()
{
	char data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

	buffer b;

	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 0);
	TEST_CHECK(b.empty());

	b.resize(10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(b.capacity() == 10);

	std::memcpy(b.begin(), data, 10);
	b.reserve(50);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);
	TEST_CHECK(b.capacity() == 50);

	b.erase(b.begin() + 6, b.end());
	TEST_CHECK(std::memcmp(b.begin(), data, 6) == 0);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 6);

	b.insert(b.begin(), data + 5, data + 10);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 11);
	TEST_CHECK(std::memcmp(b.begin(), data + 5, 5) == 0);

	b.clear();
	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 50);

	b.insert(b.end(), data, data + 10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);

	b.erase(b.begin(), b.end());
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 0);

	buffer().swap(b);
	TEST_CHECK(b.capacity() == 0);

}

// -- test chained buffer --

std::set<char*> buffer_list;

void free_buffer(char* m)
{
	std::set<char*>::iterator i = buffer_list.find(m);
	TEST_CHECK(i != buffer_list.end());

	buffer_list.erase(i);
	std::free(m);
}

char* allocate_buffer(int size)
{
	char* mem = (char*)std::malloc(size);
	buffer_list.insert(mem);
	return mem;
}

template <class T>
int copy_buffers(T const& b, char* target)
{
	int copied = 0;
	for (typename T::const_iterator i = b.begin()
		, end(b.end()); i != end; ++i)
	{
		memcpy(target, asio::buffer_cast<char const*>(*i), asio::buffer_size(*i));
		target += asio::buffer_size(*i);
		copied += asio::buffer_size(*i);
	}
	return copied;
}

bool compare_chained_buffer(chained_buffer& b, char const* mem, int size)
{
	if (size == 0) return true;
	std::vector<char> flat(size);
	std::list<asio::const_buffer> const& iovec2 = b.build_iovec(size);
	int copied = copy_buffers(iovec2, &flat[0]);
	TEST_CHECK(copied == size);
	return std::memcmp(&flat[0], mem, size) == 0;
}

void test_chained_buffer()
{
	char data[] = "foobar";
	{
		chained_buffer b;

		TEST_CHECK(b.empty());
		TEST_CHECK(b.capacity() == 0);
		TEST_CHECK(b.size() == 0);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		TEST_CHECK(buffer_list.empty());

		char* b1 = allocate_buffer(512);
		std::memcpy(b1, data, 6);
		b.append_buffer(b1, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 1);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 6);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		b.pop_front(3);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 3);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		bool ret = b.append(data, 6);

		TEST_CHECK(ret == true);
		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 9);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 12);

		ret = b.append(data, 1024);

		TEST_CHECK(ret == false);

		char* b2 = allocate_buffer(512);
		std::memcpy(b2, data, 6);
		b.append_buffer(b2, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 2);

		char* b3 = allocate_buffer(512);
		std::memcpy(b3, data, 6);
		b.append_buffer(b3, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 3);

		TEST_CHECK(b.capacity() == 512 * 3);
		TEST_CHECK(b.size() == 21);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		TEST_CHECK(compare_chained_buffer(b, "barfoobar", 9));

		for (int i = 1; i < 21; ++i)
			TEST_CHECK(compare_chained_buffer(b, "barfoobarfoobarfoobar", i));

		b.pop_front(5 + 6);

		TEST_CHECK(buffer_list.size() == 2);
		TEST_CHECK(b.capacity() == 512 * 2);
		TEST_CHECK(b.size() == 10);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		char const* str = "obarfooba";
		TEST_CHECK(compare_chained_buffer(b, str, 9));

		for (int i = 0; i < 9; ++i)
		{
			b.pop_front(1);
			++str;
			TEST_CHECK(compare_chained_buffer(b, str, 8 - i));
			TEST_CHECK(b.size() == 9 - i);
		}

		char* b4 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		std::memcpy(b4 + 6, data, 6);
		b.append_buffer(b4, 20, 12, (void(*)(char*))&free_buffer);
		TEST_CHECK(b.space_in_last_buffer() == 8);

		ret = b.append(data, 6);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 2);
		std::cout << b.space_in_last_buffer() << std::endl;
		ret = b.append(data, 2);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		std::cout << b.space_in_last_buffer() << std::endl;

		char* b5 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		b.append_buffer(b5, 20, 6, (void(*)(char*))&free_buffer);

		b.pop_front(22);
		TEST_CHECK(b.size() == 5);
	}
	TEST_CHECK(buffer_list.empty());
}

int test_main()
{
	test_buffer();
	test_chained_buffer();
	return 0;
}

<commit_msg>boost 1.35 fix in test_buffer<commit_after>/*
	Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin
	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.
    * Neither the name of Rasterbar Software nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 <cassert>
#include <boost/timer.hpp>
#include <iostream>
#include <vector>
#include <utility>
#include <set>

#include "libtorrent/buffer.hpp"
#include "libtorrent/chained_buffer.hpp"
#include "libtorrent/socket.hpp"

#include "test.hpp"

using namespace libtorrent;

/*
template<class T>
T const& min_(T const& x, T const& y)
{
	return x < y ? x : y;
}

void test_speed()
{
	buffer b;

	char data[32];

	srand(0);

	boost::timer t;

	int const iterations = 5000000;
	int const step = iterations / 20;

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			b.insert(data, data + n);
		}
		else
		{
			b.erase(min_(b.size(), n));
		}
	}

	float t1 = t.elapsed();
	std::cerr << "buffer elapsed: " << t.elapsed() << "\n";

	std::vector<char> v;

	srand(0);
	t.restart();

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			v.insert(v.end(), data, data + n);
		}
		else
		{
			v.erase(v.begin(), v.begin() + min_(v.size(), n));
		}
	}

	float t2 = t.elapsed();
	std::cerr << "std::vector elapsed: " << t.elapsed() << "\n";

	assert(t1 < t2);
}
*/

// -- test buffer --

void test_buffer()
{
	char data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

	buffer b;

	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 0);
	TEST_CHECK(b.empty());

	b.resize(10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(b.capacity() == 10);

	std::memcpy(b.begin(), data, 10);
	b.reserve(50);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);
	TEST_CHECK(b.capacity() == 50);

	b.erase(b.begin() + 6, b.end());
	TEST_CHECK(std::memcmp(b.begin(), data, 6) == 0);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 6);

	b.insert(b.begin(), data + 5, data + 10);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 11);
	TEST_CHECK(std::memcmp(b.begin(), data + 5, 5) == 0);

	b.clear();
	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 50);

	b.insert(b.end(), data, data + 10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);

	b.erase(b.begin(), b.end());
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 0);

	buffer().swap(b);
	TEST_CHECK(b.capacity() == 0);

}

// -- test chained buffer --

std::set<char*> buffer_list;

void free_buffer(char* m)
{
	std::set<char*>::iterator i = buffer_list.find(m);
	TEST_CHECK(i != buffer_list.end());

	buffer_list.erase(i);
	std::free(m);
}

char* allocate_buffer(int size)
{
	char* mem = (char*)std::malloc(size);
	buffer_list.insert(mem);
	return mem;
}

template <class T>
int copy_buffers(T const& b, char* target)
{
	int copied = 0;
	for (typename T::const_iterator i = b.begin()
		, end(b.end()); i != end; ++i)
	{
		memcpy(target, asio::buffer_cast<char const*>(*i), asio::buffer_size(*i));
		target += asio::buffer_size(*i);
		copied += asio::buffer_size(*i);
	}
	return copied;
}

bool compare_chained_buffer(chained_buffer& b, char const* mem, int size)
{
	if (size == 0) return true;
	std::vector<char> flat(size);
	std::list<asio::const_buffer> const& iovec2 = b.build_iovec(size);
	int copied = copy_buffers(iovec2, &flat[0]);
	TEST_CHECK(copied == size);
	return std::memcmp(&flat[0], mem, size) == 0;
}

void test_chained_buffer()
{
	char data[] = "foobar";
	{
		chained_buffer b;

		TEST_CHECK(b.empty());
		TEST_CHECK(b.capacity() == 0);
		TEST_CHECK(b.size() == 0);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		TEST_CHECK(buffer_list.empty());

		char* b1 = allocate_buffer(512);
		std::memcpy(b1, data, 6);
		b.append_buffer(b1, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 1);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 6);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		b.pop_front(3);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 3);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		bool ret = b.append(data, 6);

		TEST_CHECK(ret == true);
		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 9);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 12);

		ret = b.append(data, 1024);

		TEST_CHECK(ret == false);

		char* b2 = allocate_buffer(512);
		std::memcpy(b2, data, 6);
		b.append_buffer(b2, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 2);

		char* b3 = allocate_buffer(512);
		std::memcpy(b3, data, 6);
		b.append_buffer(b3, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 3);

		TEST_CHECK(b.capacity() == 512 * 3);
		TEST_CHECK(b.size() == 21);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		TEST_CHECK(compare_chained_buffer(b, "barfoobar", 9));

		for (int i = 1; i < 21; ++i)
			TEST_CHECK(compare_chained_buffer(b, "barfoobarfoobarfoobar", i));

		b.pop_front(5 + 6);

		TEST_CHECK(buffer_list.size() == 2);
		TEST_CHECK(b.capacity() == 512 * 2);
		TEST_CHECK(b.size() == 10);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		char const* str = "obarfooba";
		TEST_CHECK(compare_chained_buffer(b, str, 9));

		for (int i = 0; i < 9; ++i)
		{
			b.pop_front(1);
			++str;
			TEST_CHECK(compare_chained_buffer(b, str, 8 - i));
			TEST_CHECK(b.size() == 9 - i);
		}

		char* b4 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		std::memcpy(b4 + 6, data, 6);
		b.append_buffer(b4, 20, 12, (void(*)(char*))&free_buffer);
		TEST_CHECK(b.space_in_last_buffer() == 8);

		ret = b.append(data, 6);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 2);
		std::cout << b.space_in_last_buffer() << std::endl;
		ret = b.append(data, 2);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		std::cout << b.space_in_last_buffer() << std::endl;

		char* b5 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		b.append_buffer(b5, 20, 6, (void(*)(char*))&free_buffer);

		b.pop_front(22);
		TEST_CHECK(b.size() == 5);
	}
	TEST_CHECK(buffer_list.empty());
}

int test_main()
{
	test_buffer();
	test_chained_buffer();
	return 0;
}

<|endoftext|>


<commit_before>#include "df_clipboard.h"

#include "df_common.h"

#ifdef _MSC_VER

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HANDLE g_clipboardData;

char *ClipboardReceiveData(int *numChars) {
    if (g_clipboardData) {
        DebugAssert("Clipboard already open");
        return NULL;
    }

    if (!OpenClipboard(NULL))
        return NULL;

    // Retrieve the Clipboard data (specifying that we want ANSI text.
    g_clipboardData = GetClipboardData(CF_TEXT);
    if (!g_clipboardData)
        return NULL;

    // Get a pointer to the data associated with the handle returned from
    // GetClipboardData.
    char *data = (char*)GlobalLock(g_clipboardData);
    *numChars = strlen(data) + 1;

    return data;
}

void ClipboardReleaseReceivedData(char const *data) {
    // Unlock the global memory.
    if (g_clipboardData)
        GlobalUnlock(g_clipboardData);

    // Close the Clipboard, which unlocks it so that other applications can
    // examine or modify its contents.
    CloseClipboard();
}

int ClipboardSetData(char const *data, int sizeData) {
    if (g_clipboardData) {
        DebugAssert("Clipboard already open");
        return 0;
    }

    if (!OpenClipboard(NULL))
        return 0;

    // Empty the Clipboard. This also has the effect of allowing Windows to
    // free the memory associated with any data that is in the Clipboard.
    EmptyClipboard();

    HGLOBAL clipboardHandle = GlobalAlloc(GMEM_DDESHARE, sizeData);

    // Calling GlobalLock returns a pointer to the data associated with the
    // handle returned from GlobalAlloc()
    char *windowsData = (char*)GlobalLock(clipboardHandle);
    if (!windowsData)
		return 0;

    // Copy the data from the local variable to the global memory.
    memcpy(windowsData, data, sizeData);

    // Unlock the memory - don't call GlobalFree because Windows will free the
    // memory automatically when EmptyClipboard is next called.
    GlobalUnlock(clipboardHandle);

    // Set the Clipboard data by specifying that ANSI text is being used and
    // passing the handle to the global memory.
    SetClipboardData(CF_TEXT, clipboardHandle);

    // Close the Clipboard which unlocks it so that other applications can
    // examine or modify its contents.
    CloseClipboard();

    return 1;
}

#else

#include <stdlib.h>

char *X11InternalClipboardRequestData();
void X11InternalClipboardReleaseReceivedData();

char *ClipboardReceiveData(int *numChars) {
    return X11InternalClipboardRequestData();
}

void ClipboardReleaseReceivedData(char const *data) {
    X11InternalClipboardReleaseReceivedData();
}

int ClipboardSetData(char const *data, int sizeData) {
    return 0;
}

#endif
<commit_msg>Fixed some bugs in the new clipboard functionality.<commit_after>#include "df_clipboard.h"

#include "df_common.h"

#ifdef _MSC_VER

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HANDLE g_clipboardData;

char *ClipboardReceiveData(int *numChars) {
    if (g_clipboardData) {
        DebugAssert("Clipboard already open");
        return NULL;
    }

    if (!OpenClipboard(NULL))
        return NULL;

    // Retrieve the Clipboard data (specifying that we want ANSI text.
    g_clipboardData = GetClipboardData(CF_TEXT);
    if (!g_clipboardData)
        return NULL;

    // Get a pointer to the data associated with the handle returned from
    // GetClipboardData.
    char *data = (char*)GlobalLock(g_clipboardData);
    *numChars = strlen(data) + 1;

    return data;
}

void ClipboardReleaseReceivedData(char const *data) {
    // Unlock the global memory.
    if (g_clipboardData)
        GlobalUnlock(g_clipboardData);
    g_clipboardData = NULL;

    // Close the Clipboard, which unlocks it so that other applications can
    // examine or modify its contents.
    CloseClipboard();
}

int ClipboardSetData(char const *data, int sizeData) {
    if (g_clipboardData) {
        DebugAssert(0); // Clipboard already open
        return 0;
    }

    if (!OpenClipboard(NULL))
        return 0;

    // Empty the Clipboard. This also has the effect of allowing Windows to
    // free the memory associated with any data that is in the Clipboard.
    EmptyClipboard();

    HGLOBAL clipboardHandle = GlobalAlloc(GMEM_DDESHARE, sizeData);

    // Calling GlobalLock returns a pointer to the data associated with the
    // handle returned from GlobalAlloc()
    char *windowsData = (char*)GlobalLock(clipboardHandle);
    if (!windowsData)
		return 0;

    // Copy the data from the local variable to the global memory.
    memcpy(windowsData, data, sizeData);

    // Unlock the memory - don't call GlobalFree because Windows will free the
    // memory automatically when EmptyClipboard is next called.
    GlobalUnlock(clipboardHandle);

    // Set the Clipboard data by specifying that ANSI text is being used and
    // passing the handle to the global memory.
    SetClipboardData(CF_TEXT, clipboardHandle);

    // Close the Clipboard which unlocks it so that other applications can
    // examine or modify its contents.
    CloseClipboard();

    return 1;
}

#else

#include <stdlib.h>

char *X11InternalClipboardRequestData();
void X11InternalClipboardReleaseReceivedData();

char *ClipboardReceiveData(int *numChars) {
    return X11InternalClipboardRequestData();
}

void ClipboardReleaseReceivedData(char const *data) {
    X11InternalClipboardReleaseReceivedData();
}

int ClipboardSetData(char const *data, int sizeData) {
    return 0;
}

#endif
<|endoftext|>


<commit_before>/*

  This software is provided under the LGPL in March 2009 by the
  Cluster Science Centre
  QSAS team,
  Imperial College, London

  Copyright (C) 2009  Imperial College, London

  This is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Lesser Public License as published
  by the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

  This software 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.

  To received a copy of the GNU Library General Public License
  write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

*/

#include "qt_PlotWindow.h"

int main(int argc, char** argv)
{
    int res;

    // Deep copy of the arguments before QApplication alters them
    int Argc=argc;
    char** Argv;

    Argv=new char*[argc];
    for(int i=0; i<Argc; ++i)
    {
        int len=strlen(argv[i])+1;
        Argv[i]=new char[len];
        strncpy(Argv[i], argv[i], len);
    }

	QApplication a( argc, argv );
	PlotWindow* win=new PlotWindow(Argc, Argv);
	a.setActiveWindow( win );
	win->setVisible(true);

	res=a.exec();

    for(int i=0; i<Argc; ++i)
    {
        delete[] Argv[i];
    }
    delete[] Argv;

    return res;
}
<commit_msg>Change so that command-line options are only interpreted by the PLplot library and completely ignored by QApplication.<commit_after>/*

  This software is provided under the LGPL in March 2009 by the
  Cluster Science Centre
  QSAS team,
  Imperial College, London

  Copyright (C) 2009  Imperial College, London

  This is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Lesser Public License as published
  by the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

  This software 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.

  To received a copy of the GNU Library General Public License
  write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

*/

#include "qt_PlotWindow.h"

int main(int argc, char** argv)
{
    int res;

    // Command-line options are only to be interpreted by PLplot.  Thus,
    // make a deep copy of the arguments for PLplot use before QApplication
    // has a chance to alter them.
    int Argc=argc;
    char** Argv;

    Argv=new char*[argc];
    for(int i=0; i<Argc; ++i)
    {
        int len=strlen(argv[i])+1;
        Argv[i]=new char[len];
        strncpy(Argv[i], argv[i], len);
    }

        // Limit QApplication's interpretation of argv to just the first
	// argument (the application name) so that all command-line
        // options such as the PLplot -bg command-line option (which would
        // generate a warning message when misinterpreted by QApplication)
        // are completely ignored.
	argc = 1;
	QApplication a( argc, argv );
	PlotWindow* win=new PlotWindow(Argc, Argv);
	a.setActiveWindow( win );
	win->setVisible(true);

	res=a.exec();

    for(int i=0; i<Argc; ++i)
    {
        delete[] Argv[i];
    }
    delete[] Argv;

    return res;
}
<|endoftext|>