<commit_before>#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cctype>

#include <string>
#include <iostream>
#include <vector>
#include <unordered_map>

#include "network.h"

const string kEnwikiFile = "enwiki-20151102-pages-articles-multistream.xml";
const string kIDOffsetTitleFile = "id-offset-title.txt";

using namespace std;
typedef long long ll;

#define for_iter(i, n) for (__typeof(n.begin())i = n.begin(); i != n.end(); ++i)

const int kBufSize = 100000;
char g_input_buf[kBufSize];

class IDOffsetTitle {
public:
	IDOffsetTitle(const string &filename)
	{
		Init(filename);
	}

	/*
	 * 从filename中读取<id> <offset> <title>内容
	 * 建立合适的数据结构，以支持下面的查找操作
	 */
	void Init(const string &filename)
	{
		FILE *fp = fopen(kIDOffsetTitleFile.c_str(), "r");
		ll id;
		int len;
		long offset, pos_in_str;
		char title_buf[kBufSize];
		while (fgets(g_input_buf, kBufSize, fp)) {
			sscanf(g_input_buf, "%lld%ld%[^\n]", &id, &offset, title_buf);

			pos_in_str = title_concat_.length();
			id_offset_[id] = offset;
			ids_.push_back(id);
			pos_.push_back(pos_in_str);

			len = strlen(title_buf);

			for (int i = 0; i < len; i++)
				title_buf[i] = tolower(title_buf[i]);
			title_concat_ += title_buf;

			if (len == 1 && isalpha(title_buf[0]))
				title_index_single_[char_num(title_buf[0])] = pos_in_str;
			else
				title_index_double_[char_num(title_buf[0])][char_num(title_buf[1])].push_back(pos_in_str);
		}
		printf("IDOffsetTitle init finish.\n");
		fclose(fp);
	}

	/*
	 * 接受文章ID，返回文章内容
	 * 即<page></page>之间的内容，包括page标签
	 * 常量时间
	 */
	string ID2Page(ll id)
	{
		string page;
		FILE *fp = fopen(kEnwikiFile.c_str(), "r");
		fseek(fp, id_offset_[id], SEEK_SET);
		char ch, a[7] = {0};
		while ((ch = getchar())) {
			page.push_back(ch);
			for (int i = 0; i < 6; i++)
				a[i] = a[i + 1];
			a[7] = ch;
			if (strcmp(a, "</page>") == 0)
				break;
		}
		fclose(fp);
		return page;
	}

	vector<string> IDs2Pages(const vector<ll> ids)
	{
		/* For compatibility */
		vector<string> pages;
		for_iter(id, ids) {
			pages.push_back(ID2Page(*id));
		}
		return pages;
	}

	/*
	 * 接受一个单词，从Title中查找子串，返回匹配的前K(default=10)条
	 * Since title_concat_.length() can be very large, this function may be slow
	 */
	vector<ll> Word2ID(const string &word, int K = 10)
	{
		long pos = 0;
		vector<ll> ids;
		assert(word.length() > 0);
		if (word.length() == 1) {
			ids.push_back(title_index_single_[word[0] - 'a']);
			return ids;
		}
		long tmp = 0;
		while (K-- && (pos = FindSubStringOrDie(title_concat_.c_str(), word.c_str(), tmp))) {
			long idx = lower_bound(pos_.begin(), pos_.end(), pos) - pos_.begin();
			ids.push_back(ids_[idx]);
		}
		return ids;
	}

private:
	/* 不接受长度 < 2的字符串 */
	ll FindSubStringOrDie(const char *haystack, const char *needle, long &lastidx) {
		assert(strlen(needle) >= 2);
		vector<long> &v = title_index_double_[char_num(needle[0])][char_num(needle[1])];
		for (vector<long>::iterator it = v.begin() + lastidx; it != v.end(); ++it) {
			if (strcmp(haystack + *it, needle))
				return *it;
		}
		return 0; // or nullptr?
	}

	int char_num(int ch) { return ch - 'a'; }

	/* ID到偏移量的hash */
	unordered_map<ll, long> id_offset_;
	/* 所有title字符串的拼接 */
	string title_concat_;
	/* 第i篇文章的id */
	vector<ll> ids_;
	/* 第i篇文章title在字符串中的下标*/
	vector<long> pos_;
	/* 索引两个字母开头的所有位置 加速查找 */
	vector<long> title_index_double_[26][26];
	long title_index_single_[26];
};

string WaitInput(TCPServer &server)
{
	server.accept();
	string msg = server.recv();
	return msg;
}

int main() {
	//read_word_offset();
	//read_title_offset();
	TCPServer server("0.0.0.0", "23334");
	while (1) {
		string input = WaitInput(server);
		cout << "recv:" << input << endl;
		// do sth
	}
	return 0;
}
<commit_msg>fix bug in function FindSubStringOrDie<commit_after>#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cctype>

#include <string>
#include <iostream>
#include <vector>
#include <unordered_map>

#include "network.h"

const string kEnwikiFile = "enwiki-20151102-pages-articles-multistream.xml";
const string kIDOffsetTitleFile = "id-offset-title.txt";

using namespace std;
typedef long long ll;

#define for_iter(i, n) for (__typeof(n.begin())i = n.begin(); i != n.end(); ++i)

const int kBufSize = 100000;
char g_input_buf[kBufSize];

class IDOffsetTitle {
public:
	IDOffsetTitle(const string &filename)
	{
		Init(filename);
	}

	/*
	 * 从filename中读取<id> <offset> <title>内容
	 * 建立合适的数据结构，以支持下面的查找操作
	 */
	void Init(const string &filename)
	{
		FILE *fp = fopen(kIDOffsetTitleFile.c_str(), "r");
		ll id;
		int len;
		long offset, pos_in_str;
		char title_buf[kBufSize];
		while (fgets(g_input_buf, kBufSize, fp)) {
			sscanf(g_input_buf, "%lld%ld%[^\n]", &id, &offset, title_buf);

			pos_in_str = title_concat_.length();
			id_offset_[id] = offset;
			ids_.push_back(id);
			pos_.push_back(pos_in_str);

			len = strlen(title_buf);

			for (int i = 0; i < len; i++)
				title_buf[i] = tolower(title_buf[i]);
			title_concat_ += title_buf;

			if (len == 1 && isalpha(title_buf[0]))
				title_index_single_[char_num(title_buf[0])] = pos_in_str;
			else
				title_index_double_[char_num(title_buf[0])][char_num(title_buf[1])].push_back(pos_in_str);
		}
		printf("IDOffsetTitle init finish.\n");
		fclose(fp);
	}

	/*
	 * 接受文章ID，返回文章内容
	 * 即<page></page>之间的内容，包括page标签
	 * 常量时间
	 */
	string ID2Page(ll id)
	{
		string page;
		FILE *fp = fopen(kEnwikiFile.c_str(), "r");
		fseek(fp, id_offset_[id], SEEK_SET);
		char ch, a[7] = {0};
		while ((ch = getchar())) {
			page.push_back(ch);
			for (int i = 0; i < 6; i++)
				a[i] = a[i + 1];
			a[7] = ch;
			if (strcmp(a, "</page>") == 0)
				break;
		}
		fclose(fp);
		return page;
	}

	vector<string> IDs2Pages(const vector<ll> ids)
	{
		/* For compatibility */
		vector<string> pages;
		for_iter(id, ids) {
			pages.push_back(ID2Page(*id));
		}
		return pages;
	}

	/*
	 * 接受一个单词，从Title中查找子串，返回匹配的前K(default=10)条
	 * Since title_concat_.length() can be very large, this function may be slow
	 */
	vector<ll> Word2ID(const string &word, int K = 10)
	{
		long pos = 0;
		vector<ll> ids;
		assert(word.length() > 0);
		if (word.length() == 1) {
			ids.push_back(title_index_single_[word[0] - 'a']);
			return ids;
		}
		long tmp = 0;
		while (K-- && (pos = FindSubStringOrDie(title_concat_.c_str(), word.c_str(), tmp))) {
			long idx = lower_bound(pos_.begin(), pos_.end(), pos) - pos_.begin();
			ids.push_back(ids_[idx]);
		}
		return ids;
	}

private:
	/* 不接受长度 < 2的字符串 */
	ll FindSubStringOrDie(const char *haystack, const char *needle, long &lastidx) {
		assert(strlen(needle) >= 2);
		vector<long> &v = title_index_double_[char_num(needle[0])][char_num(needle[1])];
		for (vector<long>::iterator it = v.begin() + lastidx; it != v.end(); ++it) {
			lastidx++;
			if (strcmp(haystack + *it, needle))
				return *it;
		}
		return 0; // or nullptr?
	}

	int char_num(int ch) { return ch - 'a'; }

	/* ID到偏移量的hash */
	unordered_map<ll, long> id_offset_;
	/* 所有title字符串的拼接 */
	string title_concat_;
	/* 第i篇文章的id */
	vector<ll> ids_;
	/* 第i篇文章title在字符串中的下标*/
	vector<long> pos_;
	/* 索引两个字母开头的所有位置 加速查找 */
	vector<long> title_index_double_[26][26];
	long title_index_single_[26];
};

string WaitInput(TCPServer &server)
{
	server.accept();
	string msg = server.recv();
	return msg;
}

int main() {
	//read_word_offset();
	//read_title_offset();
	TCPServer server("0.0.0.0", "23334");
	while (1) {
		string input = WaitInput(server);
		cout << "recv:" << input << endl;
		// do sth
	}
	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <libbio/progress_indicator.hh>
#include <tuple>
#include <unistd.h>
#include <vcf2multialign/preprocess/preprocess_logger.hh>
#include <vcf2multialign/utility/can_handle_variant_alts.hh>
#include <vcf2multialign/utility/log_assertion_failure.hh>
#include <vcf2multialign/utility/progress_indicator_manager.hh>
#include <vcf2multialign/variant_format.hh>
#include <vcf2multialign/vcf_processor.hh>
#include "cmdline.h"

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace {

	class progress_indicator_delegate final : public lb::progress_indicator_delegate
	{
	protected:
		std::atomic_size_t	m_counter{};

	public:
		progress_indicator_delegate() = default;
		void increment() { m_counter.fetch_add(1, std::memory_order_relaxed); }
		virtual std::size_t progress_step_max() const override { return 0; }
		virtual std::size_t progress_current_step() const override { return m_counter.load(std::memory_order_relaxed); }
		virtual void progress_log_extra() const override {};
	};
}

namespace vcf2multialign {

	class unaligned_processor final :	public vcf_processor,
										public output_stream_controller,
										public reference_controller,
										public progress_indicator_manager,
										public preprocess_logger
	{
	protected:
		std::vector <std::string> const	m_field_names_for_filter_if_set;
		std::string	const				m_chromosome_name;

	public:
		unaligned_processor(
			std::vector <std::string> &&field_names_for_filter_if_set,
			std::string const &chromosome_name
		):
			vcf_processor(),
			output_stream_controller(),
			reference_controller(),
			progress_indicator_manager(),
			preprocess_logger(),
			m_field_names_for_filter_if_set(std::move(field_names_for_filter_if_set)),
			m_chromosome_name(chromosome_name)
		{
		}

		void process_and_output(std::size_t const sample_idx, std::uint8_t const chr_idx);

	protected:
		std::tuple <std::size_t, std::size_t, std::size_t> output_variants(std::size_t const sample_idx, std::uint8_t const chr_idx, progress_indicator_delegate &progress_delegate);
	};

	void unaligned_processor::process_and_output(std::size_t const sample_idx, std::uint8_t const chr_idx)
	{
		try
		{
			// Partition.
			progress_indicator_delegate indicator_delegate;
			this->install_progress_indicator();

			this->progress_indicator().log_with_counter(lb::copy_time() + "Processing the variants…", indicator_delegate);

			auto const res(output_variants(sample_idx, chr_idx, indicator_delegate));

			this->end_logging();
			this->uninstall_progress_indicator();

			dispatch_async(dispatch_get_main_queue(), ^{
				auto const &[included_variants, not_included_variants, skipped_variants] = res;
				lb::log_time(std::cerr);
				std::cerr << "Done. Included variants: " << included_variants
					<< " Skipped variants (GT = 0): " << not_included_variants
					<< " Skipped variants (ALT not handled): " << skipped_variants
					<< "\n";
			});

			this->m_output_stream << std::flush;
			this->finish();
		}
		catch (lb::assertion_failure_exception const &exc)
		{
			this->log_assertion_failure_and_exit(exc);
		}
		catch (std::exception const &exc)
		{
			this->log_exception_and_exit(exc);
		}
		catch (...)
		{
			this->log_unknown_exception_and_exit();
		}
	}

	std::tuple <std::size_t, std::size_t, std::size_t> unaligned_processor::output_variants(std::size_t const sample_idx, std::uint8_t const chr_idx, progress_indicator_delegate &indicator_delegate)
	{
		auto &reader(this->vcf_reader());
		reader.reset();
		reader.set_parsed_fields(lb::vcf_field::ALL);

		// Get the field descriptors needed for accessing the values.
		auto const *end_field(reader.get_end_field_ptr());

		// Determine the fields used for filtering.
		std::vector <lb::vcf_info_field_base *> filter_by_assigned;
		{
			auto const &fields(reader.info_fields());
			for (auto const &name : m_field_names_for_filter_if_set)
			{
				auto const it(fields.find(name));
				if (fields.end() == it)
				{
					this->variant_processor_no_field_for_identifier(name);
					continue;
				}

				filter_by_assigned.emplace_back(it->second.get());
			}
		}

		bool should_continue(false);
		std::size_t prev_end_pos{};
		std::size_t overlap_end{};
		std::size_t included_variants{};
		std::size_t not_included_variants{};
		std::size_t skipped_variants{};
		do {
			reader.fill_buffer();
			should_continue = reader.parse(
				[
					this,
					sample_idx,
					chr_idx,
					end_field,
					&prev_end_pos,
					&filter_by_assigned,
					&indicator_delegate,
					&included_variants,
					&not_included_variants,
					&skipped_variants
				](lb::transient_variant const &var) -> bool
				{
					auto const lineno(var.lineno());
					auto const var_pos(var.zero_based_pos());

					// Check the chromosome name.
					if (var.chrom_id() != m_chromosome_name)
						goto end;

					if (! (var_pos < m_reference.size()))
					{
						this->variant_processor_found_variant_with_position_greater_than_reference_length(var);
						return false;
					}

					if (!can_handle_variant_alts(var))
					{
						this->variant_processor_found_variant_with_no_suitable_alts(var);
						goto end;
					}

					// Filter.
					for (auto const *field_ptr : filter_by_assigned)
					{
						if (field_ptr->has_value(var))
						{
							this->variant_processor_found_filtered_variant(var, *field_ptr);
							goto end;
						}
					}

					// Compare the REF column against the reference sequence.
					{
						auto const &ref_col(var.ref());
						std::string_view const ref_sub(m_reference.data() + var_pos, ref_col.size());
						if (ref_col != ref_sub)
						{
							this->variant_processor_found_variant_with_ref_mismatch(var, ref_sub);
							goto end;
						}
					}

					// Variant passes the checks, handle it.
					{
						libbio_always_assert_lt(sample_idx, var.samples().size());
						auto const &sample(var.samples()[sample_idx]);
						auto const *gt_field(get_variant_format(var).gt);
						auto const &gt((*gt_field)(sample));
						libbio_always_assert_lt(chr_idx, gt.size());
						auto const alt_idx(gt[chr_idx].alt);
						if (0 == alt_idx)
						{
							++not_included_variants;
							goto end_2;
						}
						else
						{
							if (! (prev_end_pos <= var_pos))
							{
								// FIXME: log the overlap.
								//this->variant_processor_found_overlapping_variant(var, prev_end_pos);
								goto end;
							}

							auto const &alt(var.alts()[alt_idx - 1]);
							switch (alt.alt_sv_type)
							{
								// Handled ALTs:
								case lb::sv_type::NONE:
								case lb::sv_type::UNKNOWN:
								case lb::sv_type::DEL:
								case lb::sv_type::DEL_ME:
									break;
								default:
									// FIXME: log the ALT.
									//this->variant_processor_unhandled_alt(var, alt_idx);
									goto end;
							}

							std::string_view const ref_sub(m_reference.data() + prev_end_pos, var_pos - prev_end_pos);
							this->m_output_stream << ref_sub;

							if (lb::sv_type::NONE == alt.alt_sv_type)
							{
								auto const &alt_seq(alt.alt);
								this->m_output_stream << alt_seq;
							}

							auto const var_end(lb::variant_end_pos(var, *end_field));
							prev_end_pos = var_end;
							++included_variants;
						}

						goto end_2;
					}

				end:
					++skipped_variants;

				end_2:
					indicator_delegate.increment();
					return true;
				}
			);
		} while (should_continue);

		std::string_view const ref_sub(m_reference.data() + prev_end_pos, m_reference.size() - prev_end_pos);
		this->m_output_stream << ref_sub;

		return std::make_tuple(included_variants, not_included_variants, skipped_variants);
	}

	void vcf_to_unaligned(
		char const *reference_path,
		char const *variants_file_path,
		char const *output_file_path,
		char const *log_path,
		char const *reference_seq_name,
		char const *chr_name,
		std::vector <std::string> &&field_names_for_filter_if_set,
		std::size_t sample_idx,
		std::uint16_t chr_copy_idx,
		bool const should_overwrite_files
	)
	{
		// main() calls dispatch_main() if this function does not throw or call std::exit or something similar.
		try
		{
			// Since the processor has Boost’s streams, it cannot be moved. Hence the use of a pointer.
			auto processor_ptr(std::make_unique <unaligned_processor>(std::move(field_names_for_filter_if_set), chr_name));
			auto &processor(*processor_ptr);

			// These will eventually call std::exit if the file in question cannot be opened.
			processor.open_variants_file(variants_file_path);
			processor.read_reference(reference_path, reference_seq_name);
			processor.open_output_file(output_file_path, should_overwrite_files);
			if (log_path)
				processor.open_log_file(log_path, should_overwrite_files);

			processor.prepare_reader();

			// Run in background in order to be able to update a progress bar.
			lb::dispatch_async_fn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
				[
					processor_ptr = std::move(processor_ptr),
				 	sample_idx,
				 	chr_copy_idx
				](){
					// FIXME: get the sample index from command line.
					processor_ptr->process_and_output(sample_idx, chr_copy_idx);
				}
			);
		}
		catch (lb::assertion_failure_exception const &exc)
		{
			log_assertion_failure_exception(exc);
			throw exc;
		}
	}
}

int main(int argc, char **argv)
{
#ifndef NDEBUG
	std::cerr << "Assertions have been enabled." << std::endl;
#endif

	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		std::exit(EXIT_FAILURE);

	std::ios_base::sync_with_stdio(false);	// Don't use C style IO after calling cmdline_parser.
	std::cin.tie(nullptr);					// We don't require any input from the user.

	if (! (0 <= args_info.sample_index_arg))
	{
		std::cerr << "Sample index must be greater than or equal to zero.\n";
		std::exit(EXIT_FAILURE);
	}

	if (! (0 <= args_info.chromosome_copy_index_arg))
	{
		std::cerr << "Chromosome copy index must be greater than or equal to zero.\n";
		std::exit(EXIT_FAILURE);
	}

	std::vector <std::string> field_names_for_filter_if_set(args_info.filter_fields_set_given);
	for (std::size_t i(0); i < args_info.filter_fields_set_given; ++i)
		field_names_for_filter_if_set[i] = args_info.filter_fields_set_arg[i];

	v2m::vcf_to_unaligned(
		args_info.reference_arg,
		args_info.variants_arg,
		args_info.output_arg,
		args_info.log_arg,
		args_info.reference_sequence_given ? args_info.reference_sequence_arg : nullptr,
		args_info.chromosome_given ? args_info.chromosome_arg : nullptr,
		std::move(field_names_for_filter_if_set),
		args_info.sample_index_arg,
		args_info.chromosome_copy_index_arg,
		args_info.overwrite_flag
	);

	dispatch_main();
	// Not reached.
	return EXIT_SUCCESS;
}
<commit_msg>Output more detailed statistics<commit_after>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <libbio/progress_indicator.hh>
#include <tuple>
#include <unistd.h>
#include <vcf2multialign/preprocess/preprocess_logger.hh>
#include <vcf2multialign/utility/can_handle_variant_alts.hh>
#include <vcf2multialign/utility/log_assertion_failure.hh>
#include <vcf2multialign/utility/progress_indicator_manager.hh>
#include <vcf2multialign/variant_format.hh>
#include <vcf2multialign/vcf_processor.hh>
#include "cmdline.h"

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace {

	class progress_indicator_delegate final : public lb::progress_indicator_delegate
	{
	protected:
		std::atomic_size_t	m_counter{};

	public:
		progress_indicator_delegate() = default;
		void increment() { m_counter.fetch_add(1, std::memory_order_relaxed); }
		virtual std::size_t progress_step_max() const override { return 0; }
		virtual std::size_t progress_current_step() const override { return m_counter.load(std::memory_order_relaxed); }
		virtual void progress_log_extra() const override {};
	};
}

namespace vcf2multialign {

	struct variant_statistics
	{
		std::size_t	included_variant{};
		std::size_t	ref_mismatch{};
		std::size_t	filtered_variant{};
		std::size_t	no_suitable_alts{};
		std::size_t	gt_equals_0{};
		std::size_t	overlapping_variant{};
		std::size_t	unhandled_structural_variant{};

		variant_statistics() = default;
	};

	std::ostream &operator<<(std::ostream &os, variant_statistics const &stats)
	{
		os << "Included variants:             " << stats.included_variant             << '\n';
		os << "Reference mismatch:            " << stats.ref_mismatch                 << '\n';
		os << "Filtered variants:             " << stats.filtered_variant             << '\n';
		os << "Overlapping variants:          " << stats.overlapping_variant          << '\n';
		os << "No suitable ALTs:              " << stats.no_suitable_alts             << '\n';
		os << "GT equals 0:                   " << stats.gt_equals_0                  << '\n';
		os << "Unhandled structural variants: " << stats.unhandled_structural_variant << '\n';
		return os;
	}

	class unaligned_processor final :	public vcf_processor,
										public output_stream_controller,
										public reference_controller,
										public progress_indicator_manager,
										public preprocess_logger
	{
	protected:
		std::vector <std::string> const	m_field_names_for_filter_if_set;
		std::string	const				m_chromosome_name;

	public:
		unaligned_processor(
			std::vector <std::string> &&field_names_for_filter_if_set,
			std::string const &chromosome_name
		):
			vcf_processor(),
			output_stream_controller(),
			reference_controller(),
			progress_indicator_manager(),
			preprocess_logger(),
			m_field_names_for_filter_if_set(std::move(field_names_for_filter_if_set)),
			m_chromosome_name(chromosome_name)
		{
		}

		void process_and_output(std::size_t const sample_idx, std::uint8_t const chr_idx);

	protected:
		void output_variants(std::size_t const sample_idx, std::uint8_t const chr_idx, variant_statistics &statistics, progress_indicator_delegate &progress_delegate);
	};

	void unaligned_processor::process_and_output(std::size_t const sample_idx, std::uint8_t const chr_idx)
	{
		try
		{
			// Partition.
			progress_indicator_delegate indicator_delegate;
			this->install_progress_indicator();

			this->progress_indicator().log_with_counter(lb::copy_time() + "Processing the variants…", indicator_delegate);

			variant_statistics statistics;
			output_variants(sample_idx, chr_idx, statistics, indicator_delegate);

			this->end_logging();
			this->uninstall_progress_indicator();

			dispatch_async(dispatch_get_main_queue(), ^{
				lb::log_time(std::cerr);
				std::cerr << "Done.\n";
				std::cerr << statistics;
			});

			this->m_output_stream << std::flush;
			this->finish();
		}
		catch (lb::assertion_failure_exception const &exc)
		{
			this->log_assertion_failure_and_exit(exc);
		}
		catch (std::exception const &exc)
		{
			this->log_exception_and_exit(exc);
		}
		catch (...)
		{
			this->log_unknown_exception_and_exit();
		}
	}

	void unaligned_processor::output_variants(std::size_t const sample_idx, std::uint8_t const chr_idx, variant_statistics &statistics, progress_indicator_delegate &indicator_delegate)
	{
		auto &reader(this->vcf_reader());
		reader.reset();
		reader.set_parsed_fields(lb::vcf_field::ALL);

		// Get the field descriptors needed for accessing the values.
		auto const *end_field(reader.get_end_field_ptr());

		// Determine the fields used for filtering.
		std::vector <lb::vcf_info_field_base *> filter_by_assigned;
		{
			auto const &fields(reader.info_fields());
			for (auto const &name : m_field_names_for_filter_if_set)
			{
				auto const it(fields.find(name));
				if (fields.end() == it)
				{
					this->variant_processor_no_field_for_identifier(name);
					continue;
				}

				filter_by_assigned.emplace_back(it->second.get());
			}
		}

		bool should_continue(false);
		std::size_t prev_end_pos{};
		std::size_t overlap_end{};
		do {
			reader.fill_buffer();
			should_continue = reader.parse(
				[
					this,
					sample_idx,
					chr_idx,
					end_field,
					&prev_end_pos,
					&filter_by_assigned,
					&statistics,
					&indicator_delegate
				](lb::transient_variant const &var) -> bool
				{
					auto const lineno(var.lineno());
					auto const var_pos(var.zero_based_pos());

					// Check the chromosome name.
					if (var.chrom_id() != m_chromosome_name)
						goto end;

					if (! (var_pos < m_reference.size()))
					{
						this->variant_processor_found_variant_with_position_greater_than_reference_length(var);
						return false;
					}

					if (!can_handle_variant_alts(var))
					{
						this->variant_processor_found_variant_with_no_suitable_alts(var);
						++statistics.no_suitable_alts;
						goto end;
					}

					// Filter.
					for (auto const *field_ptr : filter_by_assigned)
					{
						if (field_ptr->has_value(var))
						{
							this->variant_processor_found_filtered_variant(var, *field_ptr);
							++statistics.filtered_variant;
							goto end;
						}
					}

					// Compare the REF column against the reference sequence.
					{
						auto const &ref_col(var.ref());
						std::string_view const ref_sub(m_reference.data() + var_pos, ref_col.size());
						if (ref_col != ref_sub)
						{
							this->variant_processor_found_variant_with_ref_mismatch(var, ref_sub);
							++statistics.ref_mismatch;
							goto end;
						}
					}

					// Variant passes the checks, handle it.
					{
						libbio_always_assert_lt(sample_idx, var.samples().size());
						auto const &sample(var.samples()[sample_idx]);
						auto const *gt_field(get_variant_format(var).gt);
						auto const &gt((*gt_field)(sample));
						libbio_always_assert_lt(chr_idx, gt.size());
						auto const alt_idx(gt[chr_idx].alt);
						if (0 == alt_idx)
						{
							++statistics.gt_equals_0;
							goto end;
						}
						else
						{
							if (! (prev_end_pos <= var_pos))
							{
								// FIXME: log the overlap.
								//this->variant_processor_found_overlapping_variant(var, prev_end_pos);
								++statistics.overlapping_variant;
								goto end;
							}

							auto const &alt(var.alts()[alt_idx - 1]);
							switch (alt.alt_sv_type)
							{
								// Handled ALTs:
								case lb::sv_type::NONE:
								case lb::sv_type::UNKNOWN:
								case lb::sv_type::DEL:
								case lb::sv_type::DEL_ME:
									break;
								default:
									// FIXME: log the ALT.
									//this->variant_processor_unhandled_alt(var, alt_idx);
									++statistics.unhandled_structural_variant;
									goto end;
							}

							std::string_view const ref_sub(m_reference.data() + prev_end_pos, var_pos - prev_end_pos);
							this->m_output_stream << ref_sub;

							if (lb::sv_type::NONE == alt.alt_sv_type)
							{
								auto const &alt_seq(alt.alt);
								this->m_output_stream << alt_seq;
							}

							auto const var_end(lb::variant_end_pos(var, *end_field));
							prev_end_pos = var_end;
							++statistics.included_variant;
						}

						goto end;
					}

				end:
					indicator_delegate.increment();
					return true;
				}
			);
		} while (should_continue);

		std::string_view const ref_sub(m_reference.data() + prev_end_pos, m_reference.size() - prev_end_pos);
		this->m_output_stream << ref_sub;
	}

	void vcf_to_unaligned(
		char const *reference_path,
		char const *variants_file_path,
		char const *output_file_path,
		char const *log_path,
		char const *reference_seq_name,
		char const *chr_name,
		std::vector <std::string> &&field_names_for_filter_if_set,
		std::size_t sample_idx,
		std::uint16_t chr_copy_idx,
		bool const should_overwrite_files
	)
	{
		// main() calls dispatch_main() if this function does not throw or call std::exit or something similar.
		try
		{
			// Since the processor has Boost’s streams, it cannot be moved. Hence the use of a pointer.
			auto processor_ptr(std::make_unique <unaligned_processor>(std::move(field_names_for_filter_if_set), chr_name));
			auto &processor(*processor_ptr);

			// These will eventually call std::exit if the file in question cannot be opened.
			processor.open_variants_file(variants_file_path);
			processor.read_reference(reference_path, reference_seq_name);
			processor.open_output_file(output_file_path, should_overwrite_files);
			if (log_path)
				processor.open_log_file(log_path, should_overwrite_files);

			processor.prepare_reader();

			// Run in background in order to be able to update a progress bar.
			lb::dispatch_async_fn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
				[
					processor_ptr = std::move(processor_ptr),
				 	sample_idx,
				 	chr_copy_idx
				](){
					// FIXME: get the sample index from command line.
					processor_ptr->process_and_output(sample_idx, chr_copy_idx);
				}
			);
		}
		catch (lb::assertion_failure_exception const &exc)
		{
			log_assertion_failure_exception(exc);
			throw exc;
		}
	}
}

int main(int argc, char **argv)
{
#ifndef NDEBUG
	std::cerr << "Assertions have been enabled." << std::endl;
#endif

	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		std::exit(EXIT_FAILURE);

	std::ios_base::sync_with_stdio(false);	// Don't use C style IO after calling cmdline_parser.
	std::cin.tie(nullptr);					// We don't require any input from the user.

	if (! (0 <= args_info.sample_index_arg))
	{
		std::cerr << "Sample index must be greater than or equal to zero.\n";
		std::exit(EXIT_FAILURE);
	}

	if (! (0 <= args_info.chromosome_copy_index_arg))
	{
		std::cerr << "Chromosome copy index must be greater than or equal to zero.\n";
		std::exit(EXIT_FAILURE);
	}

	std::vector <std::string> field_names_for_filter_if_set(args_info.filter_fields_set_given);
	for (std::size_t i(0); i < args_info.filter_fields_set_given; ++i)
		field_names_for_filter_if_set[i] = args_info.filter_fields_set_arg[i];

	v2m::vcf_to_unaligned(
		args_info.reference_arg,
		args_info.variants_arg,
		args_info.output_arg,
		args_info.log_arg,
		args_info.reference_sequence_given ? args_info.reference_sequence_arg : nullptr,
		args_info.chromosome_given ? args_info.chromosome_arg : nullptr,
		std::move(field_names_for_filter_if_set),
		args_info.sample_index_arg,
		args_info.chromosome_copy_index_arg,
		args_info.overwrite_flag
	);

	dispatch_main();
	// Not reached.
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: combobox.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: ihi $ $Date: 2008-01-14 13:02:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#ifndef _SV_COMBOBOX_HXX
#define _SV_COMBOBOX_HXX

#ifndef _VCL_DLLAPI_H
#include <vcl/dllapi.h>
#endif

#ifndef _SV_CTRL_HXX
#include <vcl/ctrl.hxx>
#endif
#ifndef _SV_COMBOBOX_H
#include <vcl/combobox.h>
#endif
#ifndef _SV_EDIT_HXX
#include <vcl/edit.hxx>
#endif

class UserDrawEvent;

class ImplListBoxFloatingWindow;
class ImplListBox;
class ImplBtn;

// ------------
// - ComboBox -
// ------------

class VCL_DLLPUBLIC ComboBox : public Edit
{
private:
    Edit*                       mpSubEdit;
    ImplListBox*                mpImplLB;
    ImplBtn*                    mpBtn;
    ImplListBoxFloatingWindow*  mpFloatWin;
    USHORT                      mnDDHeight;
    xub_Unicode                 mcMultiSep;
    BOOL                        mbDDAutoSize        : 1;
    BOOL                        mbSyntheticModify   : 1;
    BOOL                        mbMatchCase         : 1;
    Link                        maSelectHdl;
    Link                        maDoubleClickHdl;

//#if 0 // _SOLAR__PRIVATE
private:
    SAL_DLLPRIVATE void     ImplInitComboBoxData();
    SAL_DLLPRIVATE void     ImplUpdateFloatSelection();

    DECL_DLLPRIVATE_LINK(   ImplSelectHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplCancelHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplDoubleClickHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplClickBtnHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplPopupModeEndHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplSelectionChangedHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplUserDrawHdl, UserDrawEvent* );
    DECL_DLLPRIVATE_LINK(   ImplAutocompleteHdl, Edit* );

protected:
    using Window::ImplInit;
    SAL_DLLPRIVATE void     ImplInit( Window* pParent, WinBits nStyle );
    SAL_DLLPRIVATE WinBits  ImplInitStyle( WinBits nStyle );
    SAL_DLLPRIVATE void     ImplLoadRes( const ResId& rResId );
    SAL_DLLPRIVATE void     ImplCalcEditHeight();
//#endif

protected:
                    ComboBox( WindowType nType );
    BOOL            IsDropDownBox() const { return mpFloatWin ? TRUE : FALSE; }

    virtual void  FillLayoutData() const;
public:
                    ComboBox( Window* pParent, WinBits nStyle = 0 );
                    ComboBox( Window* pParent, const ResId& rResId );
                    ~ComboBox();

    virtual void    Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags );
    virtual void    Resize();
    virtual long    PreNotify( NotifyEvent& rNEvt );
    virtual long    Notify( NotifyEvent& rNEvt );
    virtual void    StateChanged( StateChangedType nType );
    virtual void    DataChanged( const DataChangedEvent& rDCEvt );

    virtual void    UserDraw( const UserDrawEvent& rUDEvt );
    virtual void    Select();
    virtual void    DoubleClick();

    virtual void    Modify();

    virtual const Wallpaper& GetDisplayBackground() const;

    virtual void    SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, USHORT nFlags = WINDOW_POSSIZE_ALL );
    void            SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
                        { Edit::SetPosSizePixel( rNewPos, rNewSize ); }
    void            SetDropDownSizePixel( const Size& rNewSize )
    { if( IsDropDownBox() ) SetPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(), WINDOW_POSSIZE_SIZE | WINDOW_POSSIZE_DROPDOWN ); }

    Rectangle       GetDropDownPosSizePixel() const;
    Rectangle       GetListPosSizePixel() const;
    // returns empty rectangle in DropDown mode,
    // else it returns the PosSize of the ListBox

    void            SetDropDownLineCount( USHORT nLines );
    USHORT          GetDropDownLineCount() const;

    void            EnableAutoSize( BOOL bAuto );
    BOOL            IsAutoSizeEnabled() const               { return mbDDAutoSize; }

    void            EnableDDAutoWidth( BOOL b );
    BOOL            IsDDAutoWidthEnabled() const;

    void            SetText( const XubString& rStr );
    void            SetText( const XubString& rStr, const Selection& rNewSelection );

    USHORT          InsertEntry( const XubString& rStr, USHORT nPos = COMBOBOX_APPEND );
    USHORT          InsertEntry( const XubString& rStr, const Image& rImage, USHORT nPos = COMBOBOX_APPEND );

    void            RemoveEntry( const XubString& rStr );
    void            RemoveEntry( USHORT nPos );

    void            Clear();

    USHORT          GetEntryPos( const XubString& rStr ) const;
    USHORT          GetEntryPos( const void* pData ) const;
    XubString       GetEntry( USHORT nPos ) const;
    USHORT          GetEntryCount() const;

    BOOL            IsTravelSelect() const;
    BOOL            IsInDropDown() const;
    void            ToggleDropDown();

    long            CalcWindowSizePixel( USHORT nLines ) const;

    void            SetUserItemSize( const Size& rSz );
    const Size&     GetUserItemSize() const;

    void            EnableUserDraw( BOOL bUserDraw );
    BOOL            IsUserDrawEnabled() const;

    void            DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos = FALSE );
    void            SetBorderStyle( USHORT nBorderStyle );

    void            SetSeparatorPos( USHORT n );
    void            SetSeparatorPos();
    USHORT          GetSeparatorPos() const;

    void            EnableAutocomplete( BOOL bEnable, BOOL bMatchCase = FALSE );
    BOOL            IsAutocompleteEnabled() const;

    void            EnableMultiSelection( BOOL bMulti );
    BOOL            IsMultiSelectionEnabled() const;
    void            SetMultiSelectionSeparator( xub_Unicode cSep ) { mcMultiSep = cSep; }
    xub_Unicode     GetMultiSelectionSeparator() const { return mcMultiSep; }

    void            SetSelectHdl( const Link& rLink )       { maSelectHdl = rLink; }
    const Link&     GetSelectHdl() const                    { return maSelectHdl; }
    void            SetDoubleClickHdl( const Link& rLink )  { maDoubleClickHdl = rLink; }
    const Link&     GetDoubleClickHdl() const               { return maDoubleClickHdl; }

    Size            CalcMinimumSize() const;
    virtual Size    GetOptimalSize(WindowSizeType eType) const;
    Size            CalcAdjustedSize( const Size& rPrefSize ) const;
    using Edit::CalcSize;
    Size            CalcSize( USHORT nColumns, USHORT nLines ) const;
    void            GetMaxVisColumnsAndLines( USHORT& rnCols, USHORT& rnLines ) const;

    void            SetMRUEntries( const XubString& rEntries, xub_Unicode cSep = ';' );
    XubString       GetMRUEntries( xub_Unicode cSep = ';' ) const;
    void            SetMaxMRUCount( USHORT n );
    USHORT          GetMaxMRUCount() const;

    void            SetEntryData( USHORT nPos, void* pNewData );
    void*           GetEntryData( USHORT nPos ) const;

    void            SetTopEntry( USHORT nPos );
    USHORT          GetTopEntry() const;

    USHORT          GetDisplayLineCount() const;

    USHORT          GetSelectEntryCount() const;
    USHORT          GetSelectEntryPos( USHORT nSelIndex = 0 ) const;
    BOOL            IsEntryPosSelected( USHORT nPos ) const;
    void            SelectEntryPos( USHORT nPos, BOOL bSelect = TRUE );
    void            SetNoSelection();
    Rectangle       GetBoundingRectangle( USHORT nItem ) const;

    /** checks whether a certain point lies within the bounds of
        a list item and returns the item as well as the character position
        the point is at.

If the point is inside an item the item pos is put into rPos and
        the item-relative character index is returned. If the point is not inside
        an item -1 is returned and rPos is unchanged.

        @param rPoint
        tells the point for which an item is requested.

        @param rPos
        gets the item at the specified point rPoint

        @returns
        the item-relative character index at point rPos or -1
        if no item is at that point.
     */
    using Control::GetIndexForPoint;
    long GetIndexForPoint( const Point& rPoint, USHORT& rPos ) const;
};

#endif  // _COMBOBOX_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.3.76); FILE MERGED 2008/04/01 13:01:07 thb 1.3.76.2: #i85898# Stripping all external header guards 2008/03/28 15:44:10 rt 1.3.76.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: combobox.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SV_COMBOBOX_HXX
#define _SV_COMBOBOX_HXX

#include <vcl/dllapi.h>
#include <vcl/ctrl.hxx>
#include <vcl/combobox.h>
#include <vcl/edit.hxx>

class UserDrawEvent;

class ImplListBoxFloatingWindow;
class ImplListBox;
class ImplBtn;

// ------------
// - ComboBox -
// ------------

class VCL_DLLPUBLIC ComboBox : public Edit
{
private:
    Edit*                       mpSubEdit;
    ImplListBox*                mpImplLB;
    ImplBtn*                    mpBtn;
    ImplListBoxFloatingWindow*  mpFloatWin;
    USHORT                      mnDDHeight;
    xub_Unicode                 mcMultiSep;
    BOOL                        mbDDAutoSize        : 1;
    BOOL                        mbSyntheticModify   : 1;
    BOOL                        mbMatchCase         : 1;
    Link                        maSelectHdl;
    Link                        maDoubleClickHdl;

//#if 0 // _SOLAR__PRIVATE
private:
    SAL_DLLPRIVATE void     ImplInitComboBoxData();
    SAL_DLLPRIVATE void     ImplUpdateFloatSelection();

    DECL_DLLPRIVATE_LINK(   ImplSelectHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplCancelHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplDoubleClickHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplClickBtnHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplPopupModeEndHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplSelectionChangedHdl, void* );
    DECL_DLLPRIVATE_LINK(   ImplUserDrawHdl, UserDrawEvent* );
    DECL_DLLPRIVATE_LINK(   ImplAutocompleteHdl, Edit* );

protected:
    using Window::ImplInit;
    SAL_DLLPRIVATE void     ImplInit( Window* pParent, WinBits nStyle );
    SAL_DLLPRIVATE WinBits  ImplInitStyle( WinBits nStyle );
    SAL_DLLPRIVATE void     ImplLoadRes( const ResId& rResId );
    SAL_DLLPRIVATE void     ImplCalcEditHeight();
//#endif

protected:
                    ComboBox( WindowType nType );
    BOOL            IsDropDownBox() const { return mpFloatWin ? TRUE : FALSE; }

    virtual void  FillLayoutData() const;
public:
                    ComboBox( Window* pParent, WinBits nStyle = 0 );
                    ComboBox( Window* pParent, const ResId& rResId );
                    ~ComboBox();

    virtual void    Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags );
    virtual void    Resize();
    virtual long    PreNotify( NotifyEvent& rNEvt );
    virtual long    Notify( NotifyEvent& rNEvt );
    virtual void    StateChanged( StateChangedType nType );
    virtual void    DataChanged( const DataChangedEvent& rDCEvt );

    virtual void    UserDraw( const UserDrawEvent& rUDEvt );
    virtual void    Select();
    virtual void    DoubleClick();

    virtual void    Modify();

    virtual const Wallpaper& GetDisplayBackground() const;

    virtual void    SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, USHORT nFlags = WINDOW_POSSIZE_ALL );
    void            SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
                        { Edit::SetPosSizePixel( rNewPos, rNewSize ); }
    void            SetDropDownSizePixel( const Size& rNewSize )
    { if( IsDropDownBox() ) SetPosSizePixel( 0, 0, rNewSize.Width(), rNewSize.Height(), WINDOW_POSSIZE_SIZE | WINDOW_POSSIZE_DROPDOWN ); }

    Rectangle       GetDropDownPosSizePixel() const;
    Rectangle       GetListPosSizePixel() const;
    // returns empty rectangle in DropDown mode,
    // else it returns the PosSize of the ListBox

    void            SetDropDownLineCount( USHORT nLines );
    USHORT          GetDropDownLineCount() const;

    void            EnableAutoSize( BOOL bAuto );
    BOOL            IsAutoSizeEnabled() const               { return mbDDAutoSize; }

    void            EnableDDAutoWidth( BOOL b );
    BOOL            IsDDAutoWidthEnabled() const;

    void            SetText( const XubString& rStr );
    void            SetText( const XubString& rStr, const Selection& rNewSelection );

    USHORT          InsertEntry( const XubString& rStr, USHORT nPos = COMBOBOX_APPEND );
    USHORT          InsertEntry( const XubString& rStr, const Image& rImage, USHORT nPos = COMBOBOX_APPEND );

    void            RemoveEntry( const XubString& rStr );
    void            RemoveEntry( USHORT nPos );

    void            Clear();

    USHORT          GetEntryPos( const XubString& rStr ) const;
    USHORT          GetEntryPos( const void* pData ) const;
    XubString       GetEntry( USHORT nPos ) const;
    USHORT          GetEntryCount() const;

    BOOL            IsTravelSelect() const;
    BOOL            IsInDropDown() const;
    void            ToggleDropDown();

    long            CalcWindowSizePixel( USHORT nLines ) const;

    void            SetUserItemSize( const Size& rSz );
    const Size&     GetUserItemSize() const;

    void            EnableUserDraw( BOOL bUserDraw );
    BOOL            IsUserDrawEnabled() const;

    void            DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos = FALSE );
    void            SetBorderStyle( USHORT nBorderStyle );

    void            SetSeparatorPos( USHORT n );
    void            SetSeparatorPos();
    USHORT          GetSeparatorPos() const;

    void            EnableAutocomplete( BOOL bEnable, BOOL bMatchCase = FALSE );
    BOOL            IsAutocompleteEnabled() const;

    void            EnableMultiSelection( BOOL bMulti );
    BOOL            IsMultiSelectionEnabled() const;
    void            SetMultiSelectionSeparator( xub_Unicode cSep ) { mcMultiSep = cSep; }
    xub_Unicode     GetMultiSelectionSeparator() const { return mcMultiSep; }

    void            SetSelectHdl( const Link& rLink )       { maSelectHdl = rLink; }
    const Link&     GetSelectHdl() const                    { return maSelectHdl; }
    void            SetDoubleClickHdl( const Link& rLink )  { maDoubleClickHdl = rLink; }
    const Link&     GetDoubleClickHdl() const               { return maDoubleClickHdl; }

    Size            CalcMinimumSize() const;
    virtual Size    GetOptimalSize(WindowSizeType eType) const;
    Size            CalcAdjustedSize( const Size& rPrefSize ) const;
    using Edit::CalcSize;
    Size            CalcSize( USHORT nColumns, USHORT nLines ) const;
    void            GetMaxVisColumnsAndLines( USHORT& rnCols, USHORT& rnLines ) const;

    void            SetMRUEntries( const XubString& rEntries, xub_Unicode cSep = ';' );
    XubString       GetMRUEntries( xub_Unicode cSep = ';' ) const;
    void            SetMaxMRUCount( USHORT n );
    USHORT          GetMaxMRUCount() const;

    void            SetEntryData( USHORT nPos, void* pNewData );
    void*           GetEntryData( USHORT nPos ) const;

    void            SetTopEntry( USHORT nPos );
    USHORT          GetTopEntry() const;

    USHORT          GetDisplayLineCount() const;

    USHORT          GetSelectEntryCount() const;
    USHORT          GetSelectEntryPos( USHORT nSelIndex = 0 ) const;
    BOOL            IsEntryPosSelected( USHORT nPos ) const;
    void            SelectEntryPos( USHORT nPos, BOOL bSelect = TRUE );
    void            SetNoSelection();
    Rectangle       GetBoundingRectangle( USHORT nItem ) const;

    /** checks whether a certain point lies within the bounds of
        a list item and returns the item as well as the character position
        the point is at.

If the point is inside an item the item pos is put into rPos and
        the item-relative character index is returned. If the point is not inside
        an item -1 is returned and rPos is unchanged.

        @param rPoint
        tells the point for which an item is requested.

        @param rPos
        gets the item at the specified point rPoint

        @returns
        the item-relative character index at point rPos or -1
        if no item is at that point.
     */
    using Control::GetIndexForPoint;
    long GetIndexForPoint( const Point& rPoint, USHORT& rPos ) const;
};

#endif  // _COMBOBOX_HXX
<|endoftext|>


<commit_before><commit_msg>coverity#1306212 silence Infinite loop<commit_after><|endoftext|>


<commit_before><commit_msg>use SAL_N_ELEMENTS<commit_after><|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <vector>
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pwd.h>
extern char **environ;
#endif

#define DEF_Server
#include "../Server.h"

CServer *Server;

#ifdef _WIN32
#include <Windows.h>

bool CopyFolder(std::wstring src, std::wstring dst)
{
	if(!os_create_dir(dst))
		return false;

	std::vector<SFile> curr_files=getFiles(src);
	for(size_t i=0;i<curr_files.size();++i)
	{
		if(curr_files[i].isdir)
		{
			bool b=CopyFolder(src+os_file_sep()+curr_files[i].name, dst+os_file_sep()+curr_files[i].name);
			if(!b)
				return false;
		}
		else
		{
			if(!os_create_hardlink(dst+os_file_sep()+curr_files[i].name, src+os_file_sep()+curr_files[i].name, false, NULL) )
			{
				BOOL b=CopyFileW( (src+os_file_sep()+curr_files[i].name).c_str(), (dst+os_file_sep()+curr_files[i].name).c_str(), FALSE);
				if(!b)
				{
					return false;
				}
			}
		}
	}

	return true;
}
#endif

std::string getBackupfolderPath(void)
{
	std::string fn;
#ifdef _WIN32
	fn=trim(getFile("backupfolder"));
#else
	fn=trim(getFile("/etc/urbackup/backupfolder"));
#endif
	if(fn.find("\n")!=std::string::npos)
		fn=getuntil("\n", fn);
	if(fn.find("\r")!=std::string::npos)
		fn=getuntil("\r", fn);

	return fn;
}

std::string handleFilename(std::string fn)
{
	fn=conv_filename(fn);
	if(fn=="..")
	{
		return "";
	}
	return fn;
}

#ifndef _WIN32
int exec_wait(const std::string& path, ...)
{
	va_list vl;
	va_start(vl, path);

	std::vector<char*> args;
	args.push_back(const_cast<char*>(path.c_str()));

	while(true)
	{
		const char* p = va_arg(vl, const char*);
		if(p==NULL) break;
		args.push_back(const_cast<char*>(p));
	}
	va_end(vl);

	args.push_back(NULL);

	pid_t child_pid = fork();

	if(child_pid==0)
	{
		environ = new char*[1];
		*environ=NULL;
		int rc = execvp(path.c_str(), args.data());
		exit(rc);
	}
	else
	{
		int status;
		waitpid(child_pid, &status, 0);
		if(WIFEXITED(status))
		{
			return WEXITSTATUS(status);
		}
		else
		{
			return -1;
		}
	}
}

bool chown_dir(const std::string& dir)
{
	passwd* user_info = getpwnam("urbackup");
	if(user_info)
	{
		int rc = chown(dir.c_str(), user_info->pw_uid, user_info->pw_gid);
		return rc!=-1;
	}
	return false;
}

std::string find_btrfs_cmd()()
{
	static std::string btrfs_cmd;

	if(!btrfs_cmd.empty())
	{
		return btrfs_cmd;
	}

	if(exec_wait("/sbin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/bin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/bin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/sbin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/usr/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/bin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/usr/bin/btrfs";
		return btrfs_cmd;
	}
	else
	{
		btrfs_cmd="btrfs";
		return btrfs_cmd;
	}
}
#endif

bool create_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return os_create_dir(subvolume_folder);
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "create", subvolume_folder.c_str(), NULL);
	chown_dir(subvolume_folder);
	return rc==0;
#endif
}

bool create_snapshot(std::string snapshot_src, std::string snapshot_dst)
{
#ifdef _WIN32
	return CopyFolder(widen(snapshot_src), widen(snapshot_dst));
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "snapshot", snapshot_src.c_str(), snapshot_dst.c_str(), NULL);
	chown_dir(snapshot_dst);
	return rc==0;
#endif
}

bool remove_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return os_remove_nonempty_dir(widen(subvolume_folder));
#else
	int compat_rc = exec_wait(find_btrfs_cmd(), "subvolume", "delete", "-c", NULL);

	int rc;
	if(compat_rc==12)
	{
		rc=exec_wait(find_btrfs_cmd(), "subvolume", "delete", subvolume_folder.c_str(), NULL);
	}
	else
	{
		rc=exec_wait(find_btrfs_cmd(), "subvolume", "delete", "-c", subvolume_folder.c_str(), NULL);
	}
	return rc==0;
#endif
}

bool is_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return true;
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "list", subvolume_folder.c_str(), NULL);
	return rc==0;
#endif
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		std::cout << "Not enough parameters" << std::endl;
		return 1;
	}

	std::string cmd=argv[1];

	std::string backupfolder=getBackupfolderPath();

	if(backupfolder.empty())
	{
		std::cout << "Backupfolder not set" << std::endl;
		return 1;
	}

#ifndef _WIN32
	if(seteuid(0)!=0)
	{
		std::cout << "Cannot become root user" << std::endl;
		return 1;
	}
#endif

	if(cmd=="create")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for create" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return create_subvolume(subvolume_folder)?0:1;
	}
	else if(cmd=="snapshot")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for snapshot" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string src_name=handleFilename(argv[3]);
		std::string dst_name=handleFilename(argv[4]);

		std::string subvolume_src_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+src_name;
		std::string subvolume_dst_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+dst_name;

		return create_snapshot(subvolume_src_folder, subvolume_dst_folder)?0:1;
	}
	else if(cmd=="remove")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for remove" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return remove_subvolume(subvolume_folder)?0:1;
	}
	else if(cmd=="test")
	{
		std::string clientdir=backupfolder+os_file_sep()+"testA54hj5luZtlorr494";

		bool create_dir_rc=os_create_dir(clientdir);
		if(!create_dir_rc)
		{
			remove_subvolume(clientdir+os_file_sep()+"A");
			remove_subvolume(clientdir+os_file_sep()+"B");
			os_remove_dir(clientdir);
		}
		create_dir_rc = create_dir_rc || os_create_dir(clientdir);
		if(create_dir_rc)
		{
			if(!create_subvolume(clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Creating test subvolume failed" << std::endl;
				os_remove_dir(clientdir);
				return 1;
			}

			bool suc=true;

			if(!create_snapshot(clientdir+os_file_sep()+"A", clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Creating test snapshot failed" << std::endl;
				suc=false;
			}

			if(suc)
			{
				writestring("test", clientdir+os_file_sep()+"A"+os_file_sep()+"test");

				if(!os_create_hardlink(clientdir+os_file_sep()+"B"+os_file_sep()+"test", clientdir+os_file_sep()+"A"+os_file_sep()+"test", true, NULL))
				{
					std::cout << "TEST FAILED: Creating cross sub-volume reflink failed. Need Linux kernel >= 3.6." << std::endl;
					suc=false;
				}
				else
				{
					if(getFile(clientdir+os_file_sep()+"B"+os_file_sep()+"test")!="test")
					{
						std::cout << "TEST FAILED: Cannot read reflinked file" << std::endl;
						suc=false;
					}
				}
			}

			if(!remove_subvolume(clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Removing subvolume A failed" << std::endl;
				suc=false;
			}

			if(!remove_subvolume(clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Removing subvolume B failed" << std::endl;
				suc=false;
			}

			if(!os_remove_dir(clientdir))
			{
				std::cout << "TEST FAILED: Removing test clientdir failed" << std::endl;
				return 1;
			}

			if(!suc)
			{
				return 1;
			}
		}
		else
		{
			std::cout << "TEST FAILED: Creating test clientdir \"" << clientdir << "\" failed" << std::endl;
			return 1;
		}
		std::cout << "TEST OK" << std::endl;
		return 0;
	}
	else if(cmd=="issubvolume")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for issubvolume" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return is_subvolume(subvolume_folder)?0:1;
	}
	else
	{
		std::cout << "Command not found" << std::endl;
		return 1;
	}
}

<commit_msg>Look first in $PATH<commit_after>#include <string>
#include <iostream>
#include <vector>
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pwd.h>
extern char **environ;
#endif

#define DEF_Server
#include "../Server.h"

CServer *Server;

#ifdef _WIN32
#include <Windows.h>

bool CopyFolder(std::wstring src, std::wstring dst)
{
	if(!os_create_dir(dst))
		return false;

	std::vector<SFile> curr_files=getFiles(src);
	for(size_t i=0;i<curr_files.size();++i)
	{
		if(curr_files[i].isdir)
		{
			bool b=CopyFolder(src+os_file_sep()+curr_files[i].name, dst+os_file_sep()+curr_files[i].name);
			if(!b)
				return false;
		}
		else
		{
			if(!os_create_hardlink(dst+os_file_sep()+curr_files[i].name, src+os_file_sep()+curr_files[i].name, false, NULL) )
			{
				BOOL b=CopyFileW( (src+os_file_sep()+curr_files[i].name).c_str(), (dst+os_file_sep()+curr_files[i].name).c_str(), FALSE);
				if(!b)
				{
					return false;
				}
			}
		}
	}

	return true;
}
#endif

std::string getBackupfolderPath(void)
{
	std::string fn;
#ifdef _WIN32
	fn=trim(getFile("backupfolder"));
#else
	fn=trim(getFile("/etc/urbackup/backupfolder"));
#endif
	if(fn.find("\n")!=std::string::npos)
		fn=getuntil("\n", fn);
	if(fn.find("\r")!=std::string::npos)
		fn=getuntil("\r", fn);

	return fn;
}

std::string handleFilename(std::string fn)
{
	fn=conv_filename(fn);
	if(fn=="..")
	{
		return "";
	}
	return fn;
}

#ifndef _WIN32
int exec_wait(const std::string& path, ...)
{
	va_list vl;
	va_start(vl, path);

	std::vector<char*> args;
	args.push_back(const_cast<char*>(path.c_str()));

	while(true)
	{
		const char* p = va_arg(vl, const char*);
		if(p==NULL) break;
		args.push_back(const_cast<char*>(p));
	}
	va_end(vl);

	args.push_back(NULL);

	pid_t child_pid = fork();

	if(child_pid==0)
	{
		environ = new char*[1];
		*environ=NULL;
		int rc = execvp(path.c_str(), args.data());
		exit(rc);
	}
	else
	{
		int status;
		waitpid(child_pid, &status, 0);
		if(WIFEXITED(status))
		{
			return WEXITSTATUS(status);
		}
		else
		{
			return -1;
		}
	}
}

bool chown_dir(const std::string& dir)
{
	passwd* user_info = getpwnam("urbackup");
	if(user_info)
	{
		int rc = chown(dir.c_str(), user_info->pw_uid, user_info->pw_gid);
		return rc!=-1;
	}
	return false;
}

std::string find_btrfs_cmd()()
{
	static std::string btrfs_cmd;

	if(!btrfs_cmd.empty())
	{
		return btrfs_cmd;
	}

	if(exec_wait("btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/sbin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/bin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/bin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/sbin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/usr/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/bin/btrfs", "--version", NULL)==0)
	{
		btrfs_cmd="/usr/bin/btrfs";
		return btrfs_cmd;
	}
	else
	{
		btrfs_cmd="btrfs";
		return btrfs_cmd;
	}
}
#endif

bool create_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return os_create_dir(subvolume_folder);
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "create", subvolume_folder.c_str(), NULL);
	chown_dir(subvolume_folder);
	return rc==0;
#endif
}

bool create_snapshot(std::string snapshot_src, std::string snapshot_dst)
{
#ifdef _WIN32
	return CopyFolder(widen(snapshot_src), widen(snapshot_dst));
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "snapshot", snapshot_src.c_str(), snapshot_dst.c_str(), NULL);
	chown_dir(snapshot_dst);
	return rc==0;
#endif
}

bool remove_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return os_remove_nonempty_dir(widen(subvolume_folder));
#else
	int compat_rc = exec_wait(find_btrfs_cmd(), "subvolume", "delete", "-c", NULL);

	int rc;
	if(compat_rc==12)
	{
		rc=exec_wait(find_btrfs_cmd(), "subvolume", "delete", subvolume_folder.c_str(), NULL);
	}
	else
	{
		rc=exec_wait(find_btrfs_cmd(), "subvolume", "delete", "-c", subvolume_folder.c_str(), NULL);
	}
	return rc==0;
#endif
}

bool is_subvolume(std::string subvolume_folder)
{
#ifdef _WIN32
	return true;
#else
	int rc=exec_wait(find_btrfs_cmd(), "subvolume", "list", subvolume_folder.c_str(), NULL);
	return rc==0;
#endif
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		std::cout << "Not enough parameters" << std::endl;
		return 1;
	}

	std::string cmd=argv[1];

	std::string backupfolder=getBackupfolderPath();

	if(backupfolder.empty())
	{
		std::cout << "Backupfolder not set" << std::endl;
		return 1;
	}

#ifndef _WIN32
	if(seteuid(0)!=0)
	{
		std::cout << "Cannot become root user" << std::endl;
		return 1;
	}
#endif

	if(cmd=="create")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for create" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return create_subvolume(subvolume_folder)?0:1;
	}
	else if(cmd=="snapshot")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for snapshot" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string src_name=handleFilename(argv[3]);
		std::string dst_name=handleFilename(argv[4]);

		std::string subvolume_src_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+src_name;
		std::string subvolume_dst_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+dst_name;

		return create_snapshot(subvolume_src_folder, subvolume_dst_folder)?0:1;
	}
	else if(cmd=="remove")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for remove" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return remove_subvolume(subvolume_folder)?0:1;
	}
	else if(cmd=="test")
	{
		std::string clientdir=backupfolder+os_file_sep()+"testA54hj5luZtlorr494";

		bool create_dir_rc=os_create_dir(clientdir);
		if(!create_dir_rc)
		{
			remove_subvolume(clientdir+os_file_sep()+"A");
			remove_subvolume(clientdir+os_file_sep()+"B");
			os_remove_dir(clientdir);
		}
		create_dir_rc = create_dir_rc || os_create_dir(clientdir);
		if(create_dir_rc)
		{
			if(!create_subvolume(clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Creating test subvolume failed" << std::endl;
				os_remove_dir(clientdir);
				return 1;
			}

			bool suc=true;

			if(!create_snapshot(clientdir+os_file_sep()+"A", clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Creating test snapshot failed" << std::endl;
				suc=false;
			}

			if(suc)
			{
				writestring("test", clientdir+os_file_sep()+"A"+os_file_sep()+"test");

				if(!os_create_hardlink(clientdir+os_file_sep()+"B"+os_file_sep()+"test", clientdir+os_file_sep()+"A"+os_file_sep()+"test", true, NULL))
				{
					std::cout << "TEST FAILED: Creating cross sub-volume reflink failed. Need Linux kernel >= 3.6." << std::endl;
					suc=false;
				}
				else
				{
					if(getFile(clientdir+os_file_sep()+"B"+os_file_sep()+"test")!="test")
					{
						std::cout << "TEST FAILED: Cannot read reflinked file" << std::endl;
						suc=false;
					}
				}
			}

			if(!remove_subvolume(clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Removing subvolume A failed" << std::endl;
				suc=false;
			}

			if(!remove_subvolume(clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Removing subvolume B failed" << std::endl;
				suc=false;
			}

			if(!os_remove_dir(clientdir))
			{
				std::cout << "TEST FAILED: Removing test clientdir failed" << std::endl;
				return 1;
			}

			if(!suc)
			{
				return 1;
			}
		}
		else
		{
			std::cout << "TEST FAILED: Creating test clientdir \"" << clientdir << "\" failed" << std::endl;
			return 1;
		}
		std::cout << "TEST OK" << std::endl;
		return 0;
	}
	else if(cmd=="issubvolume")
	{
		if(argc<4)
		{
			std::cout << "Not enough parameters for issubvolume" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[2]);
		std::string name=handleFilename(argv[3]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;

		return is_subvolume(subvolume_folder)?0:1;
	}
	else
	{
		std::cout << "Command not found" << std::endl;
		return 1;
	}
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// -----------------------------------------------------------------------
#include "depapp.hxx"
#include <ucbhelper/contentbroker.hxx>
#include <ucbhelper/configurationkeys.hxx>

void MyApp::Main()
{
#if defined(WNT)
    pDebugFile = fopen( "fprintf.out", "w" );
#endif

    pMyApp = GetpApp();
    MyWin aMainWin( NULL, WB_APP | WB_STDWORK );
    pAppWindow = &aMainWin;
   // pToolBarFrame = new FloatingWindow( aMainWin, WB_STDWORK );
    //pToolBox = new ToolBox(pToolBarFrame,DtSodResId(TID_SOLDEP_MAIN));

    pSolDep = new SolDep( &aMainWin );
    pSolDep->Init();
    aMainWin.SetText( String::CreateFromAscii( SOLDEPL_NAME ));
    pSolDep->Hide();
    aMainWin.Show();
    Help aHelp;
    SetHelp(&aHelp);
    aHelp.EnableContextHelp();
    aHelp.EnableQuickHelp();
    Execute();
    delete pResMgr;
    delete pSolDep;
}

// -----------------------------------------------------------------------

MyWin::MyWin( Window* pParent, WinBits nWinStyle ) :
    WorkWindow( pParent, nWinStyle )//,aToolBox( this, DtSodResId(TID_SOLDEP_MAIN)),
        // depper aTaskBarFrame(this, 0)
{
//depper    aTaskBarFrame.EnableAlwaysOnTop();

//depper    aMenuBar.InsertItem( 1, XubString( RTL_CONSTASCII_USTRINGPARAM( "~Source" ) ) );
//depper    aMenuBar.InsertItem( 2, XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exit" ) ) );
//depper    SetMenuBar( &aMenuBar );
//depper    aToolBox.SetPosSizePixel( Point( 0,0 ), Size( 1100,35 ));
//    aToolBox.Show();
}

// -----------------------------------------------------------------------

void MyWin::MouseMove( const MouseEvent& rMEvt )
{
    WorkWindow::MouseMove( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::MouseButtonDown( const MouseEvent& rMEvt )
{
    WorkWindow::MouseButtonDown( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::MouseButtonUp( const MouseEvent& rMEvt )
{
    WorkWindow::MouseButtonUp( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::KeyInput( const KeyEvent& rKEvt )
{
    WorkWindow::KeyInput( rKEvt );
}

// -----------------------------------------------------------------------

void MyWin::KeyUp( const KeyEvent& rKEvt )
{
    WorkWindow::KeyUp( rKEvt );
}

// -----------------------------------------------------------------------

void MyWin::Paint( const Rectangle& rRect )
{
    WorkWindow::Paint( rRect );
}

// -----------------------------------------------------------------------

void MyWin::Resize()
{
    ((MyApp*)GetpApp())->GetSolDep()->Resize();
    WorkWindow::Resize();
}

SAL_IMPLEMENT_MAIN()
{
    //Reference< XMultiServiceFactory > xMS;

    // for this to work make sure an <appname>.ini file is available, you can just copy soffice.ini
    Reference< XComponentContext > xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext();

    //xMS = cppu::createRegistryServiceFactory(
    //              rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" ) ), sal_True );

    Reference< XMultiServiceFactory > xMS( xComponentContext->getServiceManager(), UNO_QUERY);

    InitVCL( xMS );
    ::comphelper::setProcessServiceFactory(xMS);
    com::sun::star::uno::Sequence< com::sun::star::uno::Any > aArgs(2);
    aArgs[0] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
    aArgs[1] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );

    ::ucbhelper::ContentBroker::initialize( xMS, aArgs );

    aMyApp.Main();
    DeInitVCL();
    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>RTL_CONSTASCII_USTRINGPARAM in bootstrap<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// -----------------------------------------------------------------------
#include "depapp.hxx"
#include <ucbhelper/contentbroker.hxx>
#include <ucbhelper/configurationkeys.hxx>

void MyApp::Main()
{
#if defined(WNT)
    pDebugFile = fopen( "fprintf.out", "w" );
#endif

    pMyApp = GetpApp();
    MyWin aMainWin( NULL, WB_APP | WB_STDWORK );
    pAppWindow = &aMainWin;
   // pToolBarFrame = new FloatingWindow( aMainWin, WB_STDWORK );
    //pToolBox = new ToolBox(pToolBarFrame,DtSodResId(TID_SOLDEP_MAIN));

    pSolDep = new SolDep( &aMainWin );
    pSolDep->Init();
    aMainWin.SetText( String::CreateFromAscii( SOLDEPL_NAME ));
    pSolDep->Hide();
    aMainWin.Show();
    Help aHelp;
    SetHelp(&aHelp);
    aHelp.EnableContextHelp();
    aHelp.EnableQuickHelp();
    Execute();
    delete pResMgr;
    delete pSolDep;
}

// -----------------------------------------------------------------------

MyWin::MyWin( Window* pParent, WinBits nWinStyle ) :
    WorkWindow( pParent, nWinStyle )//,aToolBox( this, DtSodResId(TID_SOLDEP_MAIN)),
        // depper aTaskBarFrame(this, 0)
{
//depper    aTaskBarFrame.EnableAlwaysOnTop();

//depper    aMenuBar.InsertItem( 1, XubString( RTL_CONSTASCII_USTRINGPARAM( "~Source" ) ) );
//depper    aMenuBar.InsertItem( 2, XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exit" ) ) );
//depper    SetMenuBar( &aMenuBar );
//depper    aToolBox.SetPosSizePixel( Point( 0,0 ), Size( 1100,35 ));
//    aToolBox.Show();
}

// -----------------------------------------------------------------------

void MyWin::MouseMove( const MouseEvent& rMEvt )
{
    WorkWindow::MouseMove( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::MouseButtonDown( const MouseEvent& rMEvt )
{
    WorkWindow::MouseButtonDown( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::MouseButtonUp( const MouseEvent& rMEvt )
{
    WorkWindow::MouseButtonUp( rMEvt );
}

// -----------------------------------------------------------------------

void MyWin::KeyInput( const KeyEvent& rKEvt )
{
    WorkWindow::KeyInput( rKEvt );
}

// -----------------------------------------------------------------------

void MyWin::KeyUp( const KeyEvent& rKEvt )
{
    WorkWindow::KeyUp( rKEvt );
}

// -----------------------------------------------------------------------

void MyWin::Paint( const Rectangle& rRect )
{
    WorkWindow::Paint( rRect );
}

// -----------------------------------------------------------------------

void MyWin::Resize()
{
    ((MyApp*)GetpApp())->GetSolDep()->Resize();
    WorkWindow::Resize();
}

SAL_IMPLEMENT_MAIN()
{
    //Reference< XMultiServiceFactory > xMS;

    // for this to work make sure an <appname>.ini file is available, you can just copy soffice.ini
    Reference< XComponentContext > xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext();

    //xMS = cppu::createRegistryServiceFactory(
    //              rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" ) ), sal_True );

    Reference< XMultiServiceFactory > xMS( xComponentContext->getServiceManager(), UNO_QUERY);

    InitVCL( xMS );
    ::comphelper::setProcessServiceFactory(xMS);
    com::sun::star::uno::Sequence< com::sun::star::uno::Any > aArgs(2);
    aArgs[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( UCB_CONFIGURATION_KEY1_LOCAL ));
    aArgs[1] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( UCB_CONFIGURATION_KEY2_OFFICE ));

    ::ucbhelper::ContentBroker::initialize( xMS, aArgs );

    aMyApp.Main();
    DeInitVCL();
    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// $Id: MOL2File.C,v 1.3 2000/05/15 19:16:27 oliver Exp $

#include <BALL/FORMAT/MOL2File.h>
#include <BALL/DATATYPE/string.h>
#include <BALL/KERNEL/residue.h>
#include <BALL/KERNEL/protein.h>
#include <BALL/KERNEL/atom.h>
#include <BALL/KERNEL/PDBAtom.h>
#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/PTE.h>

#include <stack>

using namespace std;

namespace BALL
{
	MOL2File::MOL2File()
	{
	}

	MOL2File::MOL2File(const String& name, File::OpenMode open_mode)
		: File(name, open_mode)
	{
	}

	MOL2File::~MOL2File()
	{
	}

	void MOL2File::write(const System& /* system */)
	{
	}

	// the Tripos record type identifier: RTI
	const String MOL2File::TRIPOS = "@<TRIPOS>";
	const Size MOL2File::MAX_LENGTH_ = 4096;

	void MOL2File::read(System& system)
	{
		// remove old rubbish from the system
		system.destroy();

		// remember the line number for error messages
		number_of_lines_ = 0;
		String line;

    while (getline(buffer_, MAX_LENGTH_))
    {
      number_of_lines_++;
      line = buffer_;
			line.toUpper();

			while (line.hasPrefix(TRIPOS))
			{
				// we found a "Record Type Identifier" (RTI)
				String RTI = line.after(TRIPOS);
				RTI.trim();

				#ifdef BALL_DEBUG
					// BAUSTELLE: debug code
					Log.info() << "MOL2File::read: reading record " << RTI << " in line " << number_of_lines_ << endl;
				#endif

				// interpret the RTI (at least the known ones)
				if (RTI == "ATOM")
				{
					line = readAtomSection_();
				}
				else if (RTI == "BOND")
				{
					line = readBondSection_();
				}
				else if (RTI == "MOLECULE")
				{
					line = readMoleculeSection_();
				}
				else if (RTI == "SET")
				{
					line = readSetSection_();
				}
				else if (RTI == "SUBSTRUCTURE")
				{
					line = readSubstructureSection_();
				}
				else
				{
					// we found an unknown MOL2 section: print a warning message and ignore it!
					Log.warn() << "MOL2File::read: section ignored: " << line << endl;
				}
			}
		}
	}

	String MOL2File::readAtomSection_()
	{
		String line;
		Size number_of_fields = 1;
		while (getline(buffer_, MAX_LENGTH_) && (number_of_fields > 0) && !line.hasPrefix(TRIPOS))
		{
			number_of_lines_++;
			line = buffer_;
			line.trim();
			Size number_of_fields = line.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 6)
				{
					Log.error() << "MOL2File::readAtomSection_: too few fields for an atom entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[10];
					line.split(fields, 10);

					// create an atom and assign the fields of the line
					AtomStruct	atom;
					atom.name = fields[1];
					atom.position.x = fields[2].toFloat();
					atom.position.y = fields[3].toFloat();
					atom.position.z = fields[4].toFloat();
					atom.type = fields[5];
					atom.substructure = fields[6].toInt();
					atom.substructure_name = fields[7];
					atom.charge = fields[8].toFloat();

					// remember this atom
					atoms_.push_back(atom);
				}
			}
		}

		number_of_lines_++;

		return line;
	}

	String MOL2File::readBondSection_()
	{
		String line;
		Size number_of_fields = 1;
		while (getline(buffer_, MAX_LENGTH_) && (number_of_fields > 0) && !line.hasPrefix(TRIPOS))
		{
			number_of_lines_++;
			line = buffer_;
			line.trim();
			Size number_of_fields = line.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 4)
				{
					Log.error() << "MOL2File::readBondSection_: too few fields for a bond entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[4];
					line.split(fields, 4);

					// create an atom and assign the fields of the line
					BondStruct	bond;
					bond.atom1 = fields[1].toInt();
					bond.atom1 = fields[2].toInt();
					bond.type = fields[3];

					// remember this bond
					bonds_.push_back(bond);
				}
			}
		}

		number_of_lines_++;

		return "";
	}

	String MOL2File::readSetSection_()
	{
		String line;
		Size number_of_fields = 1;
		while (getline(buffer_, MAX_LENGTH_) && (number_of_fields > 0) && !line.hasPrefix(TRIPOS))
		{
			number_of_lines_++;
			line = buffer_;
			line.trim();
			Size number_of_fields = line.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 3)
				{
					Log.error() << "MOL2File::readBondSection_: too few fields for a bond entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[6];
					line.split(fields, 6);

					// create an atom and assign the fields of the line
					SetStruct	set;
					set.name = fields[1].toInt();
					set.type = fields[3].toInt();
					set.subtype = fields[4];
					set.comment = fields[6];
					if (fields[2] == "static")
					{
						getline(buffer_, MAX_LENGTH_);
						number_of_lines_++;
						line = buffer_;
						line.trim();
						Size number_of_fields = line.countFields();

						for (Size i = 1; (i <= (Size)line.getField(0).toInt()) && (i < number_of_fields); i++)
						{
							set.members.push_back(line.getField(i).toInt());
						}

						// remember this set
						sets_.push_back(set);

					}
					else
					{
						// we cannot read dynamic sets. What is the syntax of these rules?
						Log.warn() << "MOL2File::readSetSection: unsupported set type: " << fields[2] << ". Ignored." << endl;
					}
				}
			}
		}

		number_of_lines_++;

		return "";
	}

	String MOL2File::readMoleculeSection_()
	{
		String line;
		Size number_of_fields = 1;
		while (getline(buffer_, MAX_LENGTH_) && (number_of_fields > 0) && !line.hasPrefix(TRIPOS))
		{
			number_of_lines_++;
			line = buffer_;
			line.trim();
			Size number_of_fields = line.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 3)
				{
					Log.error() << "MOL2File::readBondSection_: too few fields for a bond entry in line "
						<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[6];
					line.split(fields, 6);

					// create an atom and assign the fields of the line
					SetStruct	set;
					set.name = fields[1].toInt();
					set.type = fields[3].toInt();
					set.subtype = fields[4];
					set.comment = fields[6];
					if (fields[2] == "static")
					{
						getline(buffer_, MAX_LENGTH_);
						number_of_lines_++;
						line = buffer_;
						line.trim();
						Size number_of_fields = line.countFields();

						for (Size i = 1; (i <= (Size)line.getField(0).toInt()) && (i < number_of_fields); i++)
						{
							set.members.push_back(line.getField(i).toInt());
						}

						// remember this set
						sets_.push_back(set);

					}
					else
					{
						// we cannot read dynamic sets. What is the syntax of these rules?
						Log.warn() << "MOL2File::readSetSection: unsupported set type: " << fields[2] << ". Ignored." << endl;
					}
				}
			}
		}

		number_of_lines_++;

		return "";
	}

	String MOL2File::readSubstructureSection_()
	{
		return "";
	}

} // namespace BALL
<commit_msg>added: write should work rudimentary<commit_after>// $Id: MOL2File.C,v 1.4 2000/05/23 05:44:33 oliver Exp $

#include <BALL/FORMAT/MOL2File.h>
#include <BALL/DATATYPE/string.h>
#include <BALL/KERNEL/residue.h>
#include <BALL/KERNEL/protein.h>
#include <BALL/KERNEL/system.h>
#include <BALL/KERNEL/atom.h>
#include <BALL/KERNEL/PDBAtom.h>
#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/KERNEL/forEach.h>

#include <stack>

using namespace std;

namespace BALL
{
	MOL2File::MOL2File()
	{
	}

	MOL2File::MOL2File(const String& name, File::OpenMode open_mode)
		: File(name, open_mode)
	{
	}

	MOL2File::~MOL2File()
	{
	}

	// the Tripos record type identifier: RTI
	const String MOL2File::TRIPOS = "@<TRIPOS>";
	const Size MOL2File::MAX_LENGTH_ = 4096;

	void MOL2File::write(const System& system)
	{
		// create a shorthand for the file of the MOL2File object
		File& f = static_cast<File&>(*this);

		// write the molecule header
		f << TRIPOS << "MOLECULE" << endl;

		// if the system name is empty...
		String name = system.getName();
		if (name == "")
		{
			// .. replace it by four stars
			name = "****";
		}
		f << name << endl;

		// determine the number of substructures (= fragments)
		// and hash the fragment pointers to a substructure ID (Position)
		// the vector substr_names holds the assembled names of the
		// substructures
		HashMap<const BaseFragment*, Position> substructure_map;
		vector<String>	substructure_name;
		vector<const BaseFragment*> substructure_pointers;
		BaseFragmentConstIterator frag_it = system.beginBaseFragment();

		// increment the iterator once to skip the system (which is no substructure)
		++frag_it;
		for (; +frag_it; ++frag_it)
		{
			name = frag_it->getName();
			// if the fragment is a residue...
			const Residue* residue = dynamic_cast<const Residue*>(&*frag_it);
			if (residue != 0)
			{
				// ...append its ID (PDB ID) to the name. E.g.: ALA154
				name = name + residue->getID();
			}

			// empty names are replaced by "****"
			name.trim();
			if (name == "")
			{
				name = "****";
			}

			// store the name and the pointer
			substructure_map.insert(pair<const BaseFragment*, Position>(&*frag_it, substructure_name.size()));
			substructure_pointers.push_back(&*frag_it);
			substructure_name.push_back(name);
		}

		// count the bonds in the system
		Atom::BondConstIterator bond_it;
		AtomConstIterator atom_it;
		Size number_of_bonds = 0;
		BALL_FOREACH_BOND(system, atom_it, bond_it)
		{
			number_of_bonds++;
		}

		// write the number of atoms, bonds, and substructures
		f << system.countAtoms() << " " << number_of_bonds << " " << substructure_name.size() << endl;

		String mol_type = "SMALL";
		MoleculeConstIterator mol_it = system.beginMolecule();
		for (; +mol_it; ++mol_it)
		{
			// if we find a protein, set the molecule type to PROTEIN
			if (RTTI::isKindOf<Protein>(*mol_it))
			{
				mol_type = "PROTEIN";
			}
			// if there is a nucleic acid in the system,
			// set the type to NUCLEIC_ACID. PROTEIN has priority!
			if (RTTI::isKindOf<NucleicAcid>(*mol_it) && (mol_type == "SMALL"))
			{
				mol_type = "PROTEIN";
			}
		}

		// write it the molecule type, the charge type, flags, and a comment line
		f << mol_type << endl
			<< "USER_CHARGES" << endl
			<< endl
			<< endl;
		// done with the molecule header.

		// now, write the atoms: Format: atom_id atom_name x y z atom_type subst_id subst_name charge
		// the atom pointers are stored in a hash map (required for bond list construction)
		f << TRIPOS << "ATOM" << endl;

		HashMap<const Atom*, Position> atom_map;
		Size number_of_atoms = 0;
		atom_it = system.beginAtom();
		for (; +atom_it; ++atom_it)
		{
			number_of_atoms++;
			// remember this atom in the hash map
			atom_map.insert(pair<const Atom*, Position>(&*atom_it, number_of_atoms));

			f << number_of_atoms << " ";
			name = atom_it->getName();
			name.trim();
			if (name == "")
			{
				// replace empty names by "****"
				name = "****";
			}
			f << name << " "
				<< atom_it->getPosition().x << " "
				<< atom_it->getPosition().y << " "
				<< atom_it->getPosition().z << " ";
			name = getSybylType_(*atom_it);
			name.trim();
			if (name == "")
			{
				// replace empty type names by "****"
				name = "****";
			}
			f	<< name << " ";

			// if the atom has a substructure, retrieve its name and ID
			const BaseFragment* frag = dynamic_cast<const BaseFragment*>(atom_it->getParent());
			if ((frag != 0) && substructure_map.has(frag))
			{
				f << substructure_map[frag] << " " << substructure_name[substructure_map[frag]] << " ";
			}
			else
			{
				// write empty substructure ID and name
				f << "1 **** ";
			}

			// write the charge
			f << atom_it->getCharge() << endl;
		}
		// done with the atom section.

		// write the bonds
		if (number_of_bonds > 0)
		{
			f << TRIPOS << "BOND" << endl;
			number_of_bonds = 0;
			BALL_FOREACH_BOND(system, atom_it, bond_it)
			{
				number_of_bonds++;
				// check whether both atoms were written
				if (atom_map.has(bond_it->getFirstAtom()) && atom_map.has(bond_it->getSecondAtom()))
				{

					f << number_of_bonds << " " << atom_map[bond_it->getFirstAtom()]
						<< " " << atom_map[bond_it->getSecondAtom()] << " ";

					// determine the bond type
					switch (bond_it->getOrder())
					{
						case Bond::ORDER__AROMATIC:		f << "ar" << endl; break;
						case Bond::ORDER__DOUBLE:	  	f << "2"  << endl; break;
						case Bond::ORDER__TRIPLE:	  	f << "3"  << endl; break;
						case Bond::ORDER__QUADRUPLE:	f << "4"  << endl; break;

						case Bond::ORDER__UNKNOWN:
						case Bond::ORDER__SINGLE:		  f << "1"  << endl;
					}
				}
				else
				{
					// emit a warning
					Log.warn() << "MOL2File::write: could not write bond from " << bond_it->getFirstAtom()->getFullName()
										 << " to " << bond_it->getSecondAtom()->getFullName() << " - not in system!" << endl;
				}
			}
		}

		// write the substructure section
		// iterate over all substructures and write the substructure parts
		//
		for (Position i = 0; i < substructure_pointers.size(); i++)
		{
			f << TRIPOS << "SUBSTRUCTURE" << endl
				<< i + 1 << " "
				<< substructure_name[i] << " ";
			Position root_atom = atom_map[&*(substructure_pointers[i]->beginAtom())];
			f << root_atom;
			if (RTTI::isKindOf<Residue>(*substructure_pointers[i]))
			{
				f << " RESIDUE";
			}
			f << endl;
		}

		// done with writing.
	}

	void MOL2File::read(System& system)
	{
		// remove old rubbish from the system
		system.destroy();

		// reset the contents of the members
		clear_();

		// remember the line number for error messages
		number_of_lines_ = 0;

    while (nextLine_())
    {
			line_.toUpper();

			while (line_.hasPrefix(TRIPOS))
			{
				// we found a "Record Type Identifier" (RTI)
				String RTI = line_.after(TRIPOS);
				RTI.trim();

				#ifdef BALL_DEBUG
					// BAUSTELLE: debug code
					Log.info() << "MOL2File::read: reading record " << RTI << " in line " << number_of_lines_ << endl;
				#endif

				// interpret the RTI (at least the known ones)
				if (RTI == "ATOM")
				{
					readAtomSection_();
				}
				else if (RTI == "BOND")
				{
					readBondSection_();
				}
				else if (RTI == "MOLECULE")
				{
					readMoleculeSection_();
				}
				else if (RTI == "SET")
				{
					readSetSection_();
				}
				else if (RTI == "SUBSTRUCTURE")
				{
					 readSubstructureSection_();
				}
				else
				{
					// we found an unknown MOL2 section: print a warning message and ignore it!
					Log.warn() << "MOL2File::read: section ignored in line " << number_of_lines_ << ": " << RTI << endl;
					nextLine_();
				}

				line_.toUpper();
			}
		}

		// interpret the section we already read from the file
		buildSystem_();
	}

	void MOL2File::readAtomSection_()
	{
		Log.info() << "entering readAtomSection: line " << number_of_lines_ << endl;
		Size number_of_fields = 1;
		while (nextLine_() && (number_of_fields > 0) && !line_.hasPrefix(TRIPOS))
		{
			Size number_of_fields = line_.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 6)
				{
					Log.error() << "MOL2File::readAtomSection_: too few fields for an atom entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[10];
					line_.split(fields, 10);

					// create an atom and assign the fields of the line
					AtomStruct	atom;
					atom.name = fields[1];
					atom.position.x = fields[2].toFloat();
					atom.position.y = fields[3].toFloat();
					atom.position.z = fields[4].toFloat();
					atom.type = fields[5];
					atom.substructure = fields[6].toInt();
					atom.substructure_name = fields[7];
					atom.charge = fields[8].toFloat();

					// remember this atom
					atoms_.push_back(atom);
				}
			}
		}
	}

	void MOL2File::readBondSection_()
	{
		Log.info() << "entering readBondSection: line " << number_of_lines_ << endl;
		Size number_of_fields = 1;
		while (nextLine_() && (number_of_fields > 0) && !line_.hasPrefix(TRIPOS))
		{
			line_.trim();
			Size number_of_fields = line_.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 4)
				{
					Log.error() << "MOL2File::readBondSection_: too few fields for a bond entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[4];
					line_.split(fields, 4);

					// create an atom and assign the fields of the line
					BondStruct	bond;
					bond.atom1 = fields[1].toUnsignedInt();
					bond.atom1 = fields[2].toUnsignedInt();
					bond.type = fields[3];

					// remember this bond
					bonds_.push_back(bond);
				}
			}
		}
	}

	void MOL2File::readSetSection_()
	{
		Log.info() << "entering readSetSection: line " << number_of_lines_ << endl;
		Size number_of_fields = 1;
		while (nextLine_() && (number_of_fields > 0) && !line_.hasPrefix(TRIPOS))
		{
			line_.trim();
			Size number_of_fields = line_.countFields();
			if (number_of_fields > 0)
			{
				if (number_of_fields < 3)
				{
					Log.error() << "MOL2File::readSetSection_: too few fields for a bond entry in line "
											<< number_of_lines_ << endl;
				}
				else
				{
					// split the line into fields
					String	fields[6];
					line_.split(fields, 6);

					// create an atom and assign the fields of the line
					SetStruct	set;
					set.name = fields[1].toInt();
					set.type = fields[3].toInt();
					set.subtype = fields[4];
					set.comment = fields[6];
					if (fields[2] == "static")
					{
						nextLine_();
						line_.trim();
						Size number_of_fields = line_.countFields();

						for (Size i = 1; (i <= (Size)line_.getField(0).toInt()) && (i < number_of_fields); i++)
						{
							set.members.push_back(line_.getField(i).toInt());
						}

						// remember this set
						sets_.push_back(set);

					}
					else
					{
						// we cannot read dynamic sets. What is the syntax of these rules?
						Log.warn() << "MOL2File::readSetSection: unsupported set type: " << fields[2] << ". Ignored." << endl;
					}
				}
			}
		}
	}

	void MOL2File::readMoleculeSection_()
	{
		Log.info() << "entering readMoleculeSection: line " << number_of_lines_ << endl;
		Size number_of_fields = 1;
		Size line_number = 1;
		while (nextLine_() && (number_of_fields > 0) && !line_.hasPrefix(TRIPOS) && (line_number <= 5))
		{
			// read four lines
			line_number++;

			switch (line_number)
			{
				case 1:
					// read the first line: the molecule name (->BALL system name)
					molecule_.name = line_.trim();
					break;

				case 2:
					// read the number of atoms, bonds, and substructures
					molecule_.number_of_atoms = line_.getField(0);
					if (number_of_fields > 1)
					{
						molecule_.number_of_bonds = line_.getField(1).toUnsignedInt();
					}
					if (number_of_fields > 2)
					{
						molecule_.number_of_substtructures = line_.getField(2).toUnsignedInt();
					}
					if (number_of_fields > 3)
					{
						molecule_.number_of_featuress = line_.getField(3).toUnsignedInt();
					}
					if (number_of_fields > 4)
					{
						molecule_.number_of_sets = line_.getField(4).toUnsignedInt();
					}
					break;

				case 3:
				case 4:
				case 5:
					// ignore lines 3 - 5
			}
		}
	}

	void MOL2File::readSubstructureSection_()
	{
		Log.info() << "entering readSubstructureSection: line " << number_of_lines_ << endl;
		Size number_of_fields = 1;
		while (nextLine_() && (number_of_fields > 0) && !line_.hasPrefix(TRIPOS))
		{

		}
	}

	void MOL2File::clear_()
	{
		// clear the structure for the molecule section
		molecule_.name = "";
		molecule_.number_of_atoms = 0;
		molecule_.number_of_bonds = 0;
		molecule_.number_of_substructures = 0;
		molecule_.number_of_features = 0;
		molecule_.number_of_sets = 0;

		// clear the vectors for the other sections
		atoms_.clear();
		bonds_.clear();
		substructures_.clear();
		sets_.clear();
	}

	void MOL2File::buildAll_(System& system)
	{
		// name the system
		system.setName(molecule_.name);

		// consistency check
		if (atoms_.size() != molecule_.number_of_atoms)
		{
			Log.error() << "MOL2File::read: number of atoms in the MOLECULE section is not consistent the contents of the ATOM section!" << endl;
			return;
		}
		if (bonds_.size() != molecule_.number_of_bonds)
		{
			Log.error() << "MOL2File::read: number of bonds in the MOLECULE section is not consistent the contents of the BOND section!" << endl;
			return;
		}
		if (substructures_.size() != molecule_.number_of_substructures)
		{
			Log.error() << "MOL2File::read: number of substructures in the MOLECULE section is not consistent the contents of the SUBSTRUCTURE section!" << endl;
			return;
		}

		// construct the substructures

		// construct the atoms
		Position i;
		vector<Atom*> atom_ptr(atoms_.size());
		for (i = 0; i < atoms_.size(); i++)
		{
			Atom* atom = new Atom;
			atom.setName(atoms_[i].name);
			atom.setPosition(atoms_[i].position);
			atom.setTypeName(atoms_[i].type);
			atom.setCharge(atoms_[i].charge);
			atom_ptr.push_back(atom);
		}

		// construct the bonds
		for (i = 0; i < bonds_.size(); i++)
		{
			if ((bonds_[i].atom1 > atoms_.size()) || (bonds_[i].atom2 > atoms_.size()))
			{
				Log.error() << "MOL2File::read: cannot build bond between atoms "
					<< bonds_[i].atom1 << " and " << bonds_[i].atom2 << endl;
			}
			else
			{
				Bond* bond = atom_ptr[bonds_[i].atom1 - 1]->createBond(*atom_ptr[bonds_[i].atom2 - 1]);
				if (bonds_[i].type == "ar")
				{
					bond->setOrder(Bond::ORDER__AROMATIC);
				}
				else if (bonds_[i].type == "1")
				{
					bond->setOrder(Bond::ORDER__SINGLE);
				}
				else if (bonds_[i].type == "2")
				{
					bond->setOrder(Bond::ORDER__DOUBLE);
				}
				else if (bonds_[i].type == "1")
				{
					bond->setOrder(Bond::ORDER__TRIPLE);
				}
				else
				{
					Log.error() << "MOL2File::read: unkown bond type " << bonds_[i].type << endl;
				}
			}
		}
	}

	bool MOL2File::nextLine_()
	{
		if (getline(buffer_, MAX_LENGTH_))
		{
			line_.set(buffer_);
			number_of_lines_++;

			return true;
		}

		return false;
	}

	String MOL2File::getSybylType_(const Atom& atom) const
	{
		// the basename of Sybyl name is always the element
		// and a trailing dot
		String name = atom.getElement().getSymbol();

		// if there's more than one bond, add the number of
		// bonds and a dot as separator
		if (atom.countBonds() > 1)
		{
			name = name + ".";
			name = name + atom.countBonds();
		}

		return name;
	}

} // namespace BALL
<|endoftext|>