<commit_before>#define BOOST_TEST_MODULE TEST_TRAINER_IO
/*
 * There are two different macros to test an optimizer:
 * - DYNET_TRAINER_IO_TEST_CASE:
 *   makes two updates of a model. Parameters of the model and the optimizer
 *   are save after the first update. Then, a new model and a new optimizer
 *   are created and populated with the saved data.
 *   The two models must be equal after updating the second one.
 * - DYNET_TRAINER_IO_PARAM_TEST_CASE:
 *   this is a save/load test for a given attribute of the optimizer
 *
 * TODO: EGTrainer is no fully tested because the update does not change
 *       the model.
 */

#include <fstream>
#include <boost/test/unit_test.hpp>
#include <boost/version.hpp>

#include <dynet/dynet.h>
#include <dynet/expr.h>
#include <dynet/training.h>
#include <dynet/io.h>

#include "test.h"

using namespace dynet;
using namespace std;

struct TrainerIOTest {
  TrainerIOTest() {
    // initialize if necessary
    if(default_device == nullptr) {
      for (auto x : {"TrainerTest", "--dynet-mem", "10"}) {
        av.push_back(strdup(x));
      }
      ADD_EXTRA_ARGUMENTS(av)
      char **argv = &av[0];
      int argc = av.size();
      dynet::initialize(argc, argv);
    }
    ones_vals = {1.f,1.f,1.f};
    param_vals = {0.5f,0.1f,0.4f};
  }

  ~TrainerIOTest() {
    for (auto x : av) free(x);
  }

  template <class T>
  std::string print_vec(const std::vector<T> vec) {
    ostringstream oss;
    if(vec.size()) oss << vec[0];
    for(size_t i = 1; i < vec.size(); i++)
      oss << ' ' << vec[i];
    return oss.str();
  }

    Parameter build_pc(ParameterCollection& pc)
    {
        auto p = pc.add_parameters({3});
        TensorTools::set_elements(p.get_storage().values, param_vals);
        return p;
    }

    Expression build_loss(ComputationGraph& cg, Parameter& param)
    {
        auto x = parameter(cg, param);
        auto y = input(cg, {3}, ones_vals);
        return dot_product(x, y);
    }

    dynet::real optimize(Parameter& param, Trainer& trainer)
    {
        dynet::ComputationGraph cg;
        auto z = build_loss(cg, param);
        auto loss = as_scalar(cg.forward(z));
        cg.backward(z);
        trainer.update();

        return loss;
    }

  std::vector<float> ones_vals, param_vals, param2_vals;
  std::vector<char*> av;
};

BOOST_FIXTURE_TEST_SUITE(trainer_io_test, TrainerIOTest);

#define DYNET_TRAINER_IO_TEST_CASE(name, TRAINER_TYPE)          \
BOOST_AUTO_TEST_CASE(name) {                                    \
    /* build model */                                           \
    ParameterCollection m;                                      \
    TRAINER_TYPE trainer(m);                                    \
    auto p = build_pc(m);                                       \
    /* do one update and save params */                         \
    float loss1;                                                \
    loss1 = optimize(p, trainer);                               \
    {                                                           \
        dynet::TextFileSaver s("test.model");                   \
        s.save(m);                                              \
        std::ofstream f;                                        \
        f.open("test.optimizer");                               \
        trainer.save(f);                                        \
        f.close();                                              \
    }                                                           \
    /* do a second update and check that the loss where different */ \
    /* i.e. that the params of the model are actually different */ \
    auto loss2 = optimize(p, trainer);                          \
    BOOST_CHECK(!(abs(loss1 - loss2)/abs(loss1) <= TOL && abs(loss1 - loss2)/abs(loss2) <= TOL)); \
    /*create a new model, load the save state+trainer params, */ \
    /* do one update and check that everything match */         \
    ParameterCollection m2;                                     \
    TRAINER_TYPE trainer2(m2);                                  \
    auto p2 = build_pc(m2);                                     \
    {                                                           \
        dynet::TextFileLoader s("test.model");                  \
        s.populate(m2);                                         \
        std::ifstream f;                                        \
        f.open("test.optimizer");                               \
        trainer2.populate(f);                                   \
        f.close();                                              \
    }                                                           \
    auto loss3 = optimize(p2, trainer2);                        \
    DYNET_CHECK_EQUAL(loss2, loss3);                            \
    DYNET_CHECK_EQUAL(m2, m);                                   \
}                                                               \

#define DYNET_TRAINER_IO_PARAM_TEST_CASE(name, TRAINER_TYPE, SP_NAME) \
BOOST_AUTO_TEST_CASE(name)                                      \
{                                                               \
    class Trainer : public TRAINER_TYPE                         \
    {                                                           \
        public:                                                 \
            using TRAINER_TYPE::SP_NAME;                        \
            explicit Trainer(ParameterCollection& m) : \
                TRAINER_TYPE::TRAINER_TYPE(m) \
                {} \
    };                                                          \
    /* build model */                                           \
    ParameterCollection m;                                      \
    Trainer trainer(m);                                    \
    auto p = build_pc(m);                                       \
    /* do one update and save params */                         \
    optimize(p, trainer);                                       \
    {                                                           \
        std::ofstream f;                                        \
        f.open("test.optimizer");                               \
        trainer.save(f);                                        \
        f.close();                                              \
    }                                                           \
    /*create a new model, load the save state params, */        \
    ParameterCollection m2;                                     \
    Trainer trainer2(m2);                                  \
    auto p2 = build_pc(m2);                                     \
    {                                                           \
        std::ifstream f;                                        \
        f.open("test.optimizer");                               \
        trainer2.populate(f);                                   \
        f.close();                                              \
    }                                                           \
    DYNET_CHECK_EQUAL(trainer2.SP_NAME, trainer.SP_NAME);                 \
}                                                               \

DYNET_TRAINER_IO_PARAM_TEST_CASE(momentum_sgd_io_param_vp, MomentumSGDTrainer, vp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(momentum_sgd_io_param_vlp, MomentumSGDTrainer, vlp)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adagrad_io_param_vp, AdagradTrainer, vp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adagrad_io_param_vlp, AdagradTrainer, vlp)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hg, AdadeltaTrainer, hg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hlg, AdadeltaTrainer, hlg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hd, AdadeltaTrainer, hd)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hld, AdadeltaTrainer, hld)

DYNET_TRAINER_IO_PARAM_TEST_CASE(rmsprop_io_param_hmsg, RMSPropTrainer, hmsg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(rmsprop_io_param_hlmsg, RMSPropTrainer, hlmsg)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_m, AdamTrainer, m)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_lm, AdamTrainer, lm)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_v, AdamTrainer, v)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_lv, AdamTrainer, lv)

DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_m, AmsgradTrainer, m)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lm, AmsgradTrainer, lm)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_v, AmsgradTrainer, v)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lv, AmsgradTrainer, lv)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_vhat, AmsgradTrainer, vhat)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lvhat, AmsgradTrainer, lvhat)

DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_hp, EGTrainer, hp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_hlp, EGTrainer, hlp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_zeg, EGTrainer, zeg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_meg, EGTrainer, meg)

DYNET_TRAINER_IO_TEST_CASE(simple_sgd_io, SimpleSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(cyclical_sgd_io, CyclicalSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(momentum_sgd_io, MomentumSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(adagrad_io, AdagradTrainer)
DYNET_TRAINER_IO_TEST_CASE(adadelta_io, AdadeltaTrainer)
DYNET_TRAINER_IO_TEST_CASE(rmsprop_io, RMSPropTrainer)
DYNET_TRAINER_IO_TEST_CASE(adam_io, AdamTrainer)
DYNET_TRAINER_IO_TEST_CASE(amsgrad_io, AmsgradTrainer)
//DYNET_TRAINER_IO_TEST_CASE(eg_io, EGTrainer)

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Remove useless method+attribute in the trainers-io test<commit_after>#define BOOST_TEST_MODULE TEST_TRAINER_IO
/*
 * There are two different macros to test an optimizer:
 * - DYNET_TRAINER_IO_TEST_CASE:
 *   makes two updates of a model. Parameters of the model and the optimizer
 *   are save after the first update. Then, a new model and a new optimizer
 *   are created and populated with the saved data.
 *   The two models must be equal after updating the second one.
 * - DYNET_TRAINER_IO_PARAM_TEST_CASE:
 *   this is a save/load test for a given attribute of the optimizer
 *
 * TODO: EGTrainer is no fully tested because the update does not change
 *       the model.
 */

#include <fstream>
#include <boost/test/unit_test.hpp>
#include <boost/version.hpp>

#include <dynet/dynet.h>
#include <dynet/expr.h>
#include <dynet/training.h>
#include <dynet/io.h>

#include "test.h"

using namespace dynet;
using namespace std;

struct TrainerIOTest {
  TrainerIOTest() {
    // initialize if necessary
    if(default_device == nullptr) {
      for (auto x : {"TrainerTest", "--dynet-mem", "10"}) {
        av.push_back(strdup(x));
      }
      ADD_EXTRA_ARGUMENTS(av)
      char **argv = &av[0];
      int argc = av.size();
      dynet::initialize(argc, argv);
    }
    ones_vals = {1.f,1.f,1.f};
    param_vals = {0.5f,0.1f,0.4f};
  }

  ~TrainerIOTest() {
    for (auto x : av) free(x);
  }

    Parameter build_pc(ParameterCollection& pc)
    {
        auto p = pc.add_parameters({3});
        TensorTools::set_elements(p.get_storage().values, param_vals);
        return p;
    }

    Expression build_loss(ComputationGraph& cg, Parameter& param)
    {
        auto x = parameter(cg, param);
        auto y = input(cg, {3}, ones_vals);
        return dot_product(x, y);
    }

    dynet::real optimize(Parameter& param, Trainer& trainer)
    {
        dynet::ComputationGraph cg;
        auto z = build_loss(cg, param);
        auto loss = as_scalar(cg.forward(z));
        cg.backward(z);
        trainer.update();

        return loss;
    }

  std::vector<float> ones_vals, param_vals;
  std::vector<char*> av;
};

BOOST_FIXTURE_TEST_SUITE(trainer_io_test, TrainerIOTest);

#define DYNET_TRAINER_IO_TEST_CASE(name, TRAINER_TYPE)          \
BOOST_AUTO_TEST_CASE(name) {                                    \
    /* build model */                                           \
    ParameterCollection m;                                      \
    TRAINER_TYPE trainer(m);                                    \
    auto p = build_pc(m);                                       \
    /* do one update and save params */                         \
    float loss1;                                                \
    loss1 = optimize(p, trainer);                               \
    {                                                           \
        dynet::TextFileSaver s("test.model");                   \
        s.save(m);                                              \
        std::ofstream f;                                        \
        f.open("test.optimizer");                               \
        trainer.save(f);                                        \
        f.close();                                              \
    }                                                           \
    /* do a second update and check that the loss where different */ \
    /* i.e. that the params of the model are actually different */ \
    auto loss2 = optimize(p, trainer);                          \
    BOOST_CHECK(!(abs(loss1 - loss2)/abs(loss1) <= TOL && abs(loss1 - loss2)/abs(loss2) <= TOL)); \
    /*create a new model, load the save state+trainer params, */ \
    /* do one update and check that everything match */         \
    ParameterCollection m2;                                     \
    TRAINER_TYPE trainer2(m2);                                  \
    auto p2 = build_pc(m2);                                     \
    {                                                           \
        dynet::TextFileLoader s("test.model");                  \
        s.populate(m2);                                         \
        std::ifstream f;                                        \
        f.open("test.optimizer");                               \
        trainer2.populate(f);                                   \
        f.close();                                              \
    }                                                           \
    auto loss3 = optimize(p2, trainer2);                        \
    DYNET_CHECK_EQUAL(loss2, loss3);                            \
    DYNET_CHECK_EQUAL(m2, m);                                   \
}                                                               \

#define DYNET_TRAINER_IO_PARAM_TEST_CASE(name, TRAINER_TYPE, SP_NAME) \
BOOST_AUTO_TEST_CASE(name)                                      \
{                                                               \
    class Trainer : public TRAINER_TYPE                         \
    {                                                           \
        public:                                                 \
            using TRAINER_TYPE::SP_NAME;                        \
            explicit Trainer(ParameterCollection& m) : \
                TRAINER_TYPE::TRAINER_TYPE(m) \
                {} \
    };                                                          \
    /* build model */                                           \
    ParameterCollection m;                                      \
    Trainer trainer(m);                                    \
    auto p = build_pc(m);                                       \
    /* do one update and save params */                         \
    optimize(p, trainer);                                       \
    {                                                           \
        std::ofstream f;                                        \
        f.open("test.optimizer");                               \
        trainer.save(f);                                        \
        f.close();                                              \
    }                                                           \
    /*create a new model, load the save state params, */        \
    ParameterCollection m2;                                     \
    Trainer trainer2(m2);                                  \
    auto p2 = build_pc(m2);                                     \
    {                                                           \
        std::ifstream f;                                        \
        f.open("test.optimizer");                               \
        trainer2.populate(f);                                   \
        f.close();                                              \
    }                                                           \
    DYNET_CHECK_EQUAL(trainer2.SP_NAME, trainer.SP_NAME);                 \
}                                                               \

DYNET_TRAINER_IO_PARAM_TEST_CASE(momentum_sgd_io_param_vp, MomentumSGDTrainer, vp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(momentum_sgd_io_param_vlp, MomentumSGDTrainer, vlp)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adagrad_io_param_vp, AdagradTrainer, vp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adagrad_io_param_vlp, AdagradTrainer, vlp)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hg, AdadeltaTrainer, hg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hlg, AdadeltaTrainer, hlg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hd, AdadeltaTrainer, hd)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adadelta_io_param_hld, AdadeltaTrainer, hld)

DYNET_TRAINER_IO_PARAM_TEST_CASE(rmsprop_io_param_hmsg, RMSPropTrainer, hmsg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(rmsprop_io_param_hlmsg, RMSPropTrainer, hlmsg)

DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_m, AdamTrainer, m)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_lm, AdamTrainer, lm)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_v, AdamTrainer, v)
DYNET_TRAINER_IO_PARAM_TEST_CASE(adam_io_param_lv, AdamTrainer, lv)

DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_m, AmsgradTrainer, m)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lm, AmsgradTrainer, lm)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_v, AmsgradTrainer, v)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lv, AmsgradTrainer, lv)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_vhat, AmsgradTrainer, vhat)
DYNET_TRAINER_IO_PARAM_TEST_CASE(amsgrad_io_param_lvhat, AmsgradTrainer, lvhat)

DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_hp, EGTrainer, hp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_hlp, EGTrainer, hlp)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_zeg, EGTrainer, zeg)
DYNET_TRAINER_IO_PARAM_TEST_CASE(eg_io_param_meg, EGTrainer, meg)

DYNET_TRAINER_IO_TEST_CASE(simple_sgd_io, SimpleSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(cyclical_sgd_io, CyclicalSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(momentum_sgd_io, MomentumSGDTrainer)
DYNET_TRAINER_IO_TEST_CASE(adagrad_io, AdagradTrainer)
DYNET_TRAINER_IO_TEST_CASE(adadelta_io, AdadeltaTrainer)
DYNET_TRAINER_IO_TEST_CASE(rmsprop_io, RMSPropTrainer)
DYNET_TRAINER_IO_TEST_CASE(adam_io, AdamTrainer)
DYNET_TRAINER_IO_TEST_CASE(amsgrad_io, AmsgradTrainer)
//DYNET_TRAINER_IO_TEST_CASE(eg_io, EGTrainer)

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>
#include <assert.h>
#include <thread>
#include <boost/atomic.hpp>

#include "LinkedList.hpp"

void test0() {
	LinkedList<int> l;
	assert(l.empty());
	l._checkSanity();

	auto item = l.push_back();
	item->value = 42;
	item = NULL;
	l._checkSanity();
	assert(!l.empty());
	assert(l.size() == 1);

	auto ret = l.pop_front();
	assert(ret);
	assert(ret->value == 42);
	ret = NULL;

	assert(l.empty());
	assert(l.size() == 0);
	l._checkSanity();
}

void test1() {
	LinkedList<int> l;
	l._checkSanity();

	for(int i = 0; i < 100; ++i) {
		auto item = l.push_back();
		l._checkSanity();
		item->value = i;
	}

	assert(!l.empty());
	assert(l.size() == 100);

	for(int i = 0; i < 100; ++i) {
		auto ret = l.pop_front();
		l._checkSanity();
		assert(ret);
		assert(ret->value == i);
	}

	assert(l.empty());
}

void test2() {
	LinkedList<int> l;
	l._checkSanity();

	auto producer = [&l](){
		for(int i = 0; i < 100; ++i) {
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			l.push_back(item);
		}
	};

	auto consumer = [&l](){
		for(int i = 0; i < 100; ++i) {
			while(l.empty()) {} // wait for entry
			auto ret = l.pop_front();
			assert(ret);
			assert(ret->value == i);
		}
	};

	for(int i = 0; i < 1000; ++i) {
		std::thread t1(producer), t2(consumer);
		t1.join();
		t2.join();
		assert(l.empty());
		l._checkSanity();
	}
}

void test3() {
	LinkedList<int> l;
	boost::atomic<int> state;

	auto producer = [&l, &state](){
		for(int i = 0; i < 100; ++i) {
			if(i == 50) state++;
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			l.push_back(item);
		}
		state++;
	};

	auto consumer = [&l, &state](){
		while(state == 0) {}
		for(int i = 0; i < 40; ++i) {
			while(l.empty()); // wait for entry
			auto ret = l.pop_front();
			assert(ret);
			assert(ret->value == i);
		}
		state++;
	};

	auto reader = [&l, &state]() {
		while(state < 3) {
			if(state == 0) continue;
			int first = -1;
			int old = -1;
			int count = 0;
			for(auto v : l) {
				assert(v >= 0);
				if(first < 0) first = v;
				if(old >= 0) assert(old < v);
				old = v;
				++count;
			}
			assert(count > 10);
		}
	};

	for(int i = 0; i < 1000; ++i) {
		state = 0;

		std::thread t1(producer), t2(consumer), t3(reader);
		t1.join();
		t2.join();
		t3.join();

		l._checkSanity();
		l.clear();
	}
}

void test4() {
	LinkedList<int> l;

	auto producer = [&l](){
		for(int i = 3; i <= 100; ++i) {
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			if(i < 50)
				l.push_back(item);
			else
				l.push_front(item);
		}
	};

	auto reader = [&l]() {
		int endCount = 0;
		while(true) {
			int old = -1;
			int m = 0;
			int count = 0;
			for(auto v : l) {
				assert(v >= 1);
				if(old >= 50 && v == 1) {}
				else if(old >= 0) assert(old + 1 == v);
				old = v;
				if(v > m) m = v;
				++count;
			}
			assert(count >= 2);
			assert(count <= 100);
			assert(count == m);
			if(count < 100) assert(endCount == 0);
			if(count == 100) endCount++;
			if(endCount >= 10) break;
		}
	};

	for(int i = 0; i < 1000; ++i) {
		l.push_back()->value = 1;
		l.push_back()->value = 2;

		std::thread t1(producer), t3(reader);
		t1.join();
		t3.join();

		l._checkSanity();
		l.clear();
	}
}

int main() {
	test0();
	test1();
	test2();
	test3();
	test4();
}
<commit_msg>small fix<commit_after>
#include <assert.h>
#include <thread>
#include <boost/atomic.hpp>

#include "LinkedList.hpp"

void test0() {
	LinkedList<int> l;
	assert(l.empty());
	l._checkSanity();

	auto item = l.push_back();
	item->value = 42;
	item = NULL;
	l._checkSanity();
	assert(!l.empty());
	assert(l.size() == 1);

	auto ret = l.pop_front();
	assert(ret);
	assert(ret->value == 42);
	ret = NULL;

	assert(l.empty());
	assert(l.size() == 0);
	l._checkSanity();
}

void test1() {
	LinkedList<int> l;
	l._checkSanity();

	for(int i = 0; i < 100; ++i) {
		auto item = l.push_back();
		l._checkSanity();
		item->value = i;
	}

	assert(!l.empty());
	assert(l.size() == 100);

	for(int i = 0; i < 100; ++i) {
		auto ret = l.pop_front();
		l._checkSanity();
		assert(ret);
		assert(ret->value == i);
	}

	assert(l.empty());
}

void test2() {
	LinkedList<int> l;
	l._checkSanity();

	auto producer = [&l](){
		for(int i = 0; i < 100; ++i) {
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			l.push_back(item);
		}
	};

	auto consumer = [&l](){
		for(int i = 0; i < 100; ++i) {
			while(l.empty()) {} // wait for entry
			auto ret = l.pop_front();
			assert(ret);
			assert(ret->value == i);
		}
	};

	for(int i = 0; i < 1000; ++i) {
		std::thread t1(producer), t2(consumer);
		t1.join();
		t2.join();
		assert(l.empty());
		l._checkSanity();
	}
}

void test3() {
	LinkedList<int> l;
	boost::atomic<int> state;

	auto producer = [&l, &state](){
		for(int i = 0; i < 100; ++i) {
			if(i == 50) state++;
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			l.push_back(item);
		}
		state++;
	};

	auto consumer = [&l, &state](){
		while(state == 0) {}
		for(int i = 0; i < 40; ++i) {
			while(l.empty()); // wait for entry
			auto ret = l.pop_front();
			assert(ret);
			assert(ret->value == i);
		}
		state++;
	};

	auto reader = [&l, &state]() {
		while(state < 3) {
			if(state == 0) continue;
			int first = -1;
			int old = -1;
			int count = 0;
			for(auto v : l) {
				assert(v >= 0);
				if(first < 0) first = v;
				if(old >= 0) assert(old < v);
				old = v;
				++count;
			}
			assert(count > 10);
		}
	};

	for(int i = 0; i < 1000; ++i) {
		state = 0;

		std::thread t1(producer), t2(consumer), t3(reader);
		t1.join();
		t2.join();
		t3.join();

		l._checkSanity();
		l.clear();
	}
}

void test4() {
	LinkedList<int> l;

	auto producer = [&l](){
		for(int i = 3; i <= 100; ++i) {
			LinkedList<int>::ItemPtr item(new LinkedList<int>::Item);
			item->value = i;
			if(i < 50)
				l.push_back(item);
			else
				l.push_front(item);
		}
	};

	auto reader = [&l]() {
		int endCount = 0;
		while(true) {
			int old = -1;
			int m = 0;
			int count = 0;
			for(auto v : l) {
				assert(v >= 1);
				if(old >= 50 && v == 1) {}
				else if(old >= 50) assert(old - 1 == v);
				else if(old >= 0) assert(old + 1 == v);
				old = v;
				if(v > m) m = v;
				++count;
			}
			assert(count >= 2);
			assert(count <= 100);
			assert(count == m);
			if(count >= 50) assert(old == 49);
			if(count < 100) assert(endCount == 0);
			if(count == 100) endCount++;
			if(endCount >= 10) break;
		}
	};

	for(int i = 0; i < 1000; ++i) {
		l.push_back()->value = 1;
		l.push_back()->value = 2;

		std::thread t1(producer), t3(reader);
		t1.join();
		t3.join();

		l._checkSanity();
		l.clear();
	}
}

int main() {
	test0();
	test1();
	test2();
	test3();
	test4();
}
<|endoftext|>


<commit_before>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of cdf-handler, a C++ server of OPeNDAP for access to cdf
// data

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: Patrick West <pwest@ucar.edu>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// Implementation for CDFHandlerApp.
//
// pwest 05/08/03

// CDFHandlerApp.cc

#ifdef __GNUG__
#pragma implementation
#endif

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

#include <iostream>

using std::cout ;
using std::cerr ;
using std::endl ;
using std::flush ;

#include "CDFHandlerApp.h"
#include "CDFResponseNames.h"
#include "DODSFilter.h"
#include "DODSCgi.h"

CDFHandlerApp::CDFHandlerApp()
    : _df( 0 )
{
}

CDFHandlerApp::~CDFHandlerApp()
{
    if( _df )
    {
	delete _df ;
	_df = 0 ;
    }
}

int
CDFHandlerApp::initialize( int argc, char **argv )
{
    OPeNDAPBaseApp::initialize( argc, argv ) ;

    _df = new DODSFilter( argc, argv ) ;

    return 0 ;
}

int
CDFHandlerApp::run()
{
    DODSCgi d( CDF_NAME, *_df ) ;
    d.execute_request() ;

    return 0 ;
}

<commit_msg>default modules loaded in handler app<commit_after>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of cdf-handler, a C++ server of OPeNDAP for access to cdf
// data

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: Patrick West <pwest@ucar.edu>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// Implementation for CDFHandlerApp.
//
// pwest 05/08/03

// CDFHandlerApp.cc

#ifdef __GNUG__
#pragma implementation
#endif

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

#include <iostream>

using std::cout ;
using std::cerr ;
using std::endl ;
using std::flush ;

#include "CDFHandlerApp.h"
#include "CDFResponseNames.h"
#include "DODSFilter.h"
#include "DODSCgi.h"
#include "dods_module.h"
#include "opendap_commands.h"

CDFHandlerApp::CDFHandlerApp()
    : _df( 0 )
{
}

CDFHandlerApp::~CDFHandlerApp()
{
    if( _df )
    {
	delete _df ;
	_df = 0 ;
    }
}

int
CDFHandlerApp::initialize( int argc, char **argv )
{
    dods_module::initialize( argc, argv ) ;
    opendap_commands::initialize( argc, argv ) ;

    OPeNDAPBaseApp::initialize( argc, argv ) ;

    _df = new DODSFilter( argc, argv ) ;

    return 0 ;
}

int
CDFHandlerApp::run()
{
    DODSCgi d( CDF_NAME, *_df ) ;
    d.execute_request() ;

    return 0 ;
}

<|endoftext|>


<commit_before>/*Copyright 2011 George Karagoulis

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 "bst_t.h"
#include "Core/exception.h"
#include "gassert.h"
GUTIL_USING_CORE_NAMESPACE(DataObjects);
GUTIL_USING_CORE_NAMESPACE(Interfaces);

bst_t::bst_t(bst_t::void_wrapper *vw)
    :root(0),
      data_access_wrapper(vw),
      m_size(0)
{}

bst_t::~bst_t()
{
    // Note: We delete the compare interface because it has a virtual destructor
    //  so the rest of the object will get deleted too.
    Clear();
    delete data_access_wrapper;
}

bst_t::void_wrapper::~void_wrapper(){}

bst_node *bst_t::add(const void *const v)
{
    bst_node *new_node;
    if(root)
    {
        // Find the place to insert, has to be a leaf node
        bst_node *cur( root );
        bst_node *next_cur( root );
        SideEnum insertion_side(LeftSide);
        while(next_cur)
        {
            cur = next_cur;
            int cmp_res( data_access_wrapper->CompareVoid(v, cur->Data) );

            if(cmp_res < 0)
            {
                next_cur = cur->LChild;
                insertion_side = LeftSide;
            }
            else if(cmp_res > 0)
            {
                next_cur = cur->RChild;
                insertion_side = RightSide;
            }
            else
            {
                // There's an insertion collision
                THROW_NEW_GUTIL_EXCEPTION2(GUtil::Core::Exception,
                                           "Object already exists in BST.");
            }
        }

        new_node = new bst_node;
        switch(insertion_side)
        {
        case LeftSide:
            cur->LChild = new_node;
            break;
        case RightSide:
            cur->RChild = new_node;
            break;
        default:
            GASSERT(false);
        }
        new_node->Parent = cur;

        // Now we need to ascend the tree to the root and update the heights
        walk_parents_update_heights_rebalance(cur);

        _update_root_node();
    }
    else
    {
        // If the root is null, then this is the first item in the tree (easy case)
        root = new_node = new bst_node;
    }

    m_size++;

    new_node->Data = data_access_wrapper->CopyVoid(v);
    return new_node;
}

bool bst_t::remove(const const_iterator &iter)
{
    bst_node *cur(iter.current);
    if(cur)
    {
        // Remove it.  The deletion algorithm goes as follows:
        //  I need to find a replacement from the leaves of the tree to
        //  come take my place, then I will rebalance from the bottom of the tree.
        //  I will find a replacement as the left-most item on my right side, or my
        //  right-most item on my left side, whichever one is taller.

        // Find a replacement node
        bst_node *replacement(0);
        if(cur->Height > 0)
        {
            if(cur->HeightDifference() > 0)
            {
                // Left-heavy
                replacement = cur->LChild->RightmostChild;
            }
            else
            {
                // Right-heavy
                replacement = cur->RChild->LeftmostChild;
            }
        }

        if(root == cur)
        {
            // We have to pre-emptively adjust our root node, because we will be unable to
            //  find the new root once it's deleted.
            if(root->RChild)
                root = root->RChild;
            else if(root->LChild)
                root = root->LChild;
            else
                root = 0;
        }

        data_access_wrapper->DeleteVoid(cur->Data);

        // This variable determines where to start adjusting the node height after deletion.
        bst_node *start_height_adjustment(0);

        if(replacement)
        {
            // If the replacement has a child (at most 1) then we move it into the replacement's place
            bst_node *replacement_child(0);
            if(replacement->RChild)
                replacement_child = replacement->RChild;
            else if(replacement->LChild)
                replacement_child = replacement->LChild;

            if(cur == replacement->Parent)
                start_height_adjustment = replacement;
            else
            {
                start_height_adjustment = replacement->Parent;
                switch(replacement->SideOfParent())
                {
                case RightSide:
                    replacement->Parent->RChild = replacement_child;
                    break;
                case LeftSide:
                    replacement->Parent->LChild = replacement_child;
                    break;
                default:
                    break;
                }

                if(replacement_child)
                    replacement_child->Parent = replacement->Parent;
            }

            replacement->Parent = cur->Parent;
            if(replacement != cur->RChild)
                replacement->RChild = cur->RChild;
            if(replacement != cur->LChild)
                replacement->LChild = cur->LChild;
        }
        else
        {
            start_height_adjustment = cur->Parent;
        }

        if(cur->RChild && cur->RChild != replacement)
            cur->RChild->Parent = replacement;
        if(cur->LChild && cur->LChild != replacement)
            cur->LChild->Parent = replacement;
        if(cur->Parent)
        {
            switch(cur->SideOfParent())
            {
            case RightSide:
                cur->Parent->RChild = replacement;
                break;
            case LeftSide:
                cur->Parent->LChild = replacement;
                break;
            default:
                break;
            }
        }

        // Delete the node (set children to 0 so to not delete them)
        cur->LChild = 0;
        cur->RChild = 0;
        delete cur;

        // Walk up the tree and update the height variables.
        walk_parents_update_heights_rebalance(start_height_adjustment);

        _update_root_node();

        m_size--;
    }
    return cur;
}

bool bst_t::remove(const void *const v)
{
    return remove(const_iterator(search(v), data_access_wrapper));
}

bst_node *bst_t::search(const void *const v) const
{
    return search(v, data_access_wrapper);
}

bst_node *bst_t::search(const void *const v, const IVoidComparer *vw) const
{
    bst_node *cur( root );
    while(cur)
    {
        int cmp_res( vw->CompareVoid(cur->Data, v) );

        if(cmp_res < 0)
            cur = cur->RChild;
        else if(cmp_res > 0)
            cur = cur->LChild;
        else
            break;
    }
    return cur;
}

void bst_t::Clear()
{
    if(root)
    {
        _cleanup_memory(root);
        root = 0;
        m_size = 0;
    }
}

void bst_t::_cleanup_memory(bst_node *n)
{
    if(n->LChild)
    {
        _cleanup_memory(n->LChild);
        n->LChild = 0;
    }
    if(n->RChild)
    {
        _cleanup_memory(n->RChild);
        n->RChild = 0;
    }
    data_access_wrapper->DeleteVoid(n->Data);
    delete n;
}

bst_node *bst_t::first() const
{
    return root ? root->LeftmostChild : 0;
}

bst_node *bst_t::last() const
{
    return root ? root->RightmostChild : 0;
}

void bst_t::_update_root_node()
{
    bst_node *n(root);
    while(n && (n = n->Parent))
        root = n;
}

bst_t::const_iterator::const_iterator()
    :current(0),
      cmp(0),
      mem_begin(0),
      mem_end(0)
{}

bst_t::const_iterator::const_iterator(bst_node *n, const IVoidComparer *const vc)
    :current(n),
      cmp(vc),
      mem_begin(0),
      mem_end(0)
{}

bst_t::const_iterator::const_iterator(const bst_t::const_iterator &o)
    :current(o.current),
      cmp(o.cmp),
      mem_begin(o.mem_begin),
      mem_end(o.mem_end)
{}

bool bst_t::const_iterator::operator == (const bst_t::const_iterator &o) const
{
    return current == o.current &&
            (current != 0 ||
             ((mem_begin == 0 && mem_end == 0) || (o.mem_begin == 0 && o.mem_end == 0) ||
                 (mem_begin == o.mem_begin && mem_end == o.mem_end)));
}

bool bst_t::const_iterator::operator != (const bst_t::const_iterator &o) const
{
    return !(*this == o);
}

bst_t::const_iterator::operator bool() const
{
    return current;
}

void bst_t::const_iterator::advance()
{
    if(current)
    {
        if(current->RChild)
            current = current->RChild->LeftmostChild;
        else
        {
            // Ascend current's parents to find the next greater element
            bst_node *cur(current);
            do
            {
                if(cur->SideOfParent() == LeftSide)
                {
                    current = cur->Parent;
                    break;
                }
            }while((cur = cur->Parent));

            if(!cur)
            {
                // We've hit the end of the BST
                mem_end = current;
                current = 0;
            }
        }
    }
    else if(mem_begin)
    {
        current = mem_begin;
        mem_begin = 0;
    }
    else
        THROW_NEW_GUTIL_EXCEPTION2(GUtil::Core::Exception,
                                   "Can't move iterator past the end of the container.");
}

void bst_t::const_iterator::retreat()
{
    if(current)
    {
        if(current->LChild)
            current = current->LChild->RightmostChild;
        else
        {
            // Ascend current's parents to find the next lesser element
            bst_node *cur(current);
            do
            {
                if(cur->SideOfParent() == RightSide)
                {
                    current = cur->Parent;
                    break;
                }
            }while((cur = cur->Parent));

            if(!cur)
            {
                // We've hit the beginning of the BST
                mem_begin = current;
                current = 0;
            }
        }
    }
    else if(mem_end)
    {
        current = mem_end;
        mem_end = 0;
    }
    else
        THROW_NEW_GUTIL_EXCEPTION2(GUtil::Core::Exception,
                                   "Can't move iterator before the beginning of the container.");
}

bst_t::const_iterator &bst_t::const_iterator::operator ++()
{
    advance();
    return *this;
}

bst_t::const_iterator bst_t::const_iterator::operator ++(int)
{
    const_iterator ret(*this);
    advance();
    return ret;
}

bst_t::const_iterator &bst_t::const_iterator::operator --()
{
    retreat();
    return *this;
}

bst_t::const_iterator bst_t::const_iterator::operator --(int)
{
    const_iterator ret(*this);
    retreat();
    return ret;
}

bool bst_t::const_iterator::operator <(const bst_t::const_iterator &o) const
{
    if(current && o.current)
    {
        return cmp->CompareVoid(current->Data, o.current->Data) < 0;
    }
    else
    {
        if(current == 0 && o.current == 0){
            // I am at the beginning, o is at the end
            if(mem_begin && o.mem_end)
                return true;
            return false;
        }
        else if(current == 0)
        {
            // I am at the beginning, so I come before o
            return mem_begin;
        }
        else
        {
            // o is at the end, so I come before it
            return o.mem_end;
        }
    }
}

bool bst_t::const_iterator::operator > (const const_iterator &o) const
{
    return !(*this <= o);
}

bool bst_t::const_iterator::operator <= (const const_iterator &o) const
{
    return *this == o || *this < o;
}

bool bst_t::const_iterator::operator >= (const const_iterator &o) const
{
    return !(*this < o);
}

void bst_t::walk_parents_update_heights_rebalance(bst_node *n)
{
    if(n)
    {
        refresh_node_state(n);

        // Rebalance the node if it's unbalanced
        if(!n->Balanced())
            rebalance(n);

        walk_parents_update_heights_rebalance(n->Parent);
    }
}

void bst_t::refresh_node_state(bst_node *n)
{
    // Update the node's height cache
    if(!n->LChild && !n->RChild)
        n->Height = 0;
    else
    {
        const int lheight(n->LChild ? n->LChild->Height : 0);
        const int rheight(n->RChild ? n->RChild->Height : 0);
        n->Height = gMax(lheight, rheight) + 1;
    }

    // Update the left-most and right-most child caches
    n->LeftmostChild = n->LChild ? n->LChild->LeftmostChild : n;
    n->RightmostChild = n->RChild ? n->RChild->RightmostChild : n;
}

void bst_t::rotate_right(bst_node *n)
{
    bst_node *parent(n->Parent);
    if(parent)
    {
        if(parent->LChild == n)
            parent->LChild = n->LChild;
        else
            parent->RChild = n->LChild;
    }
    n->LChild->Parent = parent;

    bst_node *tmp(n->LChild->RChild);
    n->Parent = n->LChild;
    n->LChild->RChild = n;
    n->LChild = tmp;
    if(tmp)
        tmp->Parent = n;

    // Have to refresh the node we just rotated, the other one will be refreshed
    //  automatically when we walk up the tree
    refresh_node_state(n);
}

void bst_t::rotate_left(bst_node *n)
{
    bst_node *parent(n->Parent);
    if(parent)
    {
        if(parent->LChild == n)
            parent->LChild = n->RChild;
        else
            parent->RChild = n->RChild;
    }
    n->RChild->Parent = parent;

    bst_node *tmp(n->RChild->LChild);
    n->Parent = n->RChild;
    n->RChild->LChild = n;
    n->RChild = tmp;
    if(tmp)
        tmp->Parent = n;

    // Have to refresh the node we just rotated, the other one will be refreshed
    //  automatically when we walk up the tree
    refresh_node_state(n);
}

void bst_t::rebalance(bst_node *n)
{
    int height_difference = n->HeightDifference();
    if(height_difference > 1)
    {
        // The node is left-heavy

        // Check if it's LR imbalance so we can resolve that first.
        if(n->LChild->HeightDifference() < 0)
            rotate_left(n->LChild);

        // Now that the LR imbalance is fixed, do the LL rebalance.
        rotate_right(n);
    }
    else if(height_difference < -1)
    {
        // The node is right-heavy

        // Check if it's RL imbalance so we can resolve that first.
        if(n->RChild->HeightDifference() > 0)
            rotate_right(n->RChild);

        // Now that the RL imbalance is fixed, do the RR rebalance.
        rotate_left(n);
    }
}

bst_node *bst_t::const_iterator::operator->()
{
    return current;
}

const bst_node *bst_t::const_iterator::operator->() const
{
    return current;
}
const bst_node &bst_t::const_iterator::operator *() const
{
    return *current;
}
bst_node &bst_t::const_iterator::operator *()
{
    return *current;
}
<commit_msg>Do nothing if the user tries to increment the iterator past the end or before the beginning<commit_after>/*Copyright 2011 George Karagoulis

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 "bst_t.h"
#include "Core/exception.h"
#include "gassert.h"
GUTIL_USING_CORE_NAMESPACE(DataObjects);
GUTIL_USING_CORE_NAMESPACE(Interfaces);

bst_t::bst_t(bst_t::void_wrapper *vw)
    :root(0),
      data_access_wrapper(vw),
      m_size(0)
{}

bst_t::~bst_t()
{
    // Note: We delete the compare interface because it has a virtual destructor
    //  so the rest of the object will get deleted too.
    Clear();
    delete data_access_wrapper;
}

bst_t::void_wrapper::~void_wrapper(){}

bst_node *bst_t::add(const void *const v)
{
    bst_node *new_node;
    if(root)
    {
        // Find the place to insert, has to be a leaf node
        bst_node *cur( root );
        bst_node *next_cur( root );
        SideEnum insertion_side(LeftSide);
        while(next_cur)
        {
            cur = next_cur;
            int cmp_res( data_access_wrapper->CompareVoid(v, cur->Data) );

            if(cmp_res < 0)
            {
                next_cur = cur->LChild;
                insertion_side = LeftSide;
            }
            else if(cmp_res > 0)
            {
                next_cur = cur->RChild;
                insertion_side = RightSide;
            }
            else
            {
                // There's an insertion collision
                THROW_NEW_GUTIL_EXCEPTION2(GUtil::Core::Exception,
                                           "Object already exists in BST.");
            }
        }

        new_node = new bst_node;
        switch(insertion_side)
        {
        case LeftSide:
            cur->LChild = new_node;
            break;
        case RightSide:
            cur->RChild = new_node;
            break;
        default:
            GASSERT(false);
        }
        new_node->Parent = cur;

        // Now we need to ascend the tree to the root and update the heights
        walk_parents_update_heights_rebalance(cur);

        _update_root_node();
    }
    else
    {
        // If the root is null, then this is the first item in the tree (easy case)
        root = new_node = new bst_node;
    }

    m_size++;

    new_node->Data = data_access_wrapper->CopyVoid(v);
    return new_node;
}

bool bst_t::remove(const const_iterator &iter)
{
    bst_node *cur(iter.current);
    if(cur)
    {
        // Remove it.  The deletion algorithm goes as follows:
        //  I need to find a replacement from the leaves of the tree to
        //  come take my place, then I will rebalance from the bottom of the tree.
        //  I will find a replacement as the left-most item on my right side, or my
        //  right-most item on my left side, whichever one is taller.

        // Find a replacement node
        bst_node *replacement(0);
        if(cur->Height > 0)
        {
            if(cur->HeightDifference() > 0)
            {
                // Left-heavy
                replacement = cur->LChild->RightmostChild;
            }
            else
            {
                // Right-heavy
                replacement = cur->RChild->LeftmostChild;
            }
        }

        if(root == cur)
        {
            // We have to pre-emptively adjust our root node, because we will be unable to
            //  find the new root once it's deleted.
            if(root->RChild)
                root = root->RChild;
            else if(root->LChild)
                root = root->LChild;
            else
                root = 0;
        }

        data_access_wrapper->DeleteVoid(cur->Data);

        // This variable determines where to start adjusting the node height after deletion.
        bst_node *start_height_adjustment(0);

        if(replacement)
        {
            // If the replacement has a child (at most 1) then we move it into the replacement's place
            bst_node *replacement_child(0);
            if(replacement->RChild)
                replacement_child = replacement->RChild;
            else if(replacement->LChild)
                replacement_child = replacement->LChild;

            if(cur == replacement->Parent)
                start_height_adjustment = replacement;
            else
            {
                start_height_adjustment = replacement->Parent;
                switch(replacement->SideOfParent())
                {
                case RightSide:
                    replacement->Parent->RChild = replacement_child;
                    break;
                case LeftSide:
                    replacement->Parent->LChild = replacement_child;
                    break;
                default:
                    break;
                }

                if(replacement_child)
                    replacement_child->Parent = replacement->Parent;
            }

            replacement->Parent = cur->Parent;
            if(replacement != cur->RChild)
                replacement->RChild = cur->RChild;
            if(replacement != cur->LChild)
                replacement->LChild = cur->LChild;
        }
        else
        {
            start_height_adjustment = cur->Parent;
        }

        if(cur->RChild && cur->RChild != replacement)
            cur->RChild->Parent = replacement;
        if(cur->LChild && cur->LChild != replacement)
            cur->LChild->Parent = replacement;
        if(cur->Parent)
        {
            switch(cur->SideOfParent())
            {
            case RightSide:
                cur->Parent->RChild = replacement;
                break;
            case LeftSide:
                cur->Parent->LChild = replacement;
                break;
            default:
                break;
            }
        }

        // Delete the node (set children to 0 so to not delete them)
        cur->LChild = 0;
        cur->RChild = 0;
        delete cur;

        // Walk up the tree and update the height variables.
        walk_parents_update_heights_rebalance(start_height_adjustment);

        _update_root_node();

        m_size--;
    }
    return cur;
}

bool bst_t::remove(const void *const v)
{
    return remove(const_iterator(search(v), data_access_wrapper));
}

bst_node *bst_t::search(const void *const v) const
{
    return search(v, data_access_wrapper);
}

bst_node *bst_t::search(const void *const v, const IVoidComparer *vw) const
{
    bst_node *cur( root );
    while(cur)
    {
        int cmp_res( vw->CompareVoid(cur->Data, v) );

        if(cmp_res < 0)
            cur = cur->RChild;
        else if(cmp_res > 0)
            cur = cur->LChild;
        else
            break;
    }
    return cur;
}

void bst_t::Clear()
{
    if(root)
    {
        _cleanup_memory(root);
        root = 0;
        m_size = 0;
    }
}

void bst_t::_cleanup_memory(bst_node *n)
{
    if(n->LChild)
    {
        _cleanup_memory(n->LChild);
        n->LChild = 0;
    }
    if(n->RChild)
    {
        _cleanup_memory(n->RChild);
        n->RChild = 0;
    }
    data_access_wrapper->DeleteVoid(n->Data);
    delete n;
}

bst_node *bst_t::first() const
{
    return root ? root->LeftmostChild : 0;
}

bst_node *bst_t::last() const
{
    return root ? root->RightmostChild : 0;
}

void bst_t::_update_root_node()
{
    bst_node *n(root);
    while(n && (n = n->Parent))
        root = n;
}

bst_t::const_iterator::const_iterator()
    :current(0),
      cmp(0),
      mem_begin(0),
      mem_end(0)
{}

bst_t::const_iterator::const_iterator(bst_node *n, const IVoidComparer *const vc)
    :current(n),
      cmp(vc),
      mem_begin(0),
      mem_end(0)
{}

bst_t::const_iterator::const_iterator(const bst_t::const_iterator &o)
    :current(o.current),
      cmp(o.cmp),
      mem_begin(o.mem_begin),
      mem_end(o.mem_end)
{}

bool bst_t::const_iterator::operator == (const bst_t::const_iterator &o) const
{
    return current == o.current &&
            (current != 0 ||
             ((mem_begin == 0 && mem_end == 0) || (o.mem_begin == 0 && o.mem_end == 0) ||
                 (mem_begin == o.mem_begin && mem_end == o.mem_end)));
}

bool bst_t::const_iterator::operator != (const bst_t::const_iterator &o) const
{
    return !(*this == o);
}

bst_t::const_iterator::operator bool() const
{
    return current;
}

void bst_t::const_iterator::advance()
{
    if(current)
    {
        if(current->RChild)
            current = current->RChild->LeftmostChild;
        else
        {
            // Ascend current's parents to find the next greater element
            bst_node *cur(current);
            do
            {
                if(cur->SideOfParent() == LeftSide)
                {
                    current = cur->Parent;
                    break;
                }
            }while((cur = cur->Parent));

            if(!cur)
            {
                // We've hit the end of the BST
                mem_end = current;
                current = 0;
            }
        }
    }
    else if(mem_begin)
    {
        current = mem_begin;
        mem_begin = 0;
    }
}

void bst_t::const_iterator::retreat()
{
    if(current)
    {
        if(current->LChild)
            current = current->LChild->RightmostChild;
        else
        {
            // Ascend current's parents to find the next lesser element
            bst_node *cur(current);
            do
            {
                if(cur->SideOfParent() == RightSide)
                {
                    current = cur->Parent;
                    break;
                }
            }while((cur = cur->Parent));

            if(!cur)
            {
                // We've hit the beginning of the BST
                mem_begin = current;
                current = 0;
            }
        }
    }
    else if(mem_end)
    {
        current = mem_end;
        mem_end = 0;
    }
}

bst_t::const_iterator &bst_t::const_iterator::operator ++()
{
    advance();
    return *this;
}

bst_t::const_iterator bst_t::const_iterator::operator ++(int)
{
    const_iterator ret(*this);
    advance();
    return ret;
}

bst_t::const_iterator &bst_t::const_iterator::operator --()
{
    retreat();
    return *this;
}

bst_t::const_iterator bst_t::const_iterator::operator --(int)
{
    const_iterator ret(*this);
    retreat();
    return ret;
}

bool bst_t::const_iterator::operator <(const bst_t::const_iterator &o) const
{
    if(current && o.current)
    {
        return cmp->CompareVoid(current->Data, o.current->Data) < 0;
    }
    else
    {
        if(current == 0 && o.current == 0){
            // I am at the beginning, o is at the end
            if(mem_begin && o.mem_end)
                return true;
            return false;
        }
        else if(current == 0)
        {
            // I am at the beginning, so I come before o
            return mem_begin;
        }
        else
        {
            // o is at the end, so I come before it
            return o.mem_end;
        }
    }
}

bool bst_t::const_iterator::operator > (const const_iterator &o) const
{
    return !(*this <= o);
}

bool bst_t::const_iterator::operator <= (const const_iterator &o) const
{
    return *this == o || *this < o;
}

bool bst_t::const_iterator::operator >= (const const_iterator &o) const
{
    return !(*this < o);
}

void bst_t::walk_parents_update_heights_rebalance(bst_node *n)
{
    if(n)
    {
        refresh_node_state(n);

        // Rebalance the node if it's unbalanced
        if(!n->Balanced())
            rebalance(n);

        walk_parents_update_heights_rebalance(n->Parent);
    }
}

void bst_t::refresh_node_state(bst_node *n)
{
    // Update the node's height cache
    if(!n->LChild && !n->RChild)
        n->Height = 0;
    else
    {
        const int lheight(n->LChild ? n->LChild->Height : 0);
        const int rheight(n->RChild ? n->RChild->Height : 0);
        n->Height = gMax(lheight, rheight) + 1;
    }

    // Update the left-most and right-most child caches
    n->LeftmostChild = n->LChild ? n->LChild->LeftmostChild : n;
    n->RightmostChild = n->RChild ? n->RChild->RightmostChild : n;
}

void bst_t::rotate_right(bst_node *n)
{
    bst_node *parent(n->Parent);
    if(parent)
    {
        if(parent->LChild == n)
            parent->LChild = n->LChild;
        else
            parent->RChild = n->LChild;
    }
    n->LChild->Parent = parent;

    bst_node *tmp(n->LChild->RChild);
    n->Parent = n->LChild;
    n->LChild->RChild = n;
    n->LChild = tmp;
    if(tmp)
        tmp->Parent = n;

    // Have to refresh the node we just rotated, the other one will be refreshed
    //  automatically when we walk up the tree
    refresh_node_state(n);
}

void bst_t::rotate_left(bst_node *n)
{
    bst_node *parent(n->Parent);
    if(parent)
    {
        if(parent->LChild == n)
            parent->LChild = n->RChild;
        else
            parent->RChild = n->RChild;
    }
    n->RChild->Parent = parent;

    bst_node *tmp(n->RChild->LChild);
    n->Parent = n->RChild;
    n->RChild->LChild = n;
    n->RChild = tmp;
    if(tmp)
        tmp->Parent = n;

    // Have to refresh the node we just rotated, the other one will be refreshed
    //  automatically when we walk up the tree
    refresh_node_state(n);
}

void bst_t::rebalance(bst_node *n)
{
    int height_difference = n->HeightDifference();
    if(height_difference > 1)
    {
        // The node is left-heavy

        // Check if it's LR imbalance so we can resolve that first.
        if(n->LChild->HeightDifference() < 0)
            rotate_left(n->LChild);

        // Now that the LR imbalance is fixed, do the LL rebalance.
        rotate_right(n);
    }
    else if(height_difference < -1)
    {
        // The node is right-heavy

        // Check if it's RL imbalance so we can resolve that first.
        if(n->RChild->HeightDifference() > 0)
            rotate_right(n->RChild);

        // Now that the RL imbalance is fixed, do the RR rebalance.
        rotate_left(n);
    }
}

bst_node *bst_t::const_iterator::operator->()
{
    return current;
}

const bst_node *bst_t::const_iterator::operator->() const
{
    return current;
}
const bst_node &bst_t::const_iterator::operator *() const
{
    return *current;
}
bst_node &bst_t::const_iterator::operator *()
{
    return *current;
}
<|endoftext|>


<commit_before>#include <stdexcept>
#include <string>
#include "ipns_retriever.h"
#include "../node.h"
#include "../string_util.h"
#include "../tree.hh"

using std::invalid_argument;
using std::runtime_error;
using std::string;
using std::vector;
using string_util::starts_with;
using string_util::int_list_str_to_intVect;

const static int GROUP_STRING_LEN=128;

/**
 * The factory will call the constructor with a string. The string
 * specifies where to locate the data (e.g. a filename), but
 * interpreting the string is left up to the implementing code.
 */
IpnsRetriever::IpnsRetriever(const string &str): source(str){
  if(str.size()<=0)
    throw invalid_argument("Cannot initialize from an empty string");

  char filename[50];
  strcpy(filename,str.c_str());
  char *f_ptr;
  f_ptr = filename;
  runFile =  new Runfile(f_ptr);
  if(runFile==NULL){
    //handle=NULL;
    throw runtime_error("Opening Runfile failed");
  }

}

IpnsRetriever::~IpnsRetriever(){
  /*  if(handle!=NULL){
    if(NXclose(handle)!=NX_OK)
      throw runtime_error("NXclose failed");
    handle=NULL;
    }*/
}

/**
 * This is the method for retrieving data from a file. The whole
 * tree will be written to the new file immediately after being
 * called. Interpreting the string is left up to the implementing
 * code.
 */
void IpnsRetriever::getData(Node &node, const std::string &location){
    if(location.size()<=0)
    throw invalid_argument("cannot parse empty string");

    string tLocation(location);
    if(starts_with(tLocation, "header")) {
      Header head = runFile->getHeader();
      int dims[1];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      if( location.substr(7,location.size()-7 ) == "runTitle" ) {
	value = new char[81];
	head.RunTitle((char *)value);
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "userName" ) {
	value = new char[21];
	head.UserName((char *)value);
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "startDateTime" ) {
	char date[10];
	head.StartDate((char *)date);
	char time[9];
	head.StartTime((char *)time);
	string sVal = this->fixDate( date, time );
	value = (void *)sVal.c_str();
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "endDateTime" ) {
	char date[10];
	head.EndDate((char *)date);
	char time[9];
	head.EndTime((char *)time);

	string sVal = this->fixDate( date, time );
	value = (void *)sVal.c_str();
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      node = Node(tLocation, value, 1, &(dims[0]), data_type);
      free(value);
    }
    // get data
    else if( location.substr(0, 5) == "data." ) {
      int dims[2];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      vector<vector<float> > vdata;
      vector<int> idListVect;
      float *data;
      //data retrieved from list of ids
      if ( location.substr(5, 3) == "ids" ) {
	string idList = location.substr( 8, location.size()-8 );
	// find & remove brackets
	string::size_type start_brkt = idList.find("[");
	string::size_type end_brkt = idList.find("]");
	string intListStr =
	  idList.substr(start_brkt + 1, end_brkt - (start_brkt +1) );
	// sort this string into a vector of integers
	idListVect = int_list_str_to_intVect(intListStr);
	int id;
	vector<Segment *> segments = runFile->GetSegments();
	vdata.resize(idListVect.size());
	for (id = 0; id < idListVect.size(); id++) {
	  vdata[id] = runFile->Get1DSpectrum(*segments[idListVect[id]], 1);

	}

	data = new float[idListVect.size()*vdata[0].size()];
	for (id = 0; id < idListVect.size(); id++) {
	  //	  data[id] = new float[vdata[0].size()];
	  if ( vdata[id].size() != vdata[0].size() ) {
	    throw runtime_error("ipns_retriever: all data must match size\n");
	  }
	  for (int chan =0; chan < vdata[0].size(); chan++ ) {
	    data[(id*vdata[0].size())+(chan)] = vdata[id][chan];
	  }
	}
      }

      dims[1] = vdata[0].size();
      dims[0] = idListVect.size();
      data_type = NX_FLOAT32;
      data_rank =2;
      value = (void *)data;
      node = Node(tLocation, value, data_rank, &(dims[0]), data_type);
    }
    else if( location.substr(0, 9) == "detector." ) {
      cout << "reading det from " << location.substr(9, location.size()-1);
      //      node = Node(tLocation, value, 1, &(dims[0]), data_type);
      //free(value);
    }

}

void IpnsRetriever::getData(const string &location, tree<Node> &tr){
  if(location.size()<=0)
    throw invalid_argument("cannot parse empty string");
  Node node("empty","empty");
  getData(node,location);
  tr.insert(tr.begin(),node);
}

const string IpnsRetriever::MIME_TYPE("application/x-IPNS");

string IpnsRetriever::toString() const{
  return "["+MIME_TYPE+"] "+source;
}

std::string IpnsRetriever::fixDate( char *date, char *time ) {
	int year = (date[7]-48)*10 + (date[8]-48);
	string sVal;
	if ( year > 80) {
	  sVal.append (1, '1');
	  sVal.append( 1, '9');
	}
	else {
	  sVal.append( 1, '2');
	  sVal.append( 1, '0');
	}
	sVal.append( 1, date[7]);
	sVal.append( 1, date[8]);
	sVal.append(1, '-');
	if ( date[3] == 'J' ) {
	  if ( date[4] == 'A' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '1');
	  }
	  else if (date[5] == 'N') {
	    sVal.append( 1, '0');
	    sVal.append( 1, '6');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '7');
	  }
	}
	else if ( date[3] == 'F' ) {
	  sVal.append( 1, '0');
	  sVal.append( 1, '2');
	}
	else if ( date[3] == 'M' ) {
	  if ( date[5] == 'R' ) {
	    sVal.append(1, '0');
	    sVal.append(1, '3');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '5');
	  }
	}
	else if ( date[3] == 'A' ) {
	  if ( date[5] == 'R' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '4');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '8');
	  }
	}
	else if ( date[3] == 'S' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '9');
	}
	else if ( date[3] == 'O' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '0');
	}
	else if ( date[3] == 'N' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '1');
	}
	else if ( date[3] == 'D' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '2');
	}
	sVal.append(1, '-');
	sVal.append(1, date[0]);
	sVal.append(1, date[1]);
	sVal.append(1,  'T');
	int ii;
	for (ii = 0; ii < 8; ii++ ) {
	  sVal.append(1, time[ii]);
	}
	sVal.append(1, '.');
	sVal.append(1, '0');
	sVal.append(1, '0');
	sVal.append(1, '-');
	sVal.append(1, '0');
	sVal.append(1, '6');
	sVal.append(1, ':');
	sVal.append(1, '0');
	sVal.append(1, '0');
	sVal.append(1, '\0');

  return sVal;
}
<commit_msg>Add in stuff to get TOFs & Errors from file<commit_after>#include <stdexcept>
#include <string>
#include "ipns_retriever.h"
#include "../node.h"
#include "../string_util.h"
#include "../tree.hh"

using std::invalid_argument;
using std::runtime_error;
using std::string;
using std::vector;
using string_util::starts_with;
using string_util::int_list_str_to_intVect;

const static int GROUP_STRING_LEN=128;

/**
 * The factory will call the constructor with a string. The string
 * specifies where to locate the data (e.g. a filename), but
 * interpreting the string is left up to the implementing code.
 */
IpnsRetriever::IpnsRetriever(const string &str): source(str){
  if(str.size()<=0)
    throw invalid_argument("Cannot initialize from an empty string");

  char filename[50];
  strcpy(filename,str.c_str());
  char *f_ptr;
  f_ptr = filename;
  runFile =  new Runfile(f_ptr);
  if(runFile==NULL){
    //handle=NULL;
    throw runtime_error("Opening Runfile failed");
  }

}

IpnsRetriever::~IpnsRetriever(){
  /*  if(handle!=NULL){
    if(NXclose(handle)!=NX_OK)
      throw runtime_error("NXclose failed");
    handle=NULL;
    }*/
}

/**
 * This is the method for retrieving data from a file. The whole
 * tree will be written to the new file immediately after being
 * called. Interpreting the string is left up to the implementing
 * code.
 */
void IpnsRetriever::getData(Node &node, const std::string &location){
    if(location.size()<=0)
    throw invalid_argument("cannot parse empty string");

    string tLocation(location);
    if(starts_with(tLocation, "header")) {
      Header head = runFile->getHeader();
      int dims[1];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      if( location.substr(7,location.size()-7 ) == "runTitle" ) {
	value = new char[81];
	head.RunTitle((char *)value);
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "userName" ) {
	value = new char[21];
	head.UserName((char *)value);
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "startDateTime" ) {
	char date[10];
	head.StartDate((char *)date);
	char time[9];
	head.StartTime((char *)time);
	string sVal = this->fixDate( date, time );
	value = (void *)sVal.c_str();
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      if( location.substr(7,location.size()-7 ) == "endDateTime" ) {
	char date[10];
	head.EndDate((char *)date);
	char time[9];
	head.EndTime((char *)time);

	string sVal = this->fixDate( date, time );
	value = (void *)sVal.c_str();
	dims[0] = (string((char *)value)).size();
	data_type = NX_CHAR;
	data_rank = 1;
      }
      node = Node(tLocation, value, 1, &(dims[0]), data_type);
      free(value);
    }
    // get data
    else if( location.substr(0, 5) == "data." ) {
      int dims[2];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      vector<vector<float> > vdata;
      vector<int> idListVect;
      float *data;
      //data retrieved from list of ids
      if ( location.substr(5, 3) == "ids" ) {
	string idList = location.substr( 8, location.size()-8 );
	// find & remove brackets
	string::size_type start_brkt = idList.find("[");
	string::size_type end_brkt = idList.find("]");
	string intListStr =
	  idList.substr(start_brkt + 1, end_brkt - (start_brkt +1) );
	// sort this string into a vector of integers
	idListVect = int_list_str_to_intVect(intListStr);
	int id;
	vector<Segment *> segments = runFile->GetSegments();
	vdata.resize(idListVect.size());
	for (id = 0; id < idListVect.size(); id++) {
	  vdata[id] = runFile->Get1DSpectrum(*segments[idListVect[id]], 1);

	}

	data = new float[idListVect.size()*vdata[0].size()];
	for (id = 0; id < idListVect.size(); id++) {
	  //	  data[id] = new float[vdata[0].size()];
	  if ( vdata[id].size() != vdata[0].size() ) {
	    throw runtime_error("ipns_retriever: all data must match size\n");
	  }
	  for (int chan =0; chan < vdata[0].size(); chan++ ) {
	    data[(id*vdata[0].size())+(chan)] = vdata[id][chan];
	  }
	}
      }

      dims[1] = vdata[0].size();
      dims[0] = idListVect.size();
      data_type = NX_FLOAT32;
      data_rank =2;
      value = (void *)data;
      node = Node(tLocation, value, data_rank, &(dims[0]), data_type);
    }
    else if( location.substr(0, 5) == "time." ) {
      int dims[2];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      vector<vector<float> > vdata;
      vector<int> idListVect;
      float *data;
      //data retrieved from list of ids
      if ( location.substr(5, 3) == "ids" ) {
	string idList = location.substr( 8, location.size()-8 );
	// find & remove brackets
	string::size_type start_brkt = idList.find("[");
	string::size_type end_brkt = idList.find("]");
	string intListStr =
	  idList.substr(start_brkt + 1, end_brkt - (start_brkt +1) );
	// sort this string into a vector of integers
	idListVect = int_list_str_to_intVect(intListStr);
	int id;
	vector<Segment *> segments = runFile->GetSegments();
	vdata.resize(idListVect.size());
	for (id = 0; id < idListVect.size(); id++) {
	  vdata[id] = runFile->TimeChannelBoundaries(*segments[idListVect[id]], 1);
	}
	data = new float[idListVect.size()*vdata[0].size()];
	for (id = 0; id < idListVect.size(); id++) {
	  //	  data[id] = new float[vdata[0].size()];
	  if ( vdata[id].size() != vdata[0].size() ) {
	    throw runtime_error("ipns_retriever: all data must match size\n");
	  }
	  for (int chan =0; chan < vdata[0].size(); chan++ ) {
	    data[(id*vdata[0].size())+(chan)] = vdata[id][chan];
	  }
	}
      }
      dims[1] = vdata[0].size();
      dims[0] = idListVect.size();
      data_type = NX_FLOAT32;
      data_rank =2;
      value = (void *)data;
      node = Node(tLocation, value, data_rank, &(dims[0]), data_type);
    }
    else if( location.substr(0, 6) == "error." ) {
      int dims[2];
      const int *dim_ptr;
      dim_ptr = dims;
      void *value;
      int data_type;
      int data_rank;
      vector<vector<float> > vdata;
      vector<int> idListVect;
      float *data;
      //data retrieved from list of ids
      if ( location.substr(6, 3) == "ids" ) {
	string idList = location.substr( 8, location.size()-8 );
	// find & remove brackets
	string::size_type start_brkt = idList.find("[");
	string::size_type end_brkt = idList.find("]");
	string intListStr =
	  idList.substr(start_brkt + 1, end_brkt - (start_brkt +1) );
	// sort this string into a vector of integers
	idListVect = int_list_str_to_intVect(intListStr);
	int id;
	vector<Segment *> segments = runFile->GetSegments();
	vdata.resize(idListVect.size());
	for (id = 0; id < idListVect.size(); id++) {
	  vdata[id] = runFile->Get1DSpectrum(*segments[idListVect[id]], 1);
	}
	data = new float[idListVect.size()*vdata[0].size()];
	for (id = 0; id < idListVect.size(); id++) {
	  //	  data[id] = new float[vdata[0].size()];
	  if ( vdata[id].size() != vdata[0].size() ) {
	    throw runtime_error("ipns_retriever: all data must match size\n");
	  }
	  for (int chan =0; chan < vdata[0].size(); chan++ ) {
	    data[(id*vdata[0].size())+(chan)] = sqrt(vdata[id][chan]);
	  }
	}
      }
      dims[1] = vdata[0].size();
      dims[0] = idListVect.size();
      data_type = NX_FLOAT32;
      data_rank =2;
      value = (void *)data;
      node = Node(tLocation, value, data_rank, &(dims[0]), data_type);
    }
    else if( location.substr(0, 9) == "detector." ) {
      cout << "reading det from " << location.substr(9, location.size()-1);
      //      node = Node(tLocation, value, 1, &(dims[0]), data_type);
      //free(value);
    }

}

void IpnsRetriever::getData(const string &location, tree<Node> &tr){
  if(location.size()<=0)
    throw invalid_argument("cannot parse empty string");
  Node node("empty","empty");
  getData(node,location);
  tr.insert(tr.begin(),node);
}

const string IpnsRetriever::MIME_TYPE("application/x-IPNS");

string IpnsRetriever::toString() const{
  return "["+MIME_TYPE+"] "+source;
}

std::string IpnsRetriever::fixDate( char *date, char *time ) {
	int year = (date[7]-48)*10 + (date[8]-48);
	string sVal;
	if ( year > 80) {
	  sVal.append (1, '1');
	  sVal.append( 1, '9');
	}
	else {
	  sVal.append( 1, '2');
	  sVal.append( 1, '0');
	}
	sVal.append( 1, date[7]);
	sVal.append( 1, date[8]);
	sVal.append(1, '-');
	if ( date[3] == 'J' ) {
	  if ( date[4] == 'A' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '1');
	  }
	  else if (date[5] == 'N') {
	    sVal.append( 1, '0');
	    sVal.append( 1, '6');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '7');
	  }
	}
	else if ( date[3] == 'F' ) {
	  sVal.append( 1, '0');
	  sVal.append( 1, '2');
	}
	else if ( date[3] == 'M' ) {
	  if ( date[5] == 'R' ) {
	    sVal.append(1, '0');
	    sVal.append(1, '3');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '5');
	  }
	}
	else if ( date[3] == 'A' ) {
	  if ( date[5] == 'R' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '4');
	  }
	  else {
	    sVal.append( 1, '0');
	    sVal.append( 1, '8');
	  }
	}
	else if ( date[3] == 'S' ) {
	    sVal.append( 1, '0');
	    sVal.append( 1, '9');
	}
	else if ( date[3] == 'O' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '0');
	}
	else if ( date[3] == 'N' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '1');
	}
	else if ( date[3] == 'D' ) {
	    sVal.append( 1, '1');
	    sVal.append( 1, '2');
	}
	sVal.append(1, '-');
	sVal.append(1, date[0]);
	sVal.append(1, date[1]);
	sVal.append(1,  'T');
	int ii;
	for (ii = 0; ii < 8; ii++ ) {
	  sVal.append(1, time[ii]);
	}
	sVal.append(1, '.');
	sVal.append(1, '0');
	sVal.append(1, '0');
	sVal.append(1, '-');
	sVal.append(1, '0');
	sVal.append(1, '6');
	sVal.append(1, ':');
	sVal.append(1, '0');
	sVal.append(1, '0');
	sVal.append(1, '\0');

  return sVal;
}
<|endoftext|>


<commit_before>#include <V8Runtime.h>
#include <JNIUtil.h>
#include <TypeConverter.h>

namespace titanium
{
	/* static */
	void V8Runtime::collectWeakRef(Persistent<Value> ref, void *parameter)
	{
		jobject v8Object = (jobject) parameter;

		ref.Dispose();
		JNIUtil::getJNIEnv()->DeleteGlobalRef(v8Object);
	}

	/* static */
	jobject V8Runtime::newObject(Handle<Object> object)
	{
		HandleScope scope;

		Persistent<Object> *persistent = new Persistent<Object>(object);
		JNIEnv *env = JNIUtil::getJNIEnv();
		if (!env) return NULL;

		jobject v8Object = env->NewGlobalRef(env->NewObject(JNIUtil::v8ObjectClass,
			JNIUtil::v8ObjectInitMethod, reinterpret_cast<jlong>(persistent)));

		persistent->MakeWeak(reinterpret_cast<void*>(v8Object), V8Runtime::collectWeakRef);
		return v8Object;
	}
}

extern "C" void
Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeInit(JNIEnv *env, jclass clazz)
{
	titanium::JNIUtil::initCache(env);
}

extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
	titanium::JNIUtil::javaVm = vm;
	return JNI_VERSION_1_4;
}
<commit_msg>use a weak reference as well as a standard persistent handle for Java V8Objects<commit_after>#include <V8Runtime.h>

#include <AndroidUtil.h>
#include <JNIUtil.h>
#include <TypeConverter.h>

#define TAG "V8Runtime"

namespace titanium
{
	/* static */
	void V8Runtime::collectWeakRef(Persistent<Value> ref, void *parameter)
	{
		jobject v8Object = (jobject) parameter;

		ref.Dispose();
		JNIUtil::getJNIEnv()->DeleteGlobalRef(v8Object);
	}

	/* static */
	jobject V8Runtime::newObject(Handle<Object> object)
	{
		HandleScope scope;
		LOGI(TAG, "Creating new object...");

		JNIEnv *env = JNIUtil::getJNIEnv();
		if (!env) return NULL;

		jlong ptr = reinterpret_cast<jlong>(*Persistent<Object>::New(object));
		jobject v8Object = env->NewGlobalRef(env->NewObject(JNIUtil::v8ObjectClass,
			JNIUtil::v8ObjectInitMethod, ptr));

		// make a 2nd persistent weakref so we can be informed of GC
		Persistent<Object> weak = Persistent<Object>::New(object);
		weak.MakeWeak(reinterpret_cast<void*>(v8Object), V8Runtime::collectWeakRef);
		return v8Object;
	}
}

extern "C" void
Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeInit(JNIEnv *env, jclass clazz)
{
	titanium::JNIUtil::initCache(env);
}

extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
	titanium::JNIUtil::javaVm = vm;
	return JNI_VERSION_1_4;
}
<|endoftext|>


<commit_before>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 */

#include <boost/filesystem.hpp>

#include <Core/Application/Application.h>
#include <Core/CommandLine/CommandLine.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <Modules/Factory/HardCodedModuleFactory.h>
#include <Core/Algorithms/Factory/HardCodedAlgorithmFactory.h>
#include <Dataflow/State/SimpleMapModuleState.h>
#include <Dataflow/Network/Module.h>  //TODO move Reex
#include <Dataflow/Engine/Scheduler/DesktopExecutionStrategyFactory.h>
#include <Core/Command/GlobalCommandBuilderFromCommandLine.h>
#include <Core/Logging/Log.h>
#include <Core/IEPlugin/IEPluginInit.h>
#include <Core/Utils/Exception.h>
#include <Core/Application/Session/Session.h>

#ifdef _WIN32
#include <shlobj.h>
#include <tlhelp32.h>
#include <windows.h>
#include <LMCons.h>
#include <psapi.h>
#endif

using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;
using namespace SCIRun::Core::CommandLine;
using namespace SCIRun::Core::Commands;
using namespace SCIRun::Dataflow::Engine;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Modules::Factory;
using namespace SCIRun::Dataflow::State;
using namespace SCIRun::Core::Algorithms;

namespace SCIRun
{
  namespace Core
  {
    class ApplicationPrivate
    {
    public:
      CommandLineParser parser;
      boost::filesystem::path app_filepath_;
      boost::filesystem::path app_filename_;
      ApplicationParametersHandle parameters_;
      NetworkEditorControllerHandle controller_;
    };
  }
}

CORE_SINGLETON_IMPLEMENTATION( Application )

Application::Application() :
	private_( new ApplicationPrivate )
{
  private_->app_filepath_ = boost::filesystem::current_path();
  SessionManager::Instance().initialize(private_->app_filepath_);
  SessionManager::Instance().session()->beginSession();
}

Application::~Application()
{
  SessionManager::Instance().session()->endSession();
}

void Application::shutdown()
{
  if (!private_)
    Log::get() << NOTICE << "Application shutdown called with null internals" << std::endl;
  try
  {
    private_.reset();
  }
  catch (std::exception& e)
  {
    Log::get() << EMERG << "Unhandled exception during application shutdown: " << e.what() << std::endl;
  }
  catch (...)
  {
    Log::get() << EMERG << "Unknown unhandled exception during application shutdown" << std::endl;
  }
}

std::string Application::applicationName() const
{
  return "SCIRun";
}

ApplicationParametersHandle Application::parameters() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");
  return private_->parameters_;
}

void Application::readCommandLine(int argc, const char* argv[])
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  private_->app_filename_ = boost::filesystem::path( argv[0] );
  private_->app_filepath_ = private_->app_filename_.parent_path();
  private_->parameters_ = private_->parser.parse(argc, argv);

  Logging::Log::get().setVerbose(parameters()->verboseMode());
}

NetworkEditorControllerHandle Application::controller()
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  if (!private_->controller_)
  {
    /// @todo: these all get configured
    ModuleFactoryHandle moduleFactory(new HardCodedModuleFactory);
    ModuleStateFactoryHandle sf(new SimpleMapModuleStateFactory);
    ExecutionStrategyFactoryHandle exe(new DesktopExecutionStrategyFactory(parameters()->threadMode()));
    AlgorithmFactoryHandle algoFactory(new HardCodedAlgorithmFactory);
    ReexecuteStrategyFactoryHandle reexFactory(new DynamicReexecutionStrategyFactory(parameters()->reexecuteMode()));
    private_->controller_.reset(new NetworkEditorController(moduleFactory, sf, exe, algoFactory, reexFactory));

    /// @todo: sloppy way to initialize this but similar to v4, oh well
    IEPluginManager::Initialize();
  }
  return private_->controller_;
}

void Application::executeCommandLineRequests(Commands::GlobalCommandFactoryHandle cmdFactory)
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  GlobalCommandBuilderFromCommandLine builder(cmdFactory);
  auto queue = builder.build(parameters());
  queue->runAll();
}

boost::filesystem::path Application::executablePath() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  return private_->app_filepath_;
}

std::string Application::commandHelpString() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  return private_->parser.describe();
}

std::string Application::version() const
{
	/// @todo:
  ///return CORE_APPLICATION_VERSION;
  return "5.0.0 developer version";
}

// following ugly code copied from Seg3D.

bool Application::get_user_directory( boost::filesystem::path& user_dir, bool config_path) const
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if( config_path )
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_LOCAL_APPDATA, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }
  }
  else
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_MYDOCUMENTS, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }
  }
#else

  if ( getenv( "HOME" ) )
  {
    user_dir = boost::filesystem::path( getenv( "HOME" ) );

    if (! boost::filesystem::exists( user_dir ) )
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }

    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user directory.";
    return false;
  }
#endif
}

bool Application::get_user_desktop_directory( boost::filesystem::path& user_desktop_dir ) const
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_DESKTOPDIRECTORY, 0, 0, dir ) ) )
  {
    user_desktop_dir = boost::filesystem::path( dir );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user desktop directory.";
    return false;
  }

#else

  if ( getenv( "HOME" ) )
  {
    user_desktop_dir = boost::filesystem::path( getenv( "HOME" ) ) / "Desktop" / "";

    if (! boost::filesystem::exists( user_desktop_dir ) )
    {
      Log::get() << ERROR_LOG << "Could not get user desktop directory.";
      return false;
    }

    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user desktop directory.";
    return false;
  }
#endif
}

bool Application::get_config_directory( boost::filesystem::path& config_dir ) const
{
  boost::filesystem::path user_dir;
  if ( !( get_user_directory( user_dir, true ) ) ) return false;

#ifdef _WIN32
  config_dir = user_dir / applicationName();
#else
  std::string dot_app_name = std::string( "." ) + applicationName();
  config_dir = user_dir / dot_app_name;
#endif

  if ( !( boost::filesystem::exists( config_dir ) ) )
  {
    if ( !( boost::filesystem::create_directory( config_dir ) ) )
    {
      Log::get() << ERROR_LOG << "Could not create directory: " << config_dir.string();
      return false;
    }

    Log::get() << INFO << "Created directory: " << config_dir.string();
  }

  return true;
}

bool Application::get_user_name( std::string& user_name ) const
{
#ifdef _WIN32
  TCHAR name[UNLEN+1];
  DWORD length = UNLEN;

  if ( GetUserName( name, &length ) )
  {
    user_name = std::string( name );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not resolve user name.";
    return false;
  }
#else
  if ( getenv( "USER" ) )
  {
    user_name = std::string( getenv( "USER" ) );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not resolve user name.";
    return false;
  }
#endif

}

/*
int Application::GetMajorVersion()
{
	return CORE_APPLICATION_MAJOR_VERSION;
}

int Application::GetMinorVersion()
{
	return CORE_APPLICATION_MINOR_VERSION;
}

int Application::GetPatchVersion()
{
	return CORE_APPLICATION_PATCH_VERSION;
}

bool Application::Is64Bit()
{
	return ( sizeof(void *) == 8 );
}

bool Application::Is32Bit()
{
	return ( sizeof(void *) == 4 );
}

std::string Application::GetApplicationName()
{
	return CORE_APPLICATION_NAME;
}

std::string Application::GetReleaseName()
{
	return CORE_APPLICATION_RELEASE;
}

std::string Application::GetApplicationNameAndVersion()
{
	return GetApplicationName() + " " + GetReleaseName() + " " + GetVersion();
}

std::string Application::GetAbout()
{
	return CORE_APPLICATION_ABOUT;
}
*/
<commit_msg>Add rest of includes<commit_after>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 */

#include <boost/filesystem.hpp>

#include <Core/Application/Application.h>
#include <Core/CommandLine/CommandLine.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <Modules/Factory/HardCodedModuleFactory.h>
#include <Core/Algorithms/Factory/HardCodedAlgorithmFactory.h>
#include <Dataflow/State/SimpleMapModuleState.h>
#include <Dataflow/Network/Module.h>  //TODO move Reex
#include <Dataflow/Engine/Scheduler/DesktopExecutionStrategyFactory.h>
#include <Core/Command/GlobalCommandBuilderFromCommandLine.h>
#include <Core/Logging/Log.h>
#include <Core/IEPlugin/IEPluginInit.h>
#include <Core/Utils/Exception.h>
#include <Core/Application/Session/Session.h>

// Includes for platform specific functions to get directory to store temp files and user data
#ifdef _WIN32
#include <shlobj.h>
#include <tlhelp32.h>
#include <windows.h>
#include <LMCons.h>
#include <psapi.h>
#else
#include <stdlib.h>
#include <sys/types.h>
#ifndef __APPLE__
#include <unistd.h>
#include <sys/sysinfo.h>
#else
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/mount.h>
#endif
#endif

using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;
using namespace SCIRun::Core::CommandLine;
using namespace SCIRun::Core::Commands;
using namespace SCIRun::Dataflow::Engine;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Modules::Factory;
using namespace SCIRun::Dataflow::State;
using namespace SCIRun::Core::Algorithms;

namespace SCIRun
{
  namespace Core
  {
    class ApplicationPrivate
    {
    public:
      CommandLineParser parser;
      boost::filesystem::path app_filepath_;
      boost::filesystem::path app_filename_;
      ApplicationParametersHandle parameters_;
      NetworkEditorControllerHandle controller_;
    };
  }
}

CORE_SINGLETON_IMPLEMENTATION( Application )

Application::Application() :
	private_( new ApplicationPrivate )
{
  private_->app_filepath_ = boost::filesystem::current_path();
  SessionManager::Instance().initialize(private_->app_filepath_);
  SessionManager::Instance().session()->beginSession();
}

Application::~Application()
{
  SessionManager::Instance().session()->endSession();
}

void Application::shutdown()
{
  if (!private_)
    Log::get() << NOTICE << "Application shutdown called with null internals" << std::endl;
  try
  {
    private_.reset();
  }
  catch (std::exception& e)
  {
    Log::get() << EMERG << "Unhandled exception during application shutdown: " << e.what() << std::endl;
  }
  catch (...)
  {
    Log::get() << EMERG << "Unknown unhandled exception during application shutdown" << std::endl;
  }
}

std::string Application::applicationName() const
{
  return "SCIRun";
}

ApplicationParametersHandle Application::parameters() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");
  return private_->parameters_;
}

void Application::readCommandLine(int argc, const char* argv[])
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  private_->app_filename_ = boost::filesystem::path( argv[0] );
  private_->app_filepath_ = private_->app_filename_.parent_path();
  private_->parameters_ = private_->parser.parse(argc, argv);

  Logging::Log::get().setVerbose(parameters()->verboseMode());
}

NetworkEditorControllerHandle Application::controller()
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  if (!private_->controller_)
  {
    /// @todo: these all get configured
    ModuleFactoryHandle moduleFactory(new HardCodedModuleFactory);
    ModuleStateFactoryHandle sf(new SimpleMapModuleStateFactory);
    ExecutionStrategyFactoryHandle exe(new DesktopExecutionStrategyFactory(parameters()->threadMode()));
    AlgorithmFactoryHandle algoFactory(new HardCodedAlgorithmFactory);
    ReexecuteStrategyFactoryHandle reexFactory(new DynamicReexecutionStrategyFactory(parameters()->reexecuteMode()));
    private_->controller_.reset(new NetworkEditorController(moduleFactory, sf, exe, algoFactory, reexFactory));

    /// @todo: sloppy way to initialize this but similar to v4, oh well
    IEPluginManager::Initialize();
  }
  return private_->controller_;
}

void Application::executeCommandLineRequests(Commands::GlobalCommandFactoryHandle cmdFactory)
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  GlobalCommandBuilderFromCommandLine builder(cmdFactory);
  auto queue = builder.build(parameters());
  queue->runAll();
}

boost::filesystem::path Application::executablePath() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  return private_->app_filepath_;
}

std::string Application::commandHelpString() const
{
  ENSURE_NOT_NULL(private_, "Application internals are uninitialized!");

  return private_->parser.describe();
}

std::string Application::version() const
{
	/// @todo:
  ///return CORE_APPLICATION_VERSION;
  return "5.0.0 developer version";
}

// following ugly code copied from Seg3D.

bool Application::get_user_directory( boost::filesystem::path& user_dir, bool config_path) const
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if( config_path )
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_LOCAL_APPDATA, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }
  }
  else
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_MYDOCUMENTS, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }
  }
#else

  if ( getenv( "HOME" ) )
  {
    user_dir = boost::filesystem::path( getenv( "HOME" ) );

    if (! boost::filesystem::exists( user_dir ) )
    {
      Log::get() << ERROR_LOG << "Could not get user directory.";
      return false;
    }

    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user directory.";
    return false;
  }
#endif
}

bool Application::get_user_desktop_directory( boost::filesystem::path& user_desktop_dir ) const
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_DESKTOPDIRECTORY, 0, 0, dir ) ) )
  {
    user_desktop_dir = boost::filesystem::path( dir );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user desktop directory.";
    return false;
  }

#else

  if ( getenv( "HOME" ) )
  {
    user_desktop_dir = boost::filesystem::path( getenv( "HOME" ) ) / "Desktop" / "";

    if (! boost::filesystem::exists( user_desktop_dir ) )
    {
      Log::get() << ERROR_LOG << "Could not get user desktop directory.";
      return false;
    }

    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not get user desktop directory.";
    return false;
  }
#endif
}

bool Application::get_config_directory( boost::filesystem::path& config_dir ) const
{
  boost::filesystem::path user_dir;
  if ( !( get_user_directory( user_dir, true ) ) ) return false;

#ifdef _WIN32
  config_dir = user_dir / applicationName();
#else
  std::string dot_app_name = std::string( "." ) + applicationName();
  config_dir = user_dir / dot_app_name;
#endif

  if ( !( boost::filesystem::exists( config_dir ) ) )
  {
    if ( !( boost::filesystem::create_directory( config_dir ) ) )
    {
      Log::get() << ERROR_LOG << "Could not create directory: " << config_dir.string();
      return false;
    }

    Log::get() << INFO << "Created directory: " << config_dir.string();
  }

  return true;
}

bool Application::get_user_name( std::string& user_name ) const
{
#ifdef _WIN32
  TCHAR name[UNLEN+1];
  DWORD length = UNLEN;

  if ( GetUserName( name, &length ) )
  {
    user_name = std::string( name );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not resolve user name.";
    return false;
  }
#else
  if ( getenv( "USER" ) )
  {
    user_name = std::string( getenv( "USER" ) );
    return true;
  }
  else
  {
    Log::get() << ERROR_LOG << "Could not resolve user name.";
    return false;
  }
#endif

}

/*
int Application::GetMajorVersion()
{
	return CORE_APPLICATION_MAJOR_VERSION;
}

int Application::GetMinorVersion()
{
	return CORE_APPLICATION_MINOR_VERSION;
}

int Application::GetPatchVersion()
{
	return CORE_APPLICATION_PATCH_VERSION;
}

bool Application::Is64Bit()
{
	return ( sizeof(void *) == 8 );
}

bool Application::Is32Bit()
{
	return ( sizeof(void *) == 4 );
}

std::string Application::GetApplicationName()
{
	return CORE_APPLICATION_NAME;
}

std::string Application::GetReleaseName()
{
	return CORE_APPLICATION_RELEASE;
}

std::string Application::GetApplicationNameAndVersion()
{
	return GetApplicationName() + " " + GetReleaseName() + " " + GetVersion();
}

std::string Application::GetAbout()
{
	return CORE_APPLICATION_ABOUT;
}
*/
<|endoftext|>