<commit_before>#include <clog/clog.h>
#include <nomagic.h>
#include <functional>
#include <stdexcept>
#include <string>
#include <type_traits>

#include "macros.h"

namespace {

using nomagic::loc;
using nomagic::Test;

using clogcmn::Content;

class Spy {
public:
	static Content* last() {
		return p;
	}

	static void out(const Content& content) {
		if (q == 0)
			q = new Content(content.message);
		p = q;
		*p = content;
	}

	static void reset() {
		p = 0;
	}

private:
	static Content* p;
	static Content* q;
};

Content* Spy::p(0);
Content* Spy::q(0);

namespace nspy {

void t1(const char* ms)
{
	Test t(ms);
	t.a(Spy::last() == 0, L);
}

void test_out(Test& t, const char* m)
{
	Content c(m);
	Spy::out(c);
	Content* r(Spy::last());
	t.a(r != 0, L);
	t.a(r->message == m, L);
}

void t2(const char* ms)
{
	Test t(ms);
	test_out(t, "a message 1");
	Spy::reset();
	test_out(t, "a message 2");
}

void t3(const char* ms)
{
	Test t(ms);
	Content c("a message");
	Spy::out(c);
	Spy::reset();
	Content* r(Spy::last());
	t.a(r == 0, L);
}

} // nspy

namespace nlog {

class F {
public:
	F() {
		clog::outfn = Spy::out;
	}
};

namespace nf {

bool called;

class A {
public:
	A() : v(0) {
	}

	A(const A& op)
		:	v(op.v) {
		copied = true;
	}

	int v;
	static bool copied;
};
bool A::copied;

A a;
A arg;

void reset()
{
	called = false;
	a = A();
	a.v = 1;
	arg = A();
	A::copied = false;
}

struct E {
};

} // nf

void f1()
{
	nf::called = true;
}

namespace d {

using std::enable_if;
using std::is_void;

template<class T>
struct enable_void : enable_if<is_void<T>::value> {
};

template<class T>
struct disable_void : enable_if<!is_void<T>::value> {
};

} // d

class Test_common {
public:
	Test_common(const char* ms)
		:	t(ms) {
	}

	void operator()() {
		F f;
		m = "message";
		nf::reset();
		prepare_call();
		call_and_assert();
		verify();
	}
protected:
	virtual void call_and_assert() = 0;
	virtual void prepare_call() {
	}
	virtual void verify() = 0;

	Test t;
	const char* m;
};

template<class F>
class Test_0 : public Test_common {
public:
	Test_0(F f, const char* ms)
		:	Test_common(ms), f(f) {
	}
protected:
	void call_and_assert() {
		call<decltype(clog::out(m, f))>();
	}
	void verify() {
		t.a(Spy::last()->message == m, L);
		t.a(nf::called, L);
	}

	F f;
private:
	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f);
	}
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f) == 1, L);
	}
};

template<class F>
inline Test_0<F> test_0(F f, const char* ms)
{
	return Test_0<F>(f, ms);
}

void t1(const char* ms)
{
	(test_0(f1, ms))();
}

void f2(int a)
{
	nf::called = true;
	nf::arg.v = a;
}

template<class F>
class Test_1 : public Test_common {
public:
	Test_1(F f, const char* ms) : Test_common(ms), f(f) {
	}

protected:
	void verify() {
		t.a(Spy::last()->message == m, L);
		t.a(nf::called, L);
		t.a(nf::arg.v == nf::a.v, L);
		t.a(nf::A::copied == false, L);
	}

	F f;
};

template<class F>
class Test_1v : public Test_1<F> {
public:
	Test_1v(F f, const char* ms) : Test_1<F>(f, ms) {
	}

protected:
	using Test_1<F>::m;
	using Test_1<F>::t;
	using Test_1<F>::f;

	void call_and_assert() {
		call<decltype(clog::out(m, f, nf::a.v))>();
	}
	void prepare_call() {
		nf::a.v = 2;
	}
private:
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f, nf::a.v) == 1, L);
	}

	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f, nf::a.v);
	}
};

template<class F>
inline Test_1v<F> test_1v(F f, const char* ms)
{
	return Test_1v<F>(f, ms);
}

void t2(const char* ms)
{
	(test_1v(f2, ms))();
}

void f3(nf::A& a)
{
	nf::called = true;
	nf::arg = a;
}

void f3c(const nf::A& a)
{
	nf::called = true;
	nf::arg = a;
}

template<class F>
class Test_1r : public Test_1<F> {
public:
	Test_1r(F f, const char* ms) : Test_1<F>(f, ms) {
	}

protected:
	using Test_1<F>::m;
	using Test_1<F>::t;
	using Test_1<F>::f;

	void call_and_assert() {
		call<decltype(clog::out(m, f, nf::a))>();
	}
private:
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f, nf::a) == 1, L);
	}

	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f, nf::a);
	}
};

template<class F>
inline Test_1r<F> test_1r(F f, const char* ms)
{
	return Test_1r<F>(f, ms);
}

void t3(const char* ms)
{
	(test_1r(f3, ms))();
}

int f1_1r(nf::A& a)
{
	nf::called = true;
	nf::arg = a;
	return 1;
}

int f1_1rc(const nf::A& a)
{
	nf::called = true;
	nf::arg = a;
	return 1;
}

void t8(const char* ms)
{
	(test_1r(f1_1r, ms))();
}

void t9(const char* ms)
{
	(test_1r(f1_1rc, ms))();
}

void t4(const char* ms)
{
	(test_1r(f3c, ms))();
}

int f1_0()
{
	nf::called = true;
	return 1;
}

void t5(const char* ms)
{
	(test_0(f1_0, ms))();
}

int f1_1(int v)
{
	nf::called = true;
	nf::arg.v = v;
	return 1;
}

void t6(const char* ms)
{
	(test_1v(f1_1, ms))();
}

void f0e()
{
	throw nf::E();
}

void t7(const char* ms)
{
	Test t(ms);
	F f;
	const char* m("message");
	nf::reset();
	try {
		clog::out(m, f0e);
		throw std::logic_error("test");
	}
	catch (const nf::E&) {
	}
	t.a(Spy::last()->message == m, L);
	t.a(Spy::last()->exception, L);
}

} // nlog

using nomagic::run;

void spy_tests()
{
	using namespace nspy;

	run(	"Spy returns null when it is asked to "
		"provide the last log output but there is not.", t1);

	run("Spy returns the last log object", t2);

	run("Spy resets the last log", t3);
}

void log_tests()
{
	using namespace nlog;

	run("return(void), arg(0)", t1);
	run("return(void), arg(1)", t2);
	run("return(void), arg(1, ref)", t3);
	run("return(void), arg(1, cref)", t4);
	run("return(int), arg(0)", t5);
	run("return(int), arg(1)", t6);
	run("return(int), arg(1, ref)", t8);
	run("return(int), arg(1, cref)", t9);
	run("return(void), arg(0), exception", t7);
}

} // unnamed

#include "test.h"

namespace test {

void run_clog_tests()
{
	spy_tests();
	log_tests();
}

} // test

<commit_msg>This commit changes function names slightly.<commit_after>#include <clog/clog.h>
#include <nomagic.h>
#include <functional>
#include <stdexcept>
#include <string>
#include <type_traits>

#include "macros.h"

namespace {

using nomagic::loc;
using nomagic::Test;

using clogcmn::Content;

class Spy {
public:
	static Content* last() {
		return p;
	}

	static void out(const Content& content) {
		if (q == 0)
			q = new Content(content.message);
		p = q;
		*p = content;
	}

	static void reset() {
		p = 0;
	}

private:
	static Content* p;
	static Content* q;
};

Content* Spy::p(0);
Content* Spy::q(0);

namespace nspy {

void t1(const char* ms)
{
	Test t(ms);
	t.a(Spy::last() == 0, L);
}

void test_out(Test& t, const char* m)
{
	Content c(m);
	Spy::out(c);
	Content* r(Spy::last());
	t.a(r != 0, L);
	t.a(r->message == m, L);
}

void t2(const char* ms)
{
	Test t(ms);
	test_out(t, "a message 1");
	Spy::reset();
	test_out(t, "a message 2");
}

void t3(const char* ms)
{
	Test t(ms);
	Content c("a message");
	Spy::out(c);
	Spy::reset();
	Content* r(Spy::last());
	t.a(r == 0, L);
}

} // nspy

namespace nlog {

class F {
public:
	F() {
		clog::outfn = Spy::out;
	}
};

namespace nf {

bool called;

class A {
public:
	A() : v(0) {
	}

	A(const A& op)
		:	v(op.v) {
		copied = true;
	}

	int v;
	static bool copied;
};
bool A::copied;

A a;
A arg;

void reset()
{
	called = false;
	a = A();
	a.v = 1;
	arg = A();
	A::copied = false;
}

struct E {
};

} // nf

void f1()
{
	nf::called = true;
}

namespace d {

using std::enable_if;
using std::is_void;

template<class T>
struct enable_void : enable_if<is_void<T>::value> {
};

template<class T>
struct disable_void : enable_if<!is_void<T>::value> {
};

} // d

class Test_common {
public:
	Test_common(const char* ms)
		:	t(ms) {
	}

	void operator()() {
		F f;
		m = "message";
		nf::reset();
		prepare_call();
		call_and_assert();
		verify();
	}
protected:
	virtual void call_and_assert() = 0;
	virtual void prepare_call() {
	}
	virtual void verify() = 0;

	Test t;
	const char* m;
};

template<class F>
class Test_0 : public Test_common {
public:
	Test_0(F f, const char* ms)
		:	Test_common(ms), f(f) {
	}
protected:
	void call_and_assert() {
		call<decltype(clog::out(m, f))>();
	}
	void verify() {
		t.a(Spy::last()->message == m, L);
		t.a(nf::called, L);
	}

	F f;
private:
	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f);
	}
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f) == 1, L);
	}
};

template<class F>
inline Test_0<F> test_0(F f, const char* ms)
{
	return Test_0<F>(f, ms);
}

void t1(const char* ms)
{
	(test_0(f1, ms))();
}

void f2(int a)
{
	nf::called = true;
	nf::arg.v = a;
}

template<class F>
class Test_1 : public Test_common {
public:
	Test_1(F f, const char* ms) : Test_common(ms), f(f) {
	}

protected:
	void verify() {
		t.a(Spy::last()->message == m, L);
		t.a(nf::called, L);
		t.a(nf::arg.v == nf::a.v, L);
		t.a(nf::A::copied == false, L);
	}

	F f;
};

template<class F>
class Test_1v : public Test_1<F> {
public:
	Test_1v(F f, const char* ms) : Test_1<F>(f, ms) {
	}

protected:
	using Test_1<F>::m;
	using Test_1<F>::t;
	using Test_1<F>::f;

	void call_and_assert() {
		call<decltype(clog::out(m, f, nf::a.v))>();
	}
	void prepare_call() {
		nf::a.v = 2;
	}
private:
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f, nf::a.v) == 1, L);
	}

	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f, nf::a.v);
	}
};

template<class F>
inline Test_1v<F> test_1v(F f, const char* ms)
{
	return Test_1v<F>(f, ms);
}

void t2(const char* ms)
{
	(test_1v(f2, ms))();
}

void f3(nf::A& a)
{
	nf::called = true;
	nf::arg = a;
}

void f3c(const nf::A& a)
{
	nf::called = true;
	nf::arg = a;
}

template<class F>
class Test_1r : public Test_1<F> {
public:
	Test_1r(F f, const char* ms) : Test_1<F>(f, ms) {
	}

protected:
	using Test_1<F>::m;
	using Test_1<F>::t;
	using Test_1<F>::f;

	void call_and_assert() {
		call<decltype(clog::out(m, f, nf::a))>();
	}
private:
	template<class T>
	void call(typename d::disable_void<T>::type* = 0) {
		t.a(clog::out(m, f, nf::a) == 1, L);
	}

	template<class T>
	void call(typename d::enable_void<T>::type* = 0) {
		clog::out(m, f, nf::a);
	}
};

template<class F>
inline Test_1r<F> test_1r(F f, const char* ms)
{
	return Test_1r<F>(f, ms);
}

void t3(const char* ms)
{
	(test_1r(f3, ms))();
}

int f1_1r(nf::A& a)
{
	nf::called = true;
	nf::arg = a;
	return 1;
}

int f1_1rc(const nf::A& a)
{
	nf::called = true;
	nf::arg = a;
	return 1;
}

void t7(const char* ms)
{
	(test_1r(f1_1r, ms))();
}

void t8(const char* ms)
{
	(test_1r(f1_1rc, ms))();
}

void t4(const char* ms)
{
	(test_1r(f3c, ms))();
}

int f1_0()
{
	nf::called = true;
	return 1;
}

void t5(const char* ms)
{
	(test_0(f1_0, ms))();
}

int f1_1(int v)
{
	nf::called = true;
	nf::arg.v = v;
	return 1;
}

void t6(const char* ms)
{
	(test_1v(f1_1, ms))();
}

void f0e()
{
	throw nf::E();
}

void t9(const char* ms)
{
	Test t(ms);
	F f;
	const char* m("message");
	nf::reset();
	try {
		clog::out(m, f0e);
		throw std::logic_error("test");
	}
	catch (const nf::E&) {
	}
	t.a(Spy::last()->message == m, L);
	t.a(Spy::last()->exception, L);
}

} // nlog

using nomagic::run;

void spy_tests()
{
	using namespace nspy;

	run(	"Spy returns null when it is asked to "
		"provide the last log output but there is not.", t1);

	run("Spy returns the last log object", t2);

	run("Spy resets the last log", t3);
}

void log_tests()
{
	using namespace nlog;

	run("return(void), arg(0)", t1);
	run("return(void), arg(1)", t2);
	run("return(void), arg(1, ref)", t3);
	run("return(void), arg(1, cref)", t4);
	run("return(int), arg(0)", t5);
	run("return(int), arg(1)", t6);
	run("return(int), arg(1, ref)", t7);
	run("return(int), arg(1, cref)", t8);
	run("return(void), arg(0), exception", t9);
}

} // unnamed

#include "test.h"

namespace test {

void run_clog_tests()
{
	spy_tests();
	log_tests();
}

} // test

<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(logn)

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: You should return the head of the sorted linked list,
     using constant space complexity.
     */
    ListNode *sortList(ListNode *head) {
        if (!head || !head->next) {
            return head;
        }

        auto slow = head, fast = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }

        // Split linked list.
        fast = slow;
        slow = slow->next;
        fast->next = nullptr;

        return mergeTwoLists(sortList(head), sortList(slow));
    }

private:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        ListNode dummy = ListNode{0};
        auto *curr = &dummy;

        while (l1 && l2) {
            if (l1->val <= l2->val) {
                curr->next = l1;
                l1 = l1->next;
            } else {
                curr->next = l2;
                l2 = l2->next;
            }
            curr = curr->next;
        }
        curr->next = l1 ? l1 : l2;

        return dummy.next;
    }
};
<commit_msg>Update sort-list.cpp<commit_after>// Time:  O(nlogn)
// Space: O(logn)

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: You should return the head of the sorted linked list,
     using constant space complexity.
     */
    ListNode *sortList(ListNode *head) {
        if (!head || !head->next) {
            return head;
        }

        auto slow = head, fast = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }

        // Split linked list.
        fast = slow;
        slow = slow->next;
        fast->next = nullptr;

        return mergeTwoLists(sortList(head), sortList(slow));
    }

private:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        ListNode dummy{0};
        auto curr = &dummy;

        while (l1 && l2) {
            if (l1->val <= l2->val) {
                curr->next = l1;
                l1 = l1->next;
            } else {
                curr->next = l2;
                l2 = l2->next;
            }
            curr = curr->next;
        }
        curr->next = l1 ? l1 : l2;

        return dummy.next;
    }
};
<|endoftext|>


<commit_before>#include <iostream>

#include "KafkaEventPublisher.h"

/**
 * Set up the configuration for the publisher and initialise it
 *
 * @param broker_str - the IP or hostname of the broker
 * @param topic_str - the name of the datastream (topic) to publish the data to
 */
void KafkaEventPublisher::setUp(const std::string &broker_str,
                                const std::string &topic_str) {

  std::cout << "Setting up Kafka producer" << std::endl;

  std::string error_str;

  RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
  RdKafka::Conf *tconf = RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC);

  conf->set("metadata.broker.list", broker_str, error_str);
  conf->set("message.max.bytes", "10000000", error_str);
  conf->set("fetch.message.max.bytes", "10000000", error_str);
  conf->set("replica.fetch.max.bytes", "10000000", error_str);

  // Create producer
  m_producer_ptr = std::unique_ptr<RdKafka::Producer>(
      RdKafka::Producer::create(conf, error_str));
  if (!m_producer_ptr.get()) {
    std::cerr << "Failed to create producer: " << error_str << std::endl;
    exit(1);
  }

  // Create topic handle
  m_topic_ptr = std::unique_ptr<RdKafka::Topic>(RdKafka::Topic::create(
      m_producer_ptr.get(), topic_str, tconf, error_str));
  if (!m_topic_ptr.get()) {
    std::cerr << "Failed to create topic: " << error_str << std::endl;
    exit(1);
  }
}

/**
 * Publish the provided message to the datastream
 *
 * @param buf - pointer to the message buffer
 * @param messageSize - the size of the message in bytes
 */
void KafkaEventPublisher::sendMessage(char *buf, size_t messageSize) {
  RdKafka::ErrorCode resp = m_producer_ptr->produce(
      m_topic_ptr.get(), 0, RdKafka::Producer::RK_MSG_COPY, buf, messageSize,
      NULL, NULL);

  if (resp != RdKafka::ERR_NO_ERROR) {
    std::cerr << "% Produce failed: " << RdKafka::err2str(resp) << std::endl;
    std::cerr << "message size was " << messageSize << std::endl;
  }

  m_producer_ptr->poll(0);
}
<commit_msg>distribute messages across multiple partitions<commit_after>#include <iostream>

#include "KafkaEventPublisher.h"

/**
 * Set up the configuration for the publisher and initialise it
 *
 * @param broker_str - the IP or hostname of the broker
 * @param topic_str - the name of the datastream (topic) to publish the data to
 */
void KafkaEventPublisher::setUp(const std::string &broker_str,
                                const std::string &topic_str) {

  std::cout << "Setting up Kafka producer" << std::endl;

  std::string error_str;

  RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
  RdKafka::Conf *tconf = RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC);

  conf->set("metadata.broker.list", broker_str, error_str);
  conf->set("message.max.bytes", "10000000", error_str);
  conf->set("fetch.message.max.bytes", "10000000", error_str);
  conf->set("replica.fetch.max.bytes", "10000000", error_str);
  // conf->set("compression.codec", "snappy", error_str);

  // Create producer
  m_producer_ptr = std::unique_ptr<RdKafka::Producer>(
      RdKafka::Producer::create(conf, error_str));
  if (!m_producer_ptr.get()) {
    std::cerr << "Failed to create producer: " << error_str << std::endl;
    exit(1);
  }

  // Create topic handle
  m_topic_ptr = std::unique_ptr<RdKafka::Topic>(RdKafka::Topic::create(
      m_producer_ptr.get(), topic_str, tconf, error_str));
  if (!m_topic_ptr.get()) {
    std::cerr << "Failed to create topic: " << error_str << std::endl;
    exit(1);
  }
}

/**
 * Publish the provided message to the datastream
 *
 * @param buf - pointer to the message buffer
 * @param messageSize - the size of the message in bytes
 */
void KafkaEventPublisher::sendMessage(char *buf, size_t messageSize) {
  // using -1 as the partition number will cause rdkafka to distribute messages
  // across multiple partitions to load balance (if the topic has multiple
  // partitions)
  RdKafka::ErrorCode resp = m_producer_ptr->produce(
      m_topic_ptr.get(), -1, RdKafka::Producer::RK_MSG_COPY, buf, messageSize,
      NULL, NULL);

  if (resp != RdKafka::ERR_NO_ERROR) {
    std::cerr << "% Produce failed: " << RdKafka::err2str(resp) << std::endl;
    std::cerr << "message size was " << messageSize << std::endl;
  }

  m_producer_ptr->poll(0);
}
<|endoftext|>


<commit_before>// This file is part of Metallic, a runtime library for WebAssembly.
//
// Copyright (C) 2017 Chen-Pang He <chen.pang.he@jdh8.org>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/

#include <internal/reinterpret>
#include <cmath>
#include <cstdint>

namespace std {
namespace __internal {

static float _kernel(float x)
{
    std::int32_t i = reinterpret<std::int32_t>(x);

    if (i == 0 || i >= 0x7F800000)
        return x;

    if (i < 0x00800000) {
        int shift = __builtin_clz(i) - 8;
        i = (i << shift) - (shift << 23);
    }

    i = 0x2A512CE3 + i / 3;

    double y = reinterpret<float>(i);

    y *= 0.5 + 1.5 * x / (2 * y * (y * y) + x);
    y += 0.33333333333333333333 * (x / (y * y) - y);

    return y;
}

extern "C"
float cbrtf(float x)
{
    return std::copysign(_kernel(std::abs(x)), x);
}

} // namespace __internal
} // namespace std
<commit_msg>Introduce generic std::__internal::magnitude::normalize<commit_after>// This file is part of Metallic, a runtime library for WebAssembly.
//
// Copyright (C) 2017 Chen-Pang He <chen.pang.he@jdh8.org>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/

#include <internal/ieee754>
#include <internal/reinterpret>
#include <cmath>
#include <cstdint>

namespace std {
namespace __internal {

static float _kernel(float x)
{
    std::int32_t i = reinterpret<std::int32_t>(x);

    if (i == 0 || i >= 0x7F800000)
        return x;

    i = 0x2A512CE3 + magnitude::normalize(i) / 3;

    double y = reinterpret<float>(i);

    y *= 0.5 + 1.5 * x / (2 * y * (y * y) + x);
    y += 0.33333333333333333333 * (x / (y * y) - y);

    return y;
}

extern "C"
float cbrtf(float x)
{
    return std::copysign(_kernel(std::abs(x)), x);
}

} // namespace __internal
} // namespace std
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

/*
 * This represents a collection of row blocks that we usually access with
 * a single I/O request. However, due to load balancing, we sometimes
 * need to access the collection of row blocks with many smaller I/O
 * requests. In this case, each row block is accessed by one I/O request.
 */
class large_row_io
{
	// A reference to the row block vector of the graph.
	const std::vector<row_block> *blocks;
	// The offset of the first row block in the row block vector.
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	/*
	 * Create an I/O request that access all row blocks in the collection.
	 */
	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	/*
	 * Create an I/O request that accesses a single row block.
	 */
	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

/*
 * The I/O generator that access a matrix on disks by rows.
 * An I/O generator are assigned a number of row blocks that it can accesses.
 * Each thread has an I/O generator and gets I/O requests from its own I/O
 * generator. When load balancing kicks in, a thread will try to steal I/O requests
 * from other threads' I/O generators.
 */
class row_io_generator: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	row_io_generator(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, const row_block_mapper &mapper);

	/*
	 * This method is called by the worker thread that owns the I/O generator
	 * to get I/O requests.
	 */
	virtual matrix_io get_next_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		// It's possible that all IOs have been stolen.
		// We have to check it.
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	/*
	 * This method is called by other worker threads. It's used for load
	 * balancing.
	 */
	virtual matrix_io steal_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off].get_sub_io(tot_num_cols, file_id);
			if (!ios[curr_io_off].has_data())
				curr_io_off++;
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

row_io_generator::row_io_generator(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id,
		const row_block_mapper &mapper)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		size_t num_row_blocks = mapper.get_range(i).num;
		off_t rb_off = mapper.get_range(i).idx;
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - rb_off * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, rb_off, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

/*
 * The I/O generator for accessing 2D-partitioned blocks.
 * A generated I/O request may access multiple 2D-partitioned blocks.
 * Each I/O generator still accesses all blocks in a block row.
 */
class b2d_io_generator: public matrix_io_generator
{
	// This contains the information of a block row.
	struct block_row {
		// The Id of the block row.
		uint32_t row_block_id;
		// The offset of the block row on the disks.
		off_t off;
		// The size of the block row on the disks.
		size_t size;

		bool operator<(const block_row &row) const {
			return this->size > row.size;
		}
	};

	pthread_spinlock_t lock;
	// The block rows should be sorted in the descending order of
	// block row sizes.
	std::vector<block_row> brows;
	// The offset of the block row currently being accessed.
	// For normal case, when a block row is accessed by the local worker
	// thread, the offset increases by 1.
	std::atomic<size_t> brow_off;
	// The current number of block rows in the vector.
	// When another worker thread steals block rows, it steals them from
	// the end of the vector.
	std::atomic<size_t> num_brows;

	block_2d_size block_size;
	int file_id;
	size_t tot_num_cols;
public:
	b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
			const row_block_mapper &mapper);

	virtual matrix_io get_next_io();
	virtual matrix_io steal_io();

	virtual bool has_next_io() {
		return brow_off < num_brows;
	}
};

b2d_io_generator::b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
		const row_block_mapper &mapper): block_size(
			idx->get_header().get_2d_block_size())
{
	this->tot_num_cols = idx->get_header().get_num_cols();
	this->file_id = file_id;
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		struct block_row brow;
		row_block_mapper::rb_range range = mapper.get_range(i);
		// block row is much larger now, so we only need to have one block row
		// in a range.
		assert(range.num == 1);
		brow.row_block_id = range.idx;
		brow.off = idx->get_block_row_off(range.idx);
		brow.size = idx->get_block_row_off(
				range.idx + 1) - idx->get_block_row_off(range.idx);
		brows.push_back(brow);
	}
	// Sort the block rows based on the size of block rows.
	std::sort(brows.begin(), brows.end());
}

matrix_io b2d_io_generator::get_next_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (brow_off < num_brows) {
		block_row brow = brows[brow_off++];
		matrix_loc mat_loc(brow.row_block_id * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, brow.off);
		ret = matrix_io(mat_loc, block_size.get_num_rows(), tot_num_cols,
				data_loc, brow.size);
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io b2d_io_generator::steal_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (brow_off < num_brows) {
		block_row brow = brows[num_brows - 1];
		num_brows--;
		matrix_loc mat_loc(brow.row_block_id * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, brow.off);
		ret = matrix_io(mat_loc, block_size.get_num_rows(), tot_num_cols,
				data_loc, brow.size);
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new row_io_generator(_blocks,
				tot_num_rows, tot_num_cols, file_id, mapper));
}

matrix_io_generator::ptr matrix_io_generator::create(SpM_2d_index::ptr idx,
		int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new b2d_io_generator(idx, file_id, mapper));
}

void row_block_mapper::init(size_t num_rbs, int gen_id, int num_gens,
		size_t range_size)
{
	size_t i = gen_id * range_size;
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	for (; i < num_rbs; i += range_size * num_gens) {
		struct rb_range range;
		range.idx = i;
		range.num = std::min(range_size, num_rbs - i);
		ranges.push_back(range);
	}
}

row_block_mapper::row_block_mapper(const SpM_2d_index &index, int gen_id,
		int num_gens, size_t range_size)
{
	init(index.get_num_block_rows(), gen_id, num_gens, range_size);
}

}
<commit_msg>[Matrix]: fix a bug in init of b2d_io_generator.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

/*
 * This represents a collection of row blocks that we usually access with
 * a single I/O request. However, due to load balancing, we sometimes
 * need to access the collection of row blocks with many smaller I/O
 * requests. In this case, each row block is accessed by one I/O request.
 */
class large_row_io
{
	// A reference to the row block vector of the graph.
	const std::vector<row_block> *blocks;
	// The offset of the first row block in the row block vector.
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	/*
	 * Create an I/O request that access all row blocks in the collection.
	 */
	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	/*
	 * Create an I/O request that accesses a single row block.
	 */
	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

/*
 * The I/O generator that access a matrix on disks by rows.
 * An I/O generator are assigned a number of row blocks that it can accesses.
 * Each thread has an I/O generator and gets I/O requests from its own I/O
 * generator. When load balancing kicks in, a thread will try to steal I/O requests
 * from other threads' I/O generators.
 */
class row_io_generator: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	row_io_generator(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, const row_block_mapper &mapper);

	/*
	 * This method is called by the worker thread that owns the I/O generator
	 * to get I/O requests.
	 */
	virtual matrix_io get_next_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		// It's possible that all IOs have been stolen.
		// We have to check it.
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	/*
	 * This method is called by other worker threads. It's used for load
	 * balancing.
	 */
	virtual matrix_io steal_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off].get_sub_io(tot_num_cols, file_id);
			if (!ios[curr_io_off].has_data())
				curr_io_off++;
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

row_io_generator::row_io_generator(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id,
		const row_block_mapper &mapper)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		size_t num_row_blocks = mapper.get_range(i).num;
		off_t rb_off = mapper.get_range(i).idx;
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - rb_off * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, rb_off, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

/*
 * The I/O generator for accessing 2D-partitioned blocks.
 * A generated I/O request may access multiple 2D-partitioned blocks.
 * Each I/O generator still accesses all blocks in a block row.
 */
class b2d_io_generator: public matrix_io_generator
{
	// This contains the information of a block row.
	struct block_row {
		// The Id of the block row.
		uint32_t row_block_id;
		// The offset of the block row on the disks.
		off_t off;
		// The size of the block row on the disks.
		size_t size;

		bool operator<(const block_row &row) const {
			return this->size > row.size;
		}
	};

	pthread_spinlock_t lock;
	// The block rows should be sorted in the descending order of
	// block row sizes.
	std::vector<block_row> brows;
	// The offset of the block row currently being accessed.
	// For normal case, when a block row is accessed by the local worker
	// thread, the offset increases by 1.
	std::atomic<size_t> brow_off;
	// The current number of block rows in the vector.
	// When another worker thread steals block rows, it steals them from
	// the end of the vector.
	std::atomic<size_t> num_brows;

	block_2d_size block_size;
	int file_id;
	size_t tot_num_cols;
public:
	b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
			const row_block_mapper &mapper);

	virtual matrix_io get_next_io();
	virtual matrix_io steal_io();

	virtual bool has_next_io() {
		return brow_off < num_brows;
	}
};

b2d_io_generator::b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
		const row_block_mapper &mapper): block_size(
			idx->get_header().get_2d_block_size())
{
	this->tot_num_cols = idx->get_header().get_num_cols();
	this->file_id = file_id;
	this->brow_off = 0;
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		struct block_row brow;
		row_block_mapper::rb_range range = mapper.get_range(i);
		// block row is much larger now, so we only need to have one block row
		// in a range.
		assert(range.num == 1);
		brow.row_block_id = range.idx;
		brow.off = idx->get_block_row_off(range.idx);
		brow.size = idx->get_block_row_off(
				range.idx + 1) - idx->get_block_row_off(range.idx);
		brows.push_back(brow);
	}
	// Sort the block rows based on the size of block rows.
	std::sort(brows.begin(), brows.end());
	this->num_brows = brows.size();
}

matrix_io b2d_io_generator::get_next_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (brow_off < num_brows) {
		block_row brow = brows[brow_off++];
		matrix_loc mat_loc(brow.row_block_id * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, brow.off);
		ret = matrix_io(mat_loc, block_size.get_num_rows(), tot_num_cols,
				data_loc, brow.size);
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io b2d_io_generator::steal_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (brow_off < num_brows) {
		block_row brow = brows[num_brows - 1];
		num_brows--;
		matrix_loc mat_loc(brow.row_block_id * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, brow.off);
		ret = matrix_io(mat_loc, block_size.get_num_rows(), tot_num_cols,
				data_loc, brow.size);
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new row_io_generator(_blocks,
				tot_num_rows, tot_num_cols, file_id, mapper));
}

matrix_io_generator::ptr matrix_io_generator::create(SpM_2d_index::ptr idx,
		int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new b2d_io_generator(idx, file_id, mapper));
}

void row_block_mapper::init(size_t num_rbs, int gen_id, int num_gens,
		size_t range_size)
{
	size_t i = gen_id * range_size;
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	for (; i < num_rbs; i += range_size * num_gens) {
		struct rb_range range;
		range.idx = i;
		range.num = std::min(range_size, num_rbs - i);
		ranges.push_back(range);
	}
}

row_block_mapper::row_block_mapper(const SpM_2d_index &index, int gen_id,
		int num_gens, size_t range_size)
{
	init(index.get_num_block_rows(), gen_id, num_gens, range_size);
}

}
<|endoftext|>


<commit_before><commit_msg>lameencdec: on linux look for libmp3lame.so.0 if .so isnt found -- from 3e388821<commit_after><|endoftext|>


<commit_before>/*
 *  lineedit.cpp  -  Line edit widget with extra drag and drop options
 *  Program:  kalarm
 *  Copyright (c) 2003 - 2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <QRegExp>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFocusEvent>

#include <kurl.h>
#include <kurlcompletion.h>

#include <libkdepim/maillistdrag.h>
#include <libkdepim/kvcarddrag.h>
#include <kcal/icaldrag.h>

#include "lineedit.moc"

/*=============================================================================
= Class LineEdit
= Line edit which accepts drag and drop of text, URLs and/or email addresses.
* It has an option to prevent its contents being selected when it receives
= focus.
=============================================================================*/
LineEdit::LineEdit(Type type, QWidget* parent)
	: KLineEdit(parent),
	  mType(type),
	  mNoSelect(false),
	  mSetCursorAtEnd(false)
{
	init();
}

LineEdit::LineEdit(QWidget* parent)
	: KLineEdit(parent),
	  mType(Text),
	  mNoSelect(false),
	  mSetCursorAtEnd(false)
{
	init();
}

void LineEdit::init()
{
	if (mType == Url)
	{
		setCompletionMode(KGlobalSettings::CompletionShell);
		KUrlCompletion* comp = new KUrlCompletion(KUrlCompletion::FileCompletion);
		comp->setReplaceHome(true);
		setCompletionObject(comp);
		setAutoDeleteCompletionObject(true);
	}
	else
		setCompletionMode(KGlobalSettings::CompletionNone);
}

/******************************************************************************
*  Called when the line edit receives focus.
*  If 'noSelect' is true, prevent the contents being selected.
*/
void LineEdit::focusInEvent(QFocusEvent* e)
{
	QFocusEvent newe(QEvent::FocusIn, (mNoSelect ? Qt::OtherFocusReason : e->reason()));
	KLineEdit::focusInEvent(&newe);
	mNoSelect = false;
}

void LineEdit::setText(const QString& text)
{
	KLineEdit::setText(text);
	setCursorPosition(mSetCursorAtEnd ? text.length() : 0);
}

void LineEdit::dragEnterEvent(QDragEnterEvent* e)
{
	const QMimeData* data = e->mimeData();
	bool ok;
	if (KCal::ICalDrag::canDecode(data))
		ok = false;   // don't accept "text/calendar" objects
	else
		ok = (data->hasText()
		   || KUrl::List::canDecode(data)
		   || mType != Url && KPIM::MailList::canDecode(data)
		   || mType == Emails && KVCardDrag::canDecode(data));
	if (ok)
		e->accept(rect());
	else
		e->ignore(rect());
}

void LineEdit::dropEvent(QDropEvent* e)
{
	const QMimeData* data = e->mimeData();
	QString               newText;
	QStringList           newEmails;
	KUrl::List            files;
	KABC::Addressee::List addrList;

	if (mType != Url
	&&  KPIM::MailList::canDecode( data ) )
	{
		KPIM::MailList mailList = KPIM::MailList::fromMimeData( data );
		// KMail message(s) - ignore all but the first
		if (mailList.count())
		{
			if (mType == Emails)
				newText = mailList.first().from();
			else
				setText(mailList.first().subject());    // replace any existing text
		}
	}
	// This must come before KUrl
	else if (mType == Emails
	&&  KVCardDrag::canDecode(data)  &&  KVCardDrag::fromMimeData(data, addrList))
	{
		// KAddressBook entries
		for (KABC::Addressee::List::Iterator it = addrList.begin();  it != addrList.end();  ++it)
		{
			QString em((*it).fullEmail());
			if (!em.isEmpty())
				newEmails.append(em);
		}
	}
	else if (!(files = KUrl::List::fromMimeData(data)).isEmpty())
	{
		// URL(s)
		switch (mType)
		{
			case Url:
				// URL entry field - ignore all but the first dropped URL
				setText(files.first().prettyUrl());    // replace any existing text
				break;
			case Emails:
			{
				// Email entry field - ignore all but mailto: URLs
				QString mailto = QLatin1String("mailto");
				for (KUrl::List::Iterator it = files.begin();  it != files.end();  ++it)
				{
					if ((*it).protocol() == mailto)
						newEmails.append((*it).path());
				}
				break;
			}
			case Text:
				newText = files.first().prettyUrl();
				break;
		}
	}
	else if (data->hasText())
	{
		// Plain text
		QString txt = data->text();
		if (mType == Emails)
		{
			// Remove newlines from a list of email addresses, and allow an eventual mailto: protocol
			QString mailto = QLatin1String("mailto:");
			newEmails = txt.split(QRegExp("[\r\n]+"), QString::SkipEmptyParts);
			for (QStringList::Iterator it = newEmails.begin();  it != newEmails.end();  ++it)
			{
				if ((*it).startsWith(mailto))
				{
					KUrl url(*it);
					*it = url.path();
				}
			}
		}
		else
		{
			int newline = txt.indexOf(QLatin1Char('\n'));
			newText = (newline >= 0) ? txt.left(newline) : txt;
		}
	}

	if (newEmails.count())
	{
		newText = newEmails.join(",");
		int c = cursorPosition();
		if (c > 0)
			newText.prepend(",");
		if (c < static_cast<int>(text().length()))
			newText.append(",");
	}
	if (!newText.isEmpty())
		insert(newText);
}
<commit_msg>Style<commit_after>/*
 *  lineedit.cpp  -  Line edit widget with extra drag and drop options
 *  Program:  kalarm
 *  Copyright © 2003-2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <QRegExp>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFocusEvent>

#include <kurl.h>
#include <kurlcompletion.h>

#include <libkdepim/maillistdrag.h>
#include <libkdepim/kvcarddrag.h>
#include <kcal/icaldrag.h>

#include "lineedit.moc"

/*=============================================================================
= Class LineEdit
= Line edit which accepts drag and drop of text, URLs and/or email addresses.
* It has an option to prevent its contents being selected when it receives
= focus.
=============================================================================*/
LineEdit::LineEdit(Type type, QWidget* parent)
	: KLineEdit(parent),
	  mType(type),
	  mNoSelect(false),
	  mSetCursorAtEnd(false)
{
	init();
}

LineEdit::LineEdit(QWidget* parent)
	: KLineEdit(parent),
	  mType(Text),
	  mNoSelect(false),
	  mSetCursorAtEnd(false)
{
	init();
}

void LineEdit::init()
{
	if (mType == Url)
	{
		setCompletionMode(KGlobalSettings::CompletionShell);
		KUrlCompletion* comp = new KUrlCompletion(KUrlCompletion::FileCompletion);
		comp->setReplaceHome(true);
		setCompletionObject(comp);
		setAutoDeleteCompletionObject(true);
	}
	else
		setCompletionMode(KGlobalSettings::CompletionNone);
}

/******************************************************************************
*  Called when the line edit receives focus.
*  If 'noSelect' is true, prevent the contents being selected.
*/
void LineEdit::focusInEvent(QFocusEvent* e)
{
	QFocusEvent newe(QEvent::FocusIn, (mNoSelect ? Qt::OtherFocusReason : e->reason()));
	KLineEdit::focusInEvent(&newe);
	mNoSelect = false;
}

void LineEdit::setText(const QString& text)
{
	KLineEdit::setText(text);
	setCursorPosition(mSetCursorAtEnd ? text.length() : 0);
}

void LineEdit::dragEnterEvent(QDragEnterEvent* e)
{
	const QMimeData* data = e->mimeData();
	bool ok;
	if (KCal::ICalDrag::canDecode(data))
		ok = false;   // don't accept "text/calendar" objects
	else
		ok = (data->hasText()
		   || KUrl::List::canDecode(data)
		   || mType != Url && KPIM::MailList::canDecode(data)
		   || mType == Emails && KVCardDrag::canDecode(data));
	if (ok)
		e->accept(rect());
	else
		e->ignore(rect());
}

void LineEdit::dropEvent(QDropEvent* e)
{
	const QMimeData* data = e->mimeData();
	QString               newText;
	QStringList           newEmails;
	KUrl::List            files;
	KABC::Addressee::List addrList;

	if (mType != Url
	&&  KPIM::MailList::canDecode(data))
	{
		KPIM::MailList mailList = KPIM::MailList::fromMimeData(data);
		// KMail message(s) - ignore all but the first
		if (mailList.count())
		{
			if (mType == Emails)
				newText = mailList.first().from();
			else
				setText(mailList.first().subject());    // replace any existing text
		}
	}
	// This must come before KUrl
	else if (mType == Emails
	&&  KVCardDrag::canDecode(data)  &&  KVCardDrag::fromMimeData(data, addrList))
	{
		// KAddressBook entries
		for (KABC::Addressee::List::Iterator it = addrList.begin();  it != addrList.end();  ++it)
		{
			QString em((*it).fullEmail());
			if (!em.isEmpty())
				newEmails.append(em);
		}
	}
	else if (!(files = KUrl::List::fromMimeData(data)).isEmpty())
	{
		// URL(s)
		switch (mType)
		{
			case Url:
				// URL entry field - ignore all but the first dropped URL
				setText(files.first().prettyUrl());    // replace any existing text
				break;
			case Emails:
			{
				// Email entry field - ignore all but mailto: URLs
				QString mailto = QLatin1String("mailto");
				for (KUrl::List::Iterator it = files.begin();  it != files.end();  ++it)
				{
					if ((*it).protocol() == mailto)
						newEmails.append((*it).path());
				}
				break;
			}
			case Text:
				newText = files.first().prettyUrl();
				break;
		}
	}
	else if (data->hasText())
	{
		// Plain text
		QString txt = data->text();
		if (mType == Emails)
		{
			// Remove newlines from a list of email addresses, and allow an eventual mailto: protocol
			QString mailto = QLatin1String("mailto:");
			newEmails = txt.split(QRegExp("[\r\n]+"), QString::SkipEmptyParts);
			for (QStringList::Iterator it = newEmails.begin();  it != newEmails.end();  ++it)
			{
				if ((*it).startsWith(mailto))
				{
					KUrl url(*it);
					*it = url.path();
				}
			}
		}
		else
		{
			int newline = txt.indexOf(QLatin1Char('\n'));
			newText = (newline >= 0) ? txt.left(newline) : txt;
		}
	}

	if (newEmails.count())
	{
		newText = newEmails.join(",");
		int c = cursorPosition();
		if (c > 0)
			newText.prepend(",");
		if (c < static_cast<int>(text().length()))
			newText.append(",");
	}
	if (!newText.isEmpty())
		insert(newText);
}
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

#if !defined(XALANMAP_HEADER_GUARD_1357924680)
#define XALANMAP_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <cstddef>
#include <algorithm>
#include <functional>
#include <utility>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanList.hpp>

XALAN_CPP_NAMESPACE_BEGIN

typedef size_t	size_type;

template <class Key>
class XalanHasher : public XALAN_STD_QUALIFIER unary_function<Key, size_type>
{
public:
	size_type operator()(const Key& key) const
	{
		const char *byteArray = reinterpret_cast<const char*>(&key);

		size_type result = 0;

		for (size_type i = 0; i < sizeof(Key); ++i)
		{
			result = (result << 1) ^ byteArray[i];
		}

		return result;
	}
};

template <class Key>
struct XalanMapKeyTraits
{
	typedef XalanHasher<Key>					Hasher;
	typedef XALAN_STD_QUALIFIER equal_to<Key>	Comparator;
};

template <class Key>
struct XalanHashMemberPointer
{

	size_type operator() (const Key * key) const
	{
		assert (key != 0);
		return key->hash();
	}
};

template <class Key>
struct XalanHashMemberReference
{

	size_type operator() (const Key& key) const
	{
		return key.hash();
	}
};

/**
 * Xalan map entry pair of a key and data
 */
template <class KeyType,  class DataType>
struct XalanMapEntry
{
    typedef KeyType     first_type;
    typedef DataType    second_type;

	typedef size_t	size_type;

    XalanMapEntry(
            const first_type & theFirst,
            const second_type& theSecond,
            size_type index = 0) :
		first(theFirst),
        second(theSecond),
        bucketIndex(index)
	{
	}

	XalanMapEntry() :
		first(),
        second(),
        bucketIndex(size_type())
	{
	}

    first_type      first;
    second_type     second;
    size_type       bucketIndex;
};

template <class Value>
struct XalanMapIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
};

template <class Value>
struct XalanMapConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
};

template <class XalanMapTraits, class BaseIterator>
struct XalanMapIterator : public BaseIterator
{
    typedef typename XalanMapTraits::value_type         value_type;
    typedef typename XalanMapTraits::reference          reference;
    typedef typename XalanMapTraits::pointer            pointer;

	typedef ptrdiff_t		                    difference_type;
	typedef XALAN_STD_QUALIFIER bidirectional_iterator_tag iterator_category;

    typedef XalanMapIterator<
		XalanMapIteratorTraits<value_type>,
  		typename BaseIterator::iterator>	Iterator;

    XalanMapIterator() :
            BaseIterator()
    {
    }

    XalanMapIterator(const Iterator & theRhs) :
            BaseIterator(theRhs)
    {
    }

    XalanMapIterator(const BaseIterator & theRhs) :
            BaseIterator(theRhs)
    {
    }

    XalanMapIterator operator++(int)
    {
	 XalanMapIterator temp(*this);
	 BaseIterator::operator++();
	 return temp;
    }

    XalanMapIterator& operator++()
    {
	 BaseIterator::operator++();
	 return *this;
    }

    reference operator*() const
    {
        return *(BaseIterator::operator*());
    }

    pointer operator->() const
    {
        return (BaseIterator::operator*());
    }
};

/**
  * Xalan implementation of a hashtable.
  *
  */
template <
		class Key,
		class Value,
		class KeyTraits = XalanMapKeyTraits<Key> >
class XalanMap
{
public:
	/**
	 * Each map entry is stored in a linked list.
	 * The hash buckets are a vector of pointers into the entry list
	 * An empty bucket will point to the end of the list,
	 * A non-empty bucket will point to its first entry.  Remaining
	 * entries in the chain follow the first and have the same index value.
	 */

	typedef Key					key_type;
	typedef Value				data_type;
	typedef size_t				size_type;

	typedef XalanMapEntry<const key_type, data_type>   value_type;
    typedef value_type  Entry;

	typedef XalanList<Entry*>									EntryListType;

    typedef XalanMapIterator<XalanMapIteratorTraits<Entry>, typename EntryListType::iterator>            iterator;
    typedef XalanMapIterator<XalanMapConstIteratorTraits<Entry>, typename EntryListType::const_iterator> const_iterator;

	typedef XalanVector<iterator>		EntryPosVectorType;

    typedef typename MemoryManagedConstructionTraits<key_type>::Constructor  FirstConstructor;
    typedef typename MemoryManagedConstructionTraits<data_type>::Constructor SecondConstructor;

	XalanMap(
			MemoryManagerType& theMemoryManager,
			float loadFactor = 0.75,
			size_type minBuckets = 10) :
		m_memoryManager(&theMemoryManager),
		m_loadFactor(loadFactor),
		m_minBuckets(minBuckets),
		m_size(0),
		m_entries(*m_memoryManager),
		m_buckets(*m_memoryManager)
	{
	}

	XalanMap(
			const XalanMap &theRhs,
			MemoryManagerType&  theManager) :
        m_memoryManager(&theManager),
		m_loadFactor(theRhs.m_loadFactor),
		m_minBuckets(10),
		m_size(0),
		m_entries(*m_memoryManager),
		m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, m_entries.end(), theManager)
	{
		const_iterator entry = theRhs.begin();
		while(entry != theRhs.end())
		{
			insert(*entry);
			++entry;
		}

		assert(m_size == theRhs.m_size);
	}

    MemoryManagerType&
    getMemoryManager()
    {
        assert (m_memoryManager != 0);

        return *m_memoryManager;
    }

	~XalanMap()
	{
        doRemoveEntries();
	}

	XalanMap & operator=(const XalanMap& theRhs)
	{
		XalanMap theTemp(theRhs, *m_memoryManager);
		swap(theTemp);
		return *this;
	}

	size_type size() const
	{
		return m_size;
	}

	bool empty() const
    {
		return m_size == 0;
	}

	iterator begin()
	{
		return m_entries.begin();
	}

	const_iterator begin() const
	{
		return m_entries.begin();
	}

	iterator end()
	{
		return m_entries.end();
	}

	const_iterator end() const
	{
		return m_entries.end();
	}

	iterator find(const key_type& key)
	{
		if (!m_buckets.empty())
		{
			const size_type     index = doHash(key);
            assert(index < m_buckets.size());

			iterator bucketPos = m_buckets[index];

			while (bucketPos != m_entries.end() &&
				   bucketPos->bucketIndex == index)
			{
				if (m_equals(key,bucketPos->first))
				{
					return bucketPos;
				}
				++bucketPos;
			}
		}

		return end();
	}

	const_iterator find(const key_type& key) const
	{
		return const_cast<XalanMap *>(this)->find(key);
	}

	data_type & operator[](const key_type& key)
	{
		iterator pos = find(key);

		if (pos == end())
		{
			pos = doCreateEntry(key);
		}

		return (*pos).second;
	}

	void insert(const value_type& value)
	{
		const key_type& key = value.first;
		const data_type& data = value.second;

		insert(key, data);
	}

    void insert(const key_type& key, const data_type& data)
	{
		const const_iterator    pos = find(key);

		if (pos == end())
		{
			doCreateEntry(key, &data);
		}
	}

	void erase(iterator pos)
	{
		if (pos != end())
		{
			doRemoveEntry(pos);
		}
	}

	size_type erase(const key_type& key)
	{
		const iterator  pos = find(key);

        if (pos != end())
        {
		    erase(pos);
            return 1;
        }
        else
        {
            return 0;
        }
	}

	void clear()
	{
        doRemoveEntries();

		m_size = 0;

		XALAN_STD_QUALIFIER fill(
            m_buckets.begin(),
            m_buckets.end(),
            m_entries.end());

		m_entries.clear();
	}

	void swap(XalanMap& theRhs)
	{
		size_type tempSize = m_size;
		m_size = theRhs.m_size;
		theRhs.m_size = tempSize;

		MemoryManagerType* tempMemoryManager = m_memoryManager;
		m_memoryManager = theRhs.m_memoryManager;
		theRhs.m_memoryManager = tempMemoryManager;

		m_entries.swap(theRhs.m_entries);
		m_buckets.swap(theRhs.m_buckets);
	}

	protected:

	iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
	{
		// if there are no buckets, create initial minimum set of buckets
		if (m_buckets.empty())
		{
			m_buckets.insert(m_buckets.begin(), m_minBuckets, m_entries.end());
		}

		// if the load factor has been reached, rehash
		if (size_type(m_loadFactor * size()) > m_buckets.size())
		{
			rehash();
		}

		size_type index = doHash(key);

		iterator & bucketStartPos = m_buckets[index];

		// insert a new entry as the first position in the bucket
        Entry * newEntry = allocate(1);
        FirstConstructor::construct(const_cast<key_type*>(&newEntry->first), key, *m_memoryManager);
        if (data != 0)
        {
            SecondConstructor::construct(&newEntry->second, *data, *m_memoryManager);
        }
        else
        {
             SecondConstructor::construct(&newEntry->second, *m_memoryManager);
        }

        new (&newEntry->bucketIndex) size_type(index);
		bucketStartPos = m_entries.insert(bucketStartPos, newEntry);

		++m_size;
		return bucketStartPos;
	}

	void doRemoveEntry(const iterator & toRemovePos)
	{
		size_type index = toRemovePos->bucketIndex;
		iterator nextPos = ++(iterator(toRemovePos));

		// if the entry to remove is the first in the bucket
		// set the next entry as the first or,
		// if there are no more entries set it to the end
		if (m_buckets[index] == toRemovePos)
		{
			if (nextPos != m_entries.end() &&
                nextPos->bucketIndex == index)
			{
				m_buckets[index] = nextPos;
			}
			else
			{
				m_buckets[index] = m_entries.end();
			}
		}

        value_type& toRemove = *toRemovePos;
#if defined(_MSC_VER) && _MSC_VER <= 1300
        toRemove.value_type::~value_type();
#else
        toRemove.~value_type();
#endif
        deallocate(&toRemove);
		m_entries.erase(toRemovePos);
		--m_size;
	}

    void
    doRemoveEntries()
    {
        while(size() > 0)
        {
            doRemoveEntry(begin());
        }
    }

	size_type doHash(const Key & key) const
	{
		return m_hash(key) % m_buckets.size();
	}

	void rehash()
	{
		// grow the number of buckets by 60%
		EntryPosVectorType temp(size_type(1.6 * size()), m_entries.end(), *m_memoryManager);
		m_buckets.swap(temp);

		// move current entries into a temporary list
		EntryListType tempEntryList(*m_memoryManager);
		tempEntryList.splice(tempEntryList.begin(),m_entries, m_entries.begin(), m_entries.end());

		// rehash each entry assign to bucket and insert into list
		while (tempEntryList.begin() != tempEntryList.end())
		{
			iterator entry = tempEntryList.begin();

			entry->bucketIndex = doHash(entry->first);
			iterator & bucketStartPos = m_buckets[entry->bucketIndex];

			// if the bucket is empty assign to the entry and insert
			// into the list, otherwise insert into front of the
			// current first entry
			if (bucketStartPos == m_entries.end())
			{
				bucketStartPos = entry;
				m_entries.splice(m_entries.begin(), tempEntryList, entry);
			}
			else
			{
				m_entries.splice(bucketStartPos, tempEntryList, entry);
				--bucketStartPos;
			}
		}
	}

    value_type*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(value_type);

        assert( m_memoryManager != 0 );

        void*   pointer = m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return (value_type*) pointer;
    }

    void
    deallocate(value_type*  pointer)
    {
        if (m_memoryManager == 0)
        {
            ::operator delete(pointer);
        }
        else
        {
            m_memoryManager->deallocate(pointer);
        }
    }

	// Data members...
	typename KeyTraits::Hasher					m_hash;

	typename KeyTraits::Comparator				m_equals;

    MemoryManagerType*					m_memoryManager;

	float								m_loadFactor;

	size_type							m_minBuckets;

	size_type							m_size;

	EntryListType						m_entries;

    EntryPosVectorType					m_buckets;

    private:
    // not defined
    XalanMap();
    XalanMap(const XalanMap&);
};

XALAN_CPP_NAMESPACE_END

#endif  // XALANMAP_HEADER_GUARD_1357924680

<commit_msg>Improved XalanMap implementation<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

#if !defined(XALANMAP_HEADER_GUARD_1357924680)
#define XALANMAP_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <cstddef>
#include <algorithm>
#include <functional>
#include <utility>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanList.hpp>

XALAN_CPP_NAMESPACE_BEGIN

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4189)
#endif

typedef size_t	size_type;

template <class Key>
class XalanHasher : public XALAN_STD_QUALIFIER unary_function<Key, size_type>
{
public:
	size_type operator()(const Key& key) const
	{
		const char *byteArray = reinterpret_cast<const char*>(&key);

		size_type result = 0;

		for (size_type i = 0; i < sizeof(Key); ++i)
		{
			result = (result << 1) ^ byteArray[i];
		}

		return result;
	}
};

template <class Key>
struct XalanMapKeyTraits
{
	typedef XalanHasher<Key>					Hasher;
	typedef XALAN_STD_QUALIFIER equal_to<Key>	Comparator;
};

template <class Key>
struct XalanHashMemberPointer
{

	size_type operator() (const Key * key) const
	{
		assert (key != 0);
		return key->hash();
	}
};

template <class Key>
struct XalanHashMemberReference
{

	size_type operator() (const Key& key) const
	{
		return key.hash();
	}
};

/**
 * Xalan map entry pair of a key and data
 */

template <class Value>
struct XalanMapIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
};

template <class Value>
struct XalanMapConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
};

template <class XalanMapTraits, class BaseIterator>
struct XalanMapIterator
{
    typedef typename XalanMapTraits::value_type         value_type;
    typedef typename XalanMapTraits::reference          reference;
    typedef typename XalanMapTraits::pointer            pointer;

	typedef ptrdiff_t		                    difference_type;
	typedef XALAN_STD_QUALIFIER bidirectional_iterator_tag iterator_category;

    typedef XalanMapIterator<
		XalanMapIteratorTraits<value_type>,
  		BaseIterator>	                                Iterator;

    XalanMapIterator(const Iterator & theRhs) :
        baseIterator(theRhs.baseIterator)
    {
    }

    XalanMapIterator(const BaseIterator & theRhs) :
        baseIterator(theRhs)
    {
    }

    XalanMapIterator operator++(int)
    {
	    XalanMapIterator temp(*this);
	    ++baseIterator;
	    return temp;
    }

    XalanMapIterator& operator++()
    {
        ++baseIterator;
        return *this;
    }

    reference operator*() const
    {
        return *baseIterator->value;
    }

    pointer operator->() const
    {
        return baseIterator->value;
    }

    bool operator==(const XalanMapIterator& theRhs) const
    {
        return theRhs.baseIterator == baseIterator;
    }

    bool operator!=(const XalanMapIterator& theRhs) const
    {
        return !(theRhs == *this);
    }

    BaseIterator baseIterator;
};

/**
  * Xalan implementation of a hashtable.
  *
  */
template <
		class Key,
		class Value,
		class KeyTraits = XalanMapKeyTraits<Key> >
class XalanMap
{
public:
	/**
	 * Each map entry is stored in a linked list where an entry
     * consists of a pointer to the key/value pair and a flag to indicate
     * whether the entry has been erased.
     * The hash buckets are a vector of pointers into the entry list.
     * Deleted entries are spliced into another list and marked 'erased'.
     */

	typedef Key					key_type;
	typedef Value				data_type;
	typedef size_t				size_type;

	typedef XALAN_STD_QUALIFIER pair<const key_type, data_type>   value_type;

    struct Entry
    {
        value_type* value;
        bool        erased;

        Entry(value_type* theValue) :
            value(theValue),
            erased(false)
        {
        }
    };

    typedef XalanList<Entry>                                EntryListType;

    typedef XalanVector<typename EntryListType::iterator>	BucketType;
    typedef XalanVector<BucketType>                         BucketTableType;

    typedef XalanMapIterator<
                XalanMapIteratorTraits<value_type>,
                typename EntryListType::iterator>           iterator;
    typedef XalanMapIterator<
                XalanMapConstIteratorTraits<value_type>,
                typename EntryListType::iterator>     const_iterator;

    typedef typename MemoryManagedConstructionTraits<key_type>::Constructor  FirstConstructor;
    typedef typename MemoryManagedConstructionTraits<data_type>::Constructor SecondConstructor;

	XalanMap(
			MemoryManagerType& theMemoryManager,
			float loadFactor = 0.75,
			size_type minBuckets = 10) :
		m_memoryManager(&theMemoryManager),
		m_loadFactor(loadFactor),
		m_minBuckets(minBuckets),
		m_size(0),
		m_entries(theMemoryManager),
        m_freeEntries(theMemoryManager),
		m_buckets(theMemoryManager)
	{
	}

	XalanMap(
			const XalanMap &theRhs,
			MemoryManagerType&  theMemoryManager) :
        m_memoryManager(&theMemoryManager),
		m_loadFactor(theRhs.m_loadFactor),
		m_minBuckets(10),
		m_size(0),
		m_entries(theMemoryManager),
        m_freeEntries(theMemoryManager),
		m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, BucketType(*m_memoryManager), theMemoryManager)
	{
		const_iterator entry = theRhs.begin();
		while(entry != theRhs.end())
		{
			insert(*entry);
			++entry;
		}

		assert(m_size == theRhs.m_size);
	}

    MemoryManagerType&
    getMemoryManager()
    {
        assert (m_memoryManager != 0);

        return *m_memoryManager;
    }

	~XalanMap()
	{
        doRemoveEntries();

        if (!m_buckets.empty())
        {
            EntryListType::iterator toRemove = m_freeEntries.begin();
            while(toRemove != m_freeEntries.end())
            {
                deallocate(toRemove->value);
                ++toRemove;
            }
        }
	}

	XalanMap & operator=(const XalanMap& theRhs)
	{
		XalanMap theTemp(theRhs, *m_memoryManager);
		swap(theTemp);
		return *this;
	}

	size_type size() const
	{
		return m_size;
	}

	bool empty() const
    {
		return m_size == 0;
	}

	iterator begin()
	{
		return m_entries.begin();
	}

	const_iterator begin() const
	{
        return  const_cast<XalanMap*>(this)->begin();
	}

	iterator end()
	{
		return m_entries.end();
	}

	const_iterator end() const
	{
        return const_cast<XalanMap*>(this)->end();
	}

	iterator find(const key_type& key)
	{
		if (!m_buckets.empty())
		{
			const size_type     index = doHash(key);
            assert(index < m_buckets.size());

            BucketType & bucket = m_buckets[index];
            typename BucketType::iterator pos = bucket.begin();

			while (pos != bucket.end())
			{
				if (!(*pos)->erased && m_equals(key, (*pos)->value->first))
				{
					return iterator(*pos);
				}
				++pos;
			}
		}

		return end();
	}

	const_iterator find(const key_type& key) const
	{
		return const_cast<XalanMap *>(this)->find(key);
	}

	data_type & operator[](const key_type& key)
	{
		iterator pos = find(key);

		if (pos == end())
		{
			pos = doCreateEntry(key);
		}

		return (*pos).second;
	}

	void insert(const value_type& value)
	{
		const key_type& key = value.first;
		const data_type& data = value.second;

		insert(key, data);
	}

    void insert(const key_type& key, const data_type& data)
	{
		const const_iterator    pos = find(key);

		if (pos == end())
		{
			doCreateEntry(key, &data);
		}
	}

	void erase(iterator pos)
	{
		if (pos != end())
		{
			doRemoveEntry(pos);
		}
	}

	size_type erase(const key_type& key)
	{
		const iterator  pos = find(key);

        if (pos != end())
        {
		    erase(pos);
            return 1;
        }
        else
        {
            return 0;
        }
	}

	void clear()
	{
        doRemoveEntries();

		BucketTableType::iterator bucketPos = m_buckets.begin();
		while (bucketPos != m_buckets.end())
		{
			bucketPos->clear();
			++bucketPos;
		}

        assert(0 == m_size);
        assert(m_entries.empty());
    }

	void swap(XalanMap& theRhs)
	{
		size_type tempSize = m_size;
		m_size = theRhs.m_size;
		theRhs.m_size = tempSize;

		MemoryManagerType* tempMemoryManager = m_memoryManager;
		m_memoryManager = theRhs.m_memoryManager;
		theRhs.m_memoryManager = tempMemoryManager;

		m_entries.swap(theRhs.m_entries);
        m_freeEntries.swap(theRhs.m_freeEntries);
		m_buckets.swap(theRhs.m_buckets);
	}

protected:

    iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
	{
		// if there are no buckets, create initial minimum set of buckets
		if (m_buckets.empty())
		{
			m_buckets.insert(m_buckets.begin(), m_minBuckets, BucketType(*m_memoryManager));
		}

		// if the load factor has been reached, rehash
		if (size_type(m_loadFactor * size()) > m_buckets.size())
		{
			rehash();
		}

		size_type index = doHash(key);

        if (m_freeEntries.empty())
        {
            m_freeEntries.push_back(Entry(allocate(1)));
        }

        // insert a new entry as the first position in the bucket
        Entry& newEntry = m_freeEntries.back();
        newEntry.erased = false;

        FirstConstructor::construct(const_cast<key_type*>(&newEntry.value->first), key, *m_memoryManager);
        if (data != 0)
        {
            SecondConstructor::construct(&newEntry.value->second, *data, *m_memoryManager);
        }
        else
        {
             SecondConstructor::construct(&newEntry.value->second, *m_memoryManager);
        }

        m_entries.splice(m_entries.end(), m_freeEntries, --m_freeEntries.end());

        m_buckets[index].push_back(--m_entries.end());

        ++m_size;

		return iterator(--m_entries.end());
	}

	void doRemoveEntry(const iterator & toRemovePos)
	{
        value_type& toRemove = *toRemovePos;
#if defined(_MSC_VER) && _MSC_VER <= 1300
        toRemove.value_type::~value_type();
#else
        toRemove.~value_type();
#endif
        m_freeEntries.splice(
                m_freeEntries.end(),
                m_entries,
                toRemovePos.baseIterator);

        toRemovePos.baseIterator->erased = true;

		--m_size;
	}

    void
    doRemoveEntries()
    {
        while(size() > 0)
        {
            doRemoveEntry(begin());
        }
    }

	size_type doHash(const Key & key) const
	{
		return m_hash(key) % m_buckets.size();
	}

	void rehash()
	{
		// grow the number of buckets by 60%
		BucketTableType temp(size_type(1.6 * size()), BucketType(*m_memoryManager), *m_memoryManager);
		m_buckets.swap(temp);

        // rehash each entry assign to bucket and insert into list
		EntryListType::iterator entryPos = m_entries.begin();
		while (entryPos != m_entries.end())
		{
        	size_type index = doHash(entryPos->value->first);
			m_buckets[index].push_back(entryPos);
            ++entryPos;
		}
	}

    value_type*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(value_type);

        assert( m_memoryManager != 0 );

        void*   pointer = m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return (value_type*) pointer;
    }

    void
    deallocate(value_type*  pointer)
    {
        if (m_memoryManager == 0)
        {
            ::operator delete(pointer);
        }
        else
        {
            m_memoryManager->deallocate(pointer);
        }
    }

	// Data members...
	typename KeyTraits::Hasher			m_hash;

	typename KeyTraits::Comparator		m_equals;

    MemoryManagerType*					m_memoryManager;

	float								m_loadFactor;

	size_type							m_minBuckets;

	size_type							m_size;

    EntryListType						m_entries;

    EntryListType                       m_freeEntries;

    BucketTableType 					m_buckets;

private:
    // not defined
    XalanMap();
    XalanMap(const XalanMap&);
};

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

XALAN_CPP_NAMESPACE_END

#endif  // XALANMAP_HEADER_GUARD_1357924680

<|endoftext|>