<commit_before>#include "master.hpp"

namespace factor
{

/* Certain special objects in the image are known to the runtime */
void factor_vm::init_objects(image_header *h)
{
	memcpy(special_objects,h->special_objects,sizeof(special_objects));

	true_object = h->true_object;
	bignum_zero = h->bignum_zero;
	bignum_pos_one = h->bignum_pos_one;
	bignum_neg_one = h->bignum_neg_one;
}

void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
{
	p->tenured_size = std::max((h->data_size * 3) / 2,p->tenured_size);

	init_data_heap(p->young_size,
		p->aging_size,
		p->tenured_size);

	fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);

	if((cell)bytes_read != h->data_size)
	{
		std::cout << "truncated image: " << bytes_read << " bytes read, ";
		std::cout << h->data_size << " bytes expected\n";
		fatal_error("load_data_heap failed",0);
	}

	data->tenured->initial_free_list(h->data_size);
}

void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
{
	if(h->code_size > p->code_size)
		fatal_error("Code heap too small to fit image",h->code_size);

	init_code_heap(p->code_size);

	if(h->code_size != 0)
	{
		size_t bytes_read = fread(code->allocator->first_block(),1,h->code_size,file);
		if(bytes_read != h->code_size)
		{
			std::cout << "truncated image: " << bytes_read << " bytes read, ";
			std::cout << h->code_size << " bytes expected\n";
			fatal_error("load_code_heap failed",0);
		}
	}

	code->allocator->initial_free_list(h->code_size);
}

struct data_fixupper {
	cell offset;

	explicit data_fixupper(cell offset_) : offset(offset_) {}

	object *operator()(object *obj)
	{
		return (object *)((char *)obj + offset);
	}
};

struct code_fixupper {
	cell offset;

	explicit code_fixupper(cell offset_) : offset(offset_) {}

	code_block *operator()(code_block *compiled)
	{
		return (code_block *)((char *)compiled + offset);
	}
};

static inline cell tuple_size_with_fixup(cell offset, object *obj)
{
	tuple_layout *layout = (tuple_layout *)((char *)UNTAG(((tuple *)obj)->layout) + offset);
	return tuple_size(layout);
}

struct fixup_sizer {
	cell offset;

	explicit fixup_sizer(cell offset_) : offset(offset_) {}

	cell operator()(object *obj)
	{
		if(obj->type() == TUPLE_TYPE)
			return align(tuple_size_with_fixup(offset,obj),data_alignment);
		else
			return obj->size();
	}
};

struct object_fixupper {
	factor_vm *parent;
	cell data_offset;
	slot_visitor<data_fixupper> data_visitor;
	code_block_visitor<code_fixupper> code_visitor;

	object_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		data_offset(data_offset_),
		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
		code_visitor(code_block_visitor<code_fixupper>(parent_,code_fixupper(code_offset_))) {}

	void operator()(object *obj, cell size)
	{
		parent->data->tenured->starts.record_object_start_offset(obj);

		switch(obj->type())
		{
		case ALIEN_TYPE:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);

				alien *ptr = (alien *)obj;

				if(!parent->to_boolean(ptr->base))
					ptr->expired = parent->true_object;
				else
					ptr->update_address();
				break;
			}
		case DLL_TYPE:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);

				parent->ffi_dlopen((dll *)obj);
				break;
			}
		case TUPLE_TYPE:
			{
				cell payload_start = tuple_size_with_fixup(data_offset,obj);
				data_visitor.visit_slots(obj,payload_start);
				break;
			}
		default:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);
				code_visitor.visit_object_code_block(obj);
				break;
			}
		}
	}
};

void factor_vm::fixup_data(cell data_offset, cell code_offset)
{
	slot_visitor<data_fixupper> data_workhorse(this,data_fixupper(data_offset));
	data_workhorse.visit_roots();

	object_fixupper fixupper(this,data_offset,code_offset);
	fixup_sizer sizer(data_offset);
	data->tenured->iterate(fixupper,sizer);
}

struct code_block_updater {
	factor_vm *parent;
	cell code_offset;
	slot_visitor<data_fixupper> data_visitor;
	code_fixupper code_visitor;

	code_block_updater(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		code_offset(code_offset_),
		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
		code_visitor(code_fixupper(code_offset_)) {}

	void operator()(relocation_entry rel, cell index, code_block *compiled)
	{
		relocation_type type = rel.rel_type();
		instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());

		array *literals = (parent->to_boolean(compiled->literals)
			? untag<array>(compiled->literals) : NULL);

		cell old_offset = (cell)compiled - code_offset;

		switch(type)
		{
		case RT_IMMEDIATE:
			op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
			break;
		case RT_XT:
		case RT_XT_PIC:
		case RT_XT_PIC_TAIL:
			op.store_code_block(code_visitor(op.load_code_block(old_offset)));
			break;
		case RT_PRIMITIVE:
			op.store_value(parent->compute_primitive_relocation(array_nth(literals,index)));
			break;
		case RT_DLSYM:
			op.store_value(parent->compute_dlsym_relocation(literals,index));
			break;
		case RT_HERE:
			op.store_value(parent->compute_here_relocation(array_nth(literals,index),rel.rel_offset(),compiled));
			break;
		case RT_THIS:
			op.store_value((cell)compiled->xt());
			break;
		case RT_CONTEXT:
			op.store_value(parent->compute_context_relocation());
			break;
		case RT_UNTAGGED:
			op.store_value(untag_fixnum(array_nth(literals,index)));
		case RT_MEGAMORPHIC_CACHE_HITS:
			op.store_value((cell)&parent->dispatch_stats.megamorphic_cache_hits);
			break;
		case RT_VM:
			op.store_value(parent->compute_vm_relocation(array_nth(literals,index)));
			break;
		case RT_CARDS_OFFSET:
			op.store_value(parent->cards_offset);
			break;
		case RT_DECKS_OFFSET:
			op.store_value(parent->decks_offset);
			break;
		default:
			critical_error("Bad rel type",rel.rel_type());
			break;
		}
	}
};

struct code_block_fixupper {
	factor_vm *parent;
	cell data_offset;
	cell code_offset;

	code_block_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		data_offset(data_offset_),
		code_offset(code_offset_) {}

	void operator()(code_block *compiled, cell size)
	{
		slot_visitor<data_fixupper> data_visitor(parent,data_fixupper(data_offset));
		data_visitor.visit_code_block_objects(compiled);

		code_block_updater updater(parent,data_offset,code_offset);
		parent->iterate_relocations(compiled,updater);
	}
};

void factor_vm::fixup_code(cell data_offset, cell code_offset)
{
	code_block_fixupper fixupper(this,data_offset,code_offset);
	code->allocator->iterate(fixupper);
}

/* Read an image file from disk, only done once during startup */
/* This function also initializes the data and code heaps */
void factor_vm::load_image(vm_parameters *p)
{
	FILE *file = OPEN_READ(p->image_path);
	if(file == NULL)
	{
		std::cout << "Cannot open image file: " << p->image_path << std::endl;
		std::cout << strerror(errno) << std::endl;
		exit(1);
	}

	image_header h;
	if(fread(&h,sizeof(image_header),1,file) != 1)
		fatal_error("Cannot read image header",0);

	if(h.magic != image_magic)
		fatal_error("Bad image: magic number check failed",h.magic);

	if(h.version != image_version)
		fatal_error("Bad image: version number check failed",h.version);

	load_data_heap(file,&h,p);
	load_code_heap(file,&h,p);

	fclose(file);

	init_objects(&h);

	cell data_offset = data->tenured->start - h.data_relocation_base;
	cell code_offset = code->seg->start - h.code_relocation_base;

	fixup_data(data_offset,code_offset);
	fixup_code(data_offset,code_offset);

	/* Store image path name */
	special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path);
}

/* Save the current image to disk */
bool factor_vm::save_image(const vm_char *filename)
{
	FILE* file;
	image_header h;

	file = OPEN_WRITE(filename);
	if(file == NULL)
	{
		std::cout << "Cannot open image file: " << filename << std::endl;
		std::cout << strerror(errno) << std::endl;
		return false;
	}

	h.magic = image_magic;
	h.version = image_version;
	h.data_relocation_base = data->tenured->start;
	h.data_size = data->tenured->occupied_space();
	h.code_relocation_base = code->seg->start;
	h.code_size = code->allocator->occupied_space();

	h.true_object = true_object;
	h.bignum_zero = bignum_zero;
	h.bignum_pos_one = bignum_pos_one;
	h.bignum_neg_one = bignum_neg_one;

	for(cell i = 0; i < special_object_count; i++)
		h.special_objects[i] = (save_special_p(i) ? special_objects[i] : false_object);

	bool ok = true;

	if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
	if(fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
	if(fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false;
	if(fclose(file)) ok = false;

	if(!ok)
		std::cout << "save-image failed: " << strerror(errno) << std::endl;

	return ok;
}

void factor_vm::primitive_save_image()
{
	/* do a full GC to push everything into tenured space */
	primitive_compact_gc();

	data_root<byte_array> path(dpop(),this);
	path.untag_check(this);
	save_image((vm_char *)(path.untagged() + 1));
}

void factor_vm::primitive_save_image_and_exit()
{
	/* We unbox this before doing anything else. This is the only point
	where we might throw an error, so we have to throw an error here since
	later steps destroy the current image. */
	data_root<byte_array> path(dpop(),this);
	path.untag_check(this);

	/* strip out special_objects data which is set on startup anyway */
	for(cell i = 0; i < special_object_count; i++)
		if(!save_special_p(i)) special_objects[i] = false_object;

	gc(collect_compact_op,
		0, /* requested size */
		false /* discard objects only reachable from stacks */);

	/* Save the image */
	if(save_image((vm_char *)(path.untagged() + 1)))
		exit(0);
	else
		exit(1);
}

}
<commit_msg>vm: fix some typos<commit_after>#include "master.hpp"

namespace factor
{

/* Certain special objects in the image are known to the runtime */
void factor_vm::init_objects(image_header *h)
{
	memcpy(special_objects,h->special_objects,sizeof(special_objects));

	true_object = h->true_object;
	bignum_zero = h->bignum_zero;
	bignum_pos_one = h->bignum_pos_one;
	bignum_neg_one = h->bignum_neg_one;
}

void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
{
	p->tenured_size = std::max((h->data_size * 3) / 2,p->tenured_size);

	init_data_heap(p->young_size,
		p->aging_size,
		p->tenured_size);

	fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);

	if((cell)bytes_read != h->data_size)
	{
		std::cout << "truncated image: " << bytes_read << " bytes read, ";
		std::cout << h->data_size << " bytes expected\n";
		fatal_error("load_data_heap failed",0);
	}

	data->tenured->initial_free_list(h->data_size);
}

void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
{
	if(h->code_size > p->code_size)
		fatal_error("Code heap too small to fit image",h->code_size);

	init_code_heap(p->code_size);

	if(h->code_size != 0)
	{
		size_t bytes_read = fread(code->allocator->first_block(),1,h->code_size,file);
		if(bytes_read != h->code_size)
		{
			std::cout << "truncated image: " << bytes_read << " bytes read, ";
			std::cout << h->code_size << " bytes expected\n";
			fatal_error("load_code_heap failed",0);
		}
	}

	code->allocator->initial_free_list(h->code_size);
}

struct data_fixupper {
	cell offset;

	explicit data_fixupper(cell offset_) : offset(offset_) {}

	object *operator()(object *obj)
	{
		return (object *)((char *)obj + offset);
	}
};

struct code_fixupper {
	cell offset;

	explicit code_fixupper(cell offset_) : offset(offset_) {}

	code_block *operator()(code_block *compiled)
	{
		return (code_block *)((char *)compiled + offset);
	}
};

static inline cell tuple_size_with_fixup(cell offset, object *obj)
{
	tuple_layout *layout = (tuple_layout *)((char *)UNTAG(((tuple *)obj)->layout) + offset);
	return tuple_size(layout);
}

struct fixup_sizer {
	cell offset;

	explicit fixup_sizer(cell offset_) : offset(offset_) {}

	cell operator()(object *obj)
	{
		if(obj->type() == TUPLE_TYPE)
			return align(tuple_size_with_fixup(offset,obj),data_alignment);
		else
			return obj->size();
	}
};

struct object_fixupper {
	factor_vm *parent;
	cell data_offset;
	slot_visitor<data_fixupper> data_visitor;
	code_block_visitor<code_fixupper> code_visitor;

	object_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		data_offset(data_offset_),
		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
		code_visitor(code_block_visitor<code_fixupper>(parent_,code_fixupper(code_offset_))) {}

	void operator()(object *obj, cell size)
	{
		parent->data->tenured->starts.record_object_start_offset(obj);

		switch(obj->type())
		{
		case ALIEN_TYPE:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);

				alien *ptr = (alien *)obj;

				if(!parent->to_boolean(ptr->base))
					ptr->expired = parent->true_object;
				else
					ptr->update_address();
				break;
			}
		case DLL_TYPE:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);

				parent->ffi_dlopen((dll *)obj);
				break;
			}
		case TUPLE_TYPE:
			{
				cell payload_start = tuple_size_with_fixup(data_offset,obj);
				data_visitor.visit_slots(obj,payload_start);
				break;
			}
		default:
			{
				cell payload_start = obj->binary_payload_start();
				data_visitor.visit_slots(obj,payload_start);
				code_visitor.visit_object_code_block(obj);
				break;
			}
		}
	}
};

void factor_vm::fixup_data(cell data_offset, cell code_offset)
{
	slot_visitor<data_fixupper> data_workhorse(this,data_fixupper(data_offset));
	data_workhorse.visit_roots();

	object_fixupper fixupper(this,data_offset,code_offset);
	fixup_sizer sizer(data_offset);
	data->tenured->iterate(fixupper,sizer);
}

struct code_block_updater {
	factor_vm *parent;
	cell code_offset;
	slot_visitor<data_fixupper> data_visitor;
	code_fixupper code_visitor;

	code_block_updater(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		code_offset(code_offset_),
		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
		code_visitor(code_fixupper(code_offset_)) {}

	void operator()(relocation_entry rel, cell index, code_block *compiled)
	{
		relocation_type type = rel.rel_type();
		instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());

		array *literals = (parent->to_boolean(compiled->literals)
			? untag<array>(compiled->literals) : NULL);

		cell old_offset = (cell)rel.rel_offset() + (cell)compiled->xt() - code_offset;

		switch(type)
		{
		case RT_IMMEDIATE:
			op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
			break;
		case RT_XT:
		case RT_XT_PIC:
		case RT_XT_PIC_TAIL:
			op.store_code_block(code_visitor(op.load_code_block(old_offset)));
			break;
		case RT_PRIMITIVE:
			op.store_value(parent->compute_primitive_relocation(array_nth(literals,index)));
			break;
		case RT_DLSYM:
			op.store_value(parent->compute_dlsym_relocation(literals,index));
			break;
		case RT_HERE:
			op.store_value(parent->compute_here_relocation(array_nth(literals,index),rel.rel_offset(),compiled));
			break;
		case RT_THIS:
			op.store_value((cell)compiled->xt());
			break;
		case RT_CONTEXT:
			op.store_value(parent->compute_context_relocation());
			break;
		case RT_UNTAGGED:
			op.store_value(untag_fixnum(array_nth(literals,index)));
			break;
		case RT_MEGAMORPHIC_CACHE_HITS:
			op.store_value((cell)&parent->dispatch_stats.megamorphic_cache_hits);
			break;
		case RT_VM:
			op.store_value(parent->compute_vm_relocation(array_nth(literals,index)));
			break;
		case RT_CARDS_OFFSET:
			op.store_value(parent->cards_offset);
			break;
		case RT_DECKS_OFFSET:
			op.store_value(parent->decks_offset);
			break;
		default:
			critical_error("Bad rel type",rel.rel_type());
			break;
		}
	}
};

struct code_block_fixupper {
	factor_vm *parent;
	cell data_offset;
	cell code_offset;

	code_block_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
		parent(parent_),
		data_offset(data_offset_),
		code_offset(code_offset_) {}

	void operator()(code_block *compiled, cell size)
	{
		slot_visitor<data_fixupper> data_visitor(parent,data_fixupper(data_offset));
		data_visitor.visit_code_block_objects(compiled);

		code_block_updater updater(parent,data_offset,code_offset);
		parent->iterate_relocations(compiled,updater);
	}
};

void factor_vm::fixup_code(cell data_offset, cell code_offset)
{
	code_block_fixupper fixupper(this,data_offset,code_offset);
	code->allocator->iterate(fixupper);
}

/* Read an image file from disk, only done once during startup */
/* This function also initializes the data and code heaps */
void factor_vm::load_image(vm_parameters *p)
{
	FILE *file = OPEN_READ(p->image_path);
	if(file == NULL)
	{
		std::cout << "Cannot open image file: " << p->image_path << std::endl;
		std::cout << strerror(errno) << std::endl;
		exit(1);
	}

	image_header h;
	if(fread(&h,sizeof(image_header),1,file) != 1)
		fatal_error("Cannot read image header",0);

	if(h.magic != image_magic)
		fatal_error("Bad image: magic number check failed",h.magic);

	if(h.version != image_version)
		fatal_error("Bad image: version number check failed",h.version);

	load_data_heap(file,&h,p);
	load_code_heap(file,&h,p);

	fclose(file);

	init_objects(&h);

	cell data_offset = data->tenured->start - h.data_relocation_base;
	cell code_offset = code->seg->start - h.code_relocation_base;

	fixup_data(data_offset,code_offset);
	fixup_code(data_offset,code_offset);

	/* Store image path name */
	special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path);
}

/* Save the current image to disk */
bool factor_vm::save_image(const vm_char *filename)
{
	FILE* file;
	image_header h;

	file = OPEN_WRITE(filename);
	if(file == NULL)
	{
		std::cout << "Cannot open image file: " << filename << std::endl;
		std::cout << strerror(errno) << std::endl;
		return false;
	}

	h.magic = image_magic;
	h.version = image_version;
	h.data_relocation_base = data->tenured->start;
	h.data_size = data->tenured->occupied_space();
	h.code_relocation_base = code->seg->start;
	h.code_size = code->allocator->occupied_space();

	h.true_object = true_object;
	h.bignum_zero = bignum_zero;
	h.bignum_pos_one = bignum_pos_one;
	h.bignum_neg_one = bignum_neg_one;

	for(cell i = 0; i < special_object_count; i++)
		h.special_objects[i] = (save_special_p(i) ? special_objects[i] : false_object);

	bool ok = true;

	if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
	if(fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
	if(fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false;
	if(fclose(file)) ok = false;

	if(!ok)
		std::cout << "save-image failed: " << strerror(errno) << std::endl;

	return ok;
}

void factor_vm::primitive_save_image()
{
	/* do a full GC to push everything into tenured space */
	primitive_compact_gc();

	data_root<byte_array> path(dpop(),this);
	path.untag_check(this);
	save_image((vm_char *)(path.untagged() + 1));
}

void factor_vm::primitive_save_image_and_exit()
{
	/* We unbox this before doing anything else. This is the only point
	where we might throw an error, so we have to throw an error here since
	later steps destroy the current image. */
	data_root<byte_array> path(dpop(),this);
	path.untag_check(this);

	/* strip out special_objects data which is set on startup anyway */
	for(cell i = 0; i < special_object_count; i++)
		if(!save_special_p(i)) special_objects[i] = false_object;

	gc(collect_compact_op,
		0, /* requested size */
		false /* discard objects only reachable from stacks */);

	/* Save the image */
	if(save_image((vm_char *)(path.untagged() + 1)))
		exit(0);
	else
		exit(1);
}

}
<|endoftext|>


<commit_before>#include "string.hh"

#include "exception.hh"
#include "containers.hh"
#include "utf8_iterator.hh"

#include <cstdio>

namespace Kakoune
{

Vector<String> split(StringView str, char separator, char escape)
{
    Vector<String> res;
    auto it = str.begin();
    while (it != str.end())
    {
        res.emplace_back();
        String& element = res.back();
        while (it != str.end())
        {
            auto c = *it;
            if (c == escape and it + 1 != str.end() and *(it+1) == separator)
            {
                element += separator;
                it += 2;
            }
            else if (c == separator)
            {
                ++it;
                break;
            }
            else
            {
                element += c;
                ++it;
            }
        }
    }
    return res;
}

Vector<StringView> split(StringView str, char separator)
{
    Vector<StringView> res;
    auto beg = str.begin();
    for (auto it = beg; it != str.end(); ++it)
    {
        if (*it == separator)
        {
            res.emplace_back(beg, it);
            beg = it + 1;
        }
    }
    res.emplace_back(beg, str.end());
    return res;
}

String escape(StringView str, StringView characters, char escape)
{
    String res;
    res.reserve(str.length());
    for (auto& c : str)
    {
        if (contains(characters, c))
            res += escape;
        res += c;
    }
    return res;
}

String unescape(StringView str, StringView characters, char escape)
{
    String res;
    res.reserve(str.length());
    for (auto& c : str)
    {
        if (contains(characters, c) and not res.empty() and res.back() == escape)
            res.back() = c;
        else
            res += c;
    }
    return res;
}

String indent(StringView str, StringView indent)
{
    String res;
    res.reserve(str.length());
    bool was_eol = true;
    for (ByteCount i = 0; i < str.length(); ++i)
    {
        if (was_eol)
            res += indent;
        res += str[i];
        was_eol = is_eol(str[i]);
    }
    return res;
}

int str_to_int(StringView str)
{
    unsigned int res = 0;
    bool negative = false;
    for (auto it = str.begin(), end = str.end(); it != end; ++it)
    {
        const char c = *it;
        if (it == str.begin() and c == '-')
            negative = true;
        else if (c >= '0' and c <= '9')
            res = res * 10 + c - '0';
        else
            throw runtime_error(str + "is not a number");
    }
    return negative ? -(int)res : (int)res;
}

InplaceString<16> to_string(int val)
{
    InplaceString<16> res;
    res.m_length = sprintf(res.m_data, "%i", val);
    return res;
}

InplaceString<24> to_string(size_t val)
{
    InplaceString<24> res;
    res.m_length = sprintf(res.m_data, "%zu", val);
    return res;
}

InplaceString<24> to_string(float val)
{
    InplaceString<24> res;
    res.m_length = sprintf(res.m_data, "%f", val);
    return res;
}

bool subsequence_match(StringView str, StringView subseq)
{
    auto it = str.begin();
    for (auto& c : subseq)
    {
        if (it == str.end())
            return false;
        while (*it != c)
        {
            if (++it == str.end())
                return false;
        }
        ++it;
    }
    return true;
}

String expand_tabs(StringView line, CharCount tabstop, CharCount col)
{
    String res;
    res.reserve(line.length());
    for (auto it = line.begin(), end = line.end(); it != end; )
    {
        if (*it == '\t')
        {
            CharCount end_col = (col / tabstop + 1) * tabstop;
            res += String{' ', end_col - col};
            col = end_col;
            ++it;
        }
        else
        {
            auto char_end = utf8::next(it, end);
            res += {it, char_end};
            ++col;
            it = char_end;
        }
    }
    return res;
}

Vector<StringView> wrap_lines(StringView text, CharCount max_width)
{
    using Utf8It = utf8::iterator<const char*>;
    Utf8It word_begin{text.begin()};
    Utf8It word_end{word_begin};
    Utf8It end{text.end()};
    CharCount col = 0;
    Vector<StringView> lines;
    Utf8It line_begin = text.begin();
    Utf8It line_end = line_begin;
    while (word_begin != end)
    {
        const CharCategories cat = categorize(*word_begin);
        do
        {
            ++word_end;
        } while (word_end != end and categorize(*word_end) == cat);

        col += word_end - word_begin;
        if ((word_begin != line_begin and col > max_width) or
            cat == CharCategories::EndOfLine)
        {
            lines.emplace_back(line_begin.base(), line_end.base());
            line_begin = (cat == CharCategories::EndOfLine or
                          cat == CharCategories::Blank) ? word_end : word_begin;
            col = word_end - line_begin;
        }
        if (cat == CharCategories::Word or cat == CharCategories::Punctuation)
            line_end = word_end;

        word_begin = word_end;
    }
    if (line_begin != word_begin)
        lines.emplace_back(line_begin.base(), word_begin.base());
    return lines;
}

String format(StringView fmt, ArrayView<const StringView> params)
{
    ByteCount size = fmt.length();
    for (auto& s : params) size += s.length();
    String res;
    res.reserve(size);

    int implicitIndex = 0;
    for (auto it = fmt.begin(), end = fmt.end(); it != end;)
    {
        auto opening = std::find(it, end, '{');
        res += StringView{it, opening};
        if (opening == end)
            break;

        if (opening != it && res.back() == '\\')
        {
            res.back() = '{';
            it = opening + 1;
        }
        else
        {
            auto closing = std::find(it, end, '}');
            if (closing == end)
                throw runtime_error("Format string error, unclosed '{'");
            int index;
            if (closing == opening + 1)
                index = implicitIndex;
            else
                index = str_to_int({opening+1, closing});

            if (index >= params.size())
                throw runtime_error("Format string parameter index too big");

            res += params[index];
            implicitIndex = index+1;
            it = closing+1;
        }
    }
    return res;
}

}
<commit_msg>small code tweak in format<commit_after>#include "string.hh"

#include "exception.hh"
#include "containers.hh"
#include "utf8_iterator.hh"

#include <cstdio>

namespace Kakoune
{

Vector<String> split(StringView str, char separator, char escape)
{
    Vector<String> res;
    auto it = str.begin();
    while (it != str.end())
    {
        res.emplace_back();
        String& element = res.back();
        while (it != str.end())
        {
            auto c = *it;
            if (c == escape and it + 1 != str.end() and *(it+1) == separator)
            {
                element += separator;
                it += 2;
            }
            else if (c == separator)
            {
                ++it;
                break;
            }
            else
            {
                element += c;
                ++it;
            }
        }
    }
    return res;
}

Vector<StringView> split(StringView str, char separator)
{
    Vector<StringView> res;
    auto beg = str.begin();
    for (auto it = beg; it != str.end(); ++it)
    {
        if (*it == separator)
        {
            res.emplace_back(beg, it);
            beg = it + 1;
        }
    }
    res.emplace_back(beg, str.end());
    return res;
}

String escape(StringView str, StringView characters, char escape)
{
    String res;
    res.reserve(str.length());
    for (auto& c : str)
    {
        if (contains(characters, c))
            res += escape;
        res += c;
    }
    return res;
}

String unescape(StringView str, StringView characters, char escape)
{
    String res;
    res.reserve(str.length());
    for (auto& c : str)
    {
        if (contains(characters, c) and not res.empty() and res.back() == escape)
            res.back() = c;
        else
            res += c;
    }
    return res;
}

String indent(StringView str, StringView indent)
{
    String res;
    res.reserve(str.length());
    bool was_eol = true;
    for (ByteCount i = 0; i < str.length(); ++i)
    {
        if (was_eol)
            res += indent;
        res += str[i];
        was_eol = is_eol(str[i]);
    }
    return res;
}

int str_to_int(StringView str)
{
    unsigned int res = 0;
    bool negative = false;
    for (auto it = str.begin(), end = str.end(); it != end; ++it)
    {
        const char c = *it;
        if (it == str.begin() and c == '-')
            negative = true;
        else if (c >= '0' and c <= '9')
            res = res * 10 + c - '0';
        else
            throw runtime_error(str + "is not a number");
    }
    return negative ? -(int)res : (int)res;
}

InplaceString<16> to_string(int val)
{
    InplaceString<16> res;
    res.m_length = sprintf(res.m_data, "%i", val);
    return res;
}

InplaceString<24> to_string(size_t val)
{
    InplaceString<24> res;
    res.m_length = sprintf(res.m_data, "%zu", val);
    return res;
}

InplaceString<24> to_string(float val)
{
    InplaceString<24> res;
    res.m_length = sprintf(res.m_data, "%f", val);
    return res;
}

bool subsequence_match(StringView str, StringView subseq)
{
    auto it = str.begin();
    for (auto& c : subseq)
    {
        if (it == str.end())
            return false;
        while (*it != c)
        {
            if (++it == str.end())
                return false;
        }
        ++it;
    }
    return true;
}

String expand_tabs(StringView line, CharCount tabstop, CharCount col)
{
    String res;
    res.reserve(line.length());
    for (auto it = line.begin(), end = line.end(); it != end; )
    {
        if (*it == '\t')
        {
            CharCount end_col = (col / tabstop + 1) * tabstop;
            res += String{' ', end_col - col};
            col = end_col;
            ++it;
        }
        else
        {
            auto char_end = utf8::next(it, end);
            res += {it, char_end};
            ++col;
            it = char_end;
        }
    }
    return res;
}

Vector<StringView> wrap_lines(StringView text, CharCount max_width)
{
    using Utf8It = utf8::iterator<const char*>;
    Utf8It word_begin{text.begin()};
    Utf8It word_end{word_begin};
    Utf8It end{text.end()};
    CharCount col = 0;
    Vector<StringView> lines;
    Utf8It line_begin = text.begin();
    Utf8It line_end = line_begin;
    while (word_begin != end)
    {
        const CharCategories cat = categorize(*word_begin);
        do
        {
            ++word_end;
        } while (word_end != end and categorize(*word_end) == cat);

        col += word_end - word_begin;
        if ((word_begin != line_begin and col > max_width) or
            cat == CharCategories::EndOfLine)
        {
            lines.emplace_back(line_begin.base(), line_end.base());
            line_begin = (cat == CharCategories::EndOfLine or
                          cat == CharCategories::Blank) ? word_end : word_begin;
            col = word_end - line_begin;
        }
        if (cat == CharCategories::Word or cat == CharCategories::Punctuation)
            line_end = word_end;

        word_begin = word_end;
    }
    if (line_begin != word_begin)
        lines.emplace_back(line_begin.base(), word_begin.base());
    return lines;
}

String format(StringView fmt, ArrayView<const StringView> params)
{
    ByteCount size = fmt.length();
    for (auto& s : params) size += s.length();
    String res;
    res.reserve(size);

    int implicitIndex = 0;
    for (auto it = fmt.begin(), end = fmt.end(); it != end;)
    {
        auto opening = std::find(it, end, '{');
        res += StringView{it, opening};
        if (opening == end)
            break;

        if (opening != it && *(opening-1) == '\\')
        {
            res.back() = '{';
            it = opening + 1;
        }
        else
        {
            auto closing = std::find(it, end, '}');
            if (closing == end)
                throw runtime_error("Format string error, unclosed '{'");
            int index;
            if (closing == opening + 1)
                index = implicitIndex;
            else
                index = str_to_int({opening+1, closing});

            if (index >= params.size())
                throw runtime_error("Format string parameter index too big");

            res += params[index];
            implicitIndex = index+1;
            it = closing+1;
        }
    }
    return res;
}

}
<|endoftext|>


<commit_before>/**
 *\file
 *\author Stefan de Beer, Arco Gelderblom
 *\copyright Copyright (c) 2017, The R2D2 Team
 *\license See LICENSE
 */

#include "mfrc522.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

void Mfrc522::writeRegister(const mfrc522Registers reg, const uint8_t value){
    uint8_t address = static_cast<uint8_t>(reg);
    address <<= 1;
    uint8_t data[2] = {address, value}; // clearing address byte for writing
    wiringPiSPIDataRW (0, data, 2);
}

void Mfrc522::writeRegister(const mfrc522Registers reg, const uint8_t * value, const unsigned int len){
    for(uint8_t i = 0;i<len; i++){
      writeRegister(reg, value[i]);
    }
}

unsigned char Mfrc522::readRegister(const mfrc522Registers reg){
    uint8_t data[2];
    data[0] = 0x80 | (static_cast<uint8_t>(reg)<<1); //Setting address byte for reading
    wiringPiSPIDataRW(0, data, 2);
    return data[1];
}

void Mfrc522::setRegisterBitMask(const mfrc522Registers reg, const uint8_t mask){
    uint8_t buffer = readRegister(reg);
    writeRegister(reg, buffer|mask);
}

void Mfrc522::clearRegisterBitMask(const mfrc522Registers reg, const uint8_t mask){
    uint8_t buffer = readRegister(reg);
    buffer &= (~mask);
    writeRegister(reg, buffer);
}

void Mfrc522::softReset(){
  writeRegister(mfrc522Registers::command, static_cast<uint8_t>(mfrc522Commands::softReset)); //Send softReset command.
    delay(50); //wait while resetting.
    while(readRegister(mfrc522Registers::command)&(1<<4)); //wait for bit 4(powerDown bit) to clear if not reset yet.
}

void Mfrc522::init(){
    pinMode(6, OUTPUT); // The reset pin
    if(!digitalRead(6)){
        digitalWrite(6, HIGH);
        delay(50); //wait for mfrc522 to reset
    }else{
        softReset();
    }

    writeRegister(mfrc522Registers::tMode, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
    writeRegister(mfrc522Registers::tPrescaler, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25�s.
    writeRegister(mfrc522Registers::tReloadH, 0x03);		// Reload timer with 0x3E8 = 1000, 25ms before timeout.
    writeRegister(mfrc522Registers::tReloadL, 0xE8);

    writeRegister(mfrc522Registers::txAsk, 0x40);		// Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
    writeRegister(mfrc522Registers::mode, 0x3D);		// Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363
    antennaOn(); 						// enable antenna
    setAntennaGain(0x70);				// set the antenna gain
}

void Mfrc522::antennaOn(){
    uint8_t value = readRegister(mfrc522Registers::txControl);
    writeRegister(mfrc522Registers::txControl, value |= 0x03); // set lower 2 bits
}

void Mfrc522::antennaOff(){
    uint8_t value = readRegister(mfrc522Registers::txControl);
    writeRegister(mfrc522Registers::txControl, value&0xFC); // clear lower 2 bits
}

void Mfrc522::setAntennaGain(uint8_t value){
    if(getAntennaGain() != value){
        clearRegisterBitMask(mfrc522Registers::rfcFg, (0x07<<4));
        setRegisterBitMask(mfrc522Registers::rfcFg, value & (0x07<<4));
    }
}

uint8_t Mfrc522::getAntennaGain(){
    return readRegister(mfrc522Registers::rfcFg) & (0x07 << 4);
}

Mfrc522::statusCodes Mfrc522::communicateWithTag(const mfrc522Commands command,
                                                 const uint8_t * sendData,
                                                 const uint8_t sendDataLen,
                                                 uint8_t * receiveData,
                                                 const uint8_t receiveDataLen){

    writeRegister(mfrc522Registers::command, static_cast<uint8_t>(mfrc522Commands::idle));		// Stop any active command.
    writeRegister(mfrc522Registers::comIrq, 0x7F);			// Clear all seven interrupt request bits
    setRegisterBitMask(mfrc522Registers::FIFOLevel, 0x80);     // flush the buffer
    writeRegister(mfrc522Registers::FIFOData, sendData, sendDataLen);	// Write sendData to the FIFO
    writeRegister(mfrc522Registers::command, static_cast<uint8_t>(command)); //execute command

    if(command == mfrc522Commands::transceive){
        setRegisterBitMask(mfrc522Registers::bitFraming, 0x80); //start send
    }
    int i = 50; //max ~50 milliseconds timeout
    while(true){
        uint8_t n = readRegister(mfrc522Registers::comIrq);
        if(n & 0x30){
            break; // Tag found
        }
        else if(n & 0x01){
            return statusCodes::statusTimeout; // no Tag found
        }
        if(--i == 0){
            return statusCodes::statusError; // something went wrong. Is the mfrc522 connected properly?
        }
        delay(1);
    }
    if(receiveData){ // if receiveData is not nullptr
      uint8_t recievedLen = readRegister(mfrc522Registers::FIFOLevel);
        if(receiveDataLen >= recievedLen){ // does the data fit in the given container?
            for(uint8_t i = 0;i < recievedLen;i++){
                receiveData[i] = readRegister(mfrc522Registers::FIFOData); // copy data
            }
        }
    }
    return statusCodes::statusOk;
}

bool Mfrc522::isTagPresent(){
    writeRegister(mfrc522Registers::bitFraming, 0x07);

    uint8_t data = static_cast<uint8_t>(mifareCommands::reqIdle); // first element is the command to send to the tag. Here we request every tag that is in idle

    statusCodes status = communicateWithTag(mfrc522Commands::transceive, &data, 1, nullptr, 0); // nullptr beacause we do not need ro read data from the tag.

    return status == statusCodes::statusOk;
}

Mfrc522::statusCodes Mfrc522::receiveTagId(uint8_t * inputForId){
    writeRegister(mfrc522Registers::bitFraming, 0x07);

    uint8_t data = static_cast<uint8_t>(mifareCommands::antiColl);

    statusCodes status = communicateWithTag(mfrc522Commands::transceive, &data, 1, inputForId, 16);

    return status;
}<commit_msg>[RFID-02] Edited statuscode output, because it was incorrect<commit_after>/**
 *\file
 *\author Stefan de Beer, Arco Gelderblom
 *\copyright Copyright (c) 2017, The R2D2 Team
 *\license See LICENSE
 */

#include "mfrc522.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

void Mfrc522::writeRegister(const mfrc522Registers reg, const uint8_t value){
    uint8_t address = static_cast<uint8_t>(reg);
    address <<= 1;
    uint8_t data[2] = {address, value}; // clearing address byte for writing
    wiringPiSPIDataRW (0, data, 2);
}

void Mfrc522::writeRegister(const mfrc522Registers reg, const uint8_t * value, const unsigned int len){
    for(uint8_t i = 0;i<len; i++){
      writeRegister(reg, value[i]);
    }
}

unsigned char Mfrc522::readRegister(const mfrc522Registers reg){
    uint8_t data[2];
    data[0] = 0x80 | (static_cast<uint8_t>(reg)<<1); //Setting address byte for reading
    wiringPiSPIDataRW(0, data, 2);
    return data[1];
}

void Mfrc522::setRegisterBitMask(const mfrc522Registers reg, const uint8_t mask){
    uint8_t buffer = readRegister(reg);
    writeRegister(reg, buffer|mask);
}

void Mfrc522::clearRegisterBitMask(const mfrc522Registers reg, const uint8_t mask){
    uint8_t buffer = readRegister(reg);
    buffer &= (~mask);
    writeRegister(reg, buffer);
}

void Mfrc522::softReset(){
  writeRegister(mfrc522Registers::command, static_cast<uint8_t>(mfrc522Commands::softReset)); //Send softReset command.
    delay(50); //wait while resetting.
    while(readRegister(mfrc522Registers::command)&(1<<4)); //wait for bit 4(powerDown bit) to clear if not reset yet.
}

void Mfrc522::init(){
    pinMode(6, OUTPUT); // The reset pin
    if(!digitalRead(6)){
        digitalWrite(6, HIGH);
        delay(50); //wait for mfrc522 to reset
    }else{
        softReset();
    }

    writeRegister(mfrc522Registers::tMode, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
    writeRegister(mfrc522Registers::tPrescaler, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25�s.
    writeRegister(mfrc522Registers::tReloadH, 0x03);		// Reload timer with 0x3E8 = 1000, 25ms before timeout.
    writeRegister(mfrc522Registers::tReloadL, 0xE8);

    writeRegister(mfrc522Registers::txAsk, 0x40);		// Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
    writeRegister(mfrc522Registers::mode, 0x3D);		// Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363
    antennaOn(); 						// enable antenna
    setAntennaGain(0x70);				// set the antenna gain
}

void Mfrc522::antennaOn(){
    uint8_t value = readRegister(mfrc522Registers::txControl);
    writeRegister(mfrc522Registers::txControl, value |= 0x03); // set lower 2 bits
}

void Mfrc522::antennaOff(){
    uint8_t value = readRegister(mfrc522Registers::txControl);
    writeRegister(mfrc522Registers::txControl, value&0xFC); // clear lower 2 bits
}

void Mfrc522::setAntennaGain(uint8_t value){
    if(getAntennaGain() != value){
        clearRegisterBitMask(mfrc522Registers::rfcFg, (0x07<<4));
        setRegisterBitMask(mfrc522Registers::rfcFg, value & (0x07<<4));
    }
}

uint8_t Mfrc522::getAntennaGain(){
    return readRegister(mfrc522Registers::rfcFg) & (0x07 << 4);
}

Mfrc522::statusCodes Mfrc522::communicateWithTag(const mfrc522Commands command,
                                                 const uint8_t * sendData,
                                                 const uint8_t sendDataLen,
                                                 uint8_t * receiveData,
                                                 const uint8_t receiveDataLen){

    writeRegister(mfrc522Registers::command, static_cast<uint8_t>(mfrc522Commands::idle));		// Stop any active command.
    writeRegister(mfrc522Registers::comIrq, 0x7F);			// Clear all seven interrupt request bits
    setRegisterBitMask(mfrc522Registers::FIFOLevel, 0x80);     // flush the buffer
    writeRegister(mfrc522Registers::FIFOData, sendData, sendDataLen);	// Write sendData to the FIFO
    writeRegister(mfrc522Registers::command, static_cast<uint8_t>(command)); //execute command

    if(command == mfrc522Commands::transceive){
        setRegisterBitMask(mfrc522Registers::bitFraming, 0x80); //start send
    }
    int i = 50; //max ~50 milliseconds timeout
    while(true){
        uint8_t n = readRegister(mfrc522Registers::comIrq);
        if(n & 0x30){
            break; // Tag found
        }
        else if(n & 0x01){
            return statusCodes::statusError; // no Tag found
        }
        if(--i == 0){
            return statusCodes::statusTimeout; // something went wrong. Is the mfrc522 connected properly?
        }
        delay(1);
    }
    if(receiveData){ // if receiveData is not nullptr
      uint8_t recievedLen = readRegister(mfrc522Registers::FIFOLevel);
        if(receiveDataLen >= recievedLen){ // does the data fit in the given container?
            for(uint8_t i = 0;i < recievedLen;i++){
                receiveData[i] = readRegister(mfrc522Registers::FIFOData); // copy data
            }
        }
    }
    return statusCodes::statusOk;
}

bool Mfrc522::isTagPresent(){
    writeRegister(mfrc522Registers::bitFraming, 0x07);

    uint8_t data = static_cast<uint8_t>(mifareCommands::reqIdle); // first element is the command to send to the tag. Here we request every tag that is in idle

    statusCodes status = communicateWithTag(mfrc522Commands::transceive, &data, 1, nullptr, 0); // nullptr beacause we do not need ro read data from the tag.

    return status == statusCodes::statusOk;
}

Mfrc522::statusCodes Mfrc522::receiveTagId(uint8_t * inputForId){
    writeRegister(mfrc522Registers::bitFraming, 0x07);

    uint8_t data = static_cast<uint8_t>(mifareCommands::antiColl);

    statusCodes status = communicateWithTag(mfrc522Commands::transceive, &data, 1, inputForId, 16);

    return status;
}<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"

#include "base58.h"
#include "util.h"

using namespace json_spirit;
extern Array read_json(const std::string& filename);

BOOST_AUTO_TEST_SUITE(base58_tests)

// Goal: test low-level base58 encoding functionality
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
    Array tests = read_json("base58_encode_decode.json");

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 2) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
        std::string base58string = test[1].get_str();
        BOOST_CHECK_MESSAGE(
                    EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string,
                    strTest);
    }
}

// Goal: test low-level base58 decoding functionality
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
    Array tests = read_json("base58_encode_decode.json");
    std::vector<unsigned char> result;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 2) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::vector<unsigned char> expected = ParseHex(test[0].get_str());
        std::string base58string = test[1].get_str();
        BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest);
        BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest);
    }

    BOOST_CHECK(!DecodeBase58("invalid", result));
}

// Visitor to check address type
class TestAddrTypeVisitor : public boost::static_visitor<bool>
{
private:
    std::string exp_addrType;
public:
    TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { }
    bool operator()(const CKeyID &id) const
    {
        return (exp_addrType == "pubkey");
    }
    bool operator()(const CScriptID &id) const
    {
        return (exp_addrType == "script");
    }
    bool operator()(const CNoDestination &no) const
    {
        return (exp_addrType == "none");
    }
};

// Visitor to check address payload
class TestPayloadVisitor : public boost::static_visitor<bool>
{
private:
    std::vector<unsigned char> exp_payload;
public:
    TestPayloadVisitor(std::vector<unsigned char> &exp_payload) : exp_payload(exp_payload) { }
    bool operator()(const CKeyID &id) const
    {
        uint160 exp_key(exp_payload);
        return exp_key == id;
    }
    bool operator()(const CScriptID &id) const
    {
        uint160 exp_key(exp_payload);
        return exp_key == id;
    }
    bool operator()(const CNoDestination &no) const
    {
        return exp_payload.size() == 0;
    }
};

// Goal: check that parsed keys match test payload
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
    Array tests = read_json("base58_keys_valid.json");
    std::vector<unsigned char> result;
    CBitcoinSecret secret;
    CBitcoinAddress addr;
    // Save global state
    bool fTestNet_stored = fTestNet;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 3) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();
        std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
        const Object &metadata = test[2].get_obj();
        bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
        bool isTestnet = find_value(metadata, "isTestnet").get_bool();
        fTestNet = isTestnet; // Override testnet flag
        if(isPrivkey)
        {
            bool isCompressed = find_value(metadata, "isCompressed").get_bool();
            // Must be valid private key
            // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
            BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
            BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
            bool fCompressedOut = false;
            CSecret privkey = secret.GetSecret(fCompressedOut);
            BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest);
            BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);

            // Private key must be invalid public key
            addr.SetString(exp_base58string);
            BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest);
        }
        else
        {
            std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
            // Must be valid public key
            BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest);
            BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
            BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
            CTxDestination dest = addr.Get();
            BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);

            // Public key must be invalid private key
            secret.SetString(exp_base58string);
            BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
        }
    }
    // Restore global state
    fTestNet = fTestNet_stored;
}

// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
    Array tests = read_json("base58_keys_valid.json");
    std::vector<unsigned char> result;
    // Save global state
    bool fTestNet_stored = fTestNet;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 3) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();
        std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
        const Object &metadata = test[2].get_obj();
        bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
        bool isTestnet = find_value(metadata, "isTestnet").get_bool();
        fTestNet = isTestnet; // Override testnet flag
        if(isPrivkey)
        {
            bool isCompressed = find_value(metadata, "isCompressed").get_bool();
            CBitcoinSecret secret;
            secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed);
            BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
        }
        else
        {
            std::string exp_addrType = find_value(metadata, "addrType").get_str();
            CTxDestination dest;
            if(exp_addrType == "pubkey")
            {
                dest = CKeyID(uint160(exp_payload));
            }
            else if(exp_addrType == "script")
            {
                dest = CScriptID(uint160(exp_payload));
            }
            else if(exp_addrType == "none")
            {
                dest = CNoDestination();
            }
            else
            {
                BOOST_ERROR("Bad addrtype: " << strTest);
                continue;
            }
            CBitcoinAddress addrOut;
            BOOST_CHECK_MESSAGE(boost::apply_visitor(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest);
            BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
        }
    }

    // Visiting a CNoDestination must fail
    CBitcoinAddress dummyAddr;
    CTxDestination nodest = CNoDestination();
    BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest));

    // Restore global state
    fTestNet = fTestNet_stored;
}

// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
    Array tests = read_json("base58_keys_invalid.json"); // Negative testcases
    std::vector<unsigned char> result;
    CBitcoinSecret secret;
    CBitcoinAddress addr;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 1) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();

        // must be invalid as public and as private key
        addr.SetString(exp_base58string);
        BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest);
        secret.SetString(exp_base58string);
        BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
    }
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Update to v3<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Copyright (c) 2013-2014 Memorycoin Dev Team

#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"

#include "base58.h"
#include "util.h"

using namespace json_spirit;
extern Array read_json(const std::string& filename);

BOOST_AUTO_TEST_SUITE(base58_tests)

// Goal: test low-level base58 encoding functionality
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
    Array tests = read_json("base58_encode_decode.json");

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 2) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
        std::string base58string = test[1].get_str();
        BOOST_CHECK_MESSAGE(
                    EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string,
                    strTest);
    }
}

// Goal: test low-level base58 decoding functionality
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
    Array tests = read_json("base58_encode_decode.json");
    std::vector<unsigned char> result;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 2) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::vector<unsigned char> expected = ParseHex(test[0].get_str());
        std::string base58string = test[1].get_str();
        BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest);
        BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest);
    }

    BOOST_CHECK(!DecodeBase58("invalid", result));
}

// Visitor to check address type
class TestAddrTypeVisitor : public boost::static_visitor<bool>
{
private:
    std::string exp_addrType;
public:
    TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { }
    bool operator()(const CKeyID &id) const
    {
        return (exp_addrType == "pubkey");
    }
    bool operator()(const CScriptID &id) const
    {
        return (exp_addrType == "script");
    }
    bool operator()(const CNoDestination &no) const
    {
        return (exp_addrType == "none");
    }
};

// Visitor to check address payload
class TestPayloadVisitor : public boost::static_visitor<bool>
{
private:
    std::vector<unsigned char> exp_payload;
public:
    TestPayloadVisitor(std::vector<unsigned char> &exp_payload) : exp_payload(exp_payload) { }
    bool operator()(const CKeyID &id) const
    {
        uint160 exp_key(exp_payload);
        return exp_key == id;
    }
    bool operator()(const CScriptID &id) const
    {
        uint160 exp_key(exp_payload);
        return exp_key == id;
    }
    bool operator()(const CNoDestination &no) const
    {
        return exp_payload.size() == 0;
    }
};

// Goal: check that parsed keys match test payload
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
    Array tests = read_json("base58_keys_valid.json");
    std::vector<unsigned char> result;
    CMemorycoinSecret secret;
    CMemorycoinAddress addr;
    // Save global state
    bool fTestNet_stored = fTestNet;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 3) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();
        std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
        const Object &metadata = test[2].get_obj();
        bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
        bool isTestnet = find_value(metadata, "isTestnet").get_bool();
        fTestNet = isTestnet; // Override testnet flag
        if(isPrivkey)
        {
            bool isCompressed = find_value(metadata, "isCompressed").get_bool();
            // Must be valid private key
            // Note: CMemorycoinSecret::SetString tests isValid, whereas CMemorycoinAddress does not!
            BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
            BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
            bool fCompressedOut = false;
            CSecret privkey = secret.GetSecret(fCompressedOut);
            BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest);
            BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);

            // Private key must be invalid public key
            addr.SetString(exp_base58string);
            BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest);
        }
        else
        {
            std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
            // Must be valid public key
            BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest);
            BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
            BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
            CTxDestination dest = addr.Get();
            BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);

            // Public key must be invalid private key
            secret.SetString(exp_base58string);
            BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
        }
    }
    // Restore global state
    fTestNet = fTestNet_stored;
}

// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
    Array tests = read_json("base58_keys_valid.json");
    std::vector<unsigned char> result;
    // Save global state
    bool fTestNet_stored = fTestNet;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 3) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();
        std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
        const Object &metadata = test[2].get_obj();
        bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
        bool isTestnet = find_value(metadata, "isTestnet").get_bool();
        fTestNet = isTestnet; // Override testnet flag
        if(isPrivkey)
        {
            bool isCompressed = find_value(metadata, "isCompressed").get_bool();
            CMemorycoinSecret secret;
            secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed);
            BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
        }
        else
        {
            std::string exp_addrType = find_value(metadata, "addrType").get_str();
            CTxDestination dest;
            if(exp_addrType == "pubkey")
            {
                dest = CKeyID(uint160(exp_payload));
            }
            else if(exp_addrType == "script")
            {
                dest = CScriptID(uint160(exp_payload));
            }
            else if(exp_addrType == "none")
            {
                dest = CNoDestination();
            }
            else
            {
                BOOST_ERROR("Bad addrtype: " << strTest);
                continue;
            }
            CMemorycoinAddress addrOut;
            BOOST_CHECK_MESSAGE(boost::apply_visitor(CMemorycoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest);
            BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
        }
    }

    // Visiting a CNoDestination must fail
    CMemorycoinAddress dummyAddr;
    CTxDestination nodest = CNoDestination();
    BOOST_CHECK(!boost::apply_visitor(CMemorycoinAddressVisitor(&dummyAddr), nodest));

    // Restore global state
    fTestNet = fTestNet_stored;
}

// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
    Array tests = read_json("base58_keys_invalid.json"); // Negative testcases
    std::vector<unsigned char> result;
    CMemorycoinSecret secret;
    CMemorycoinAddress addr;

    BOOST_FOREACH(Value& tv, tests)
    {
        Array test = tv.get_array();
        std::string strTest = write_string(tv, false);
        if (test.size() < 1) // Allow for extra stuff (useful for comments)
        {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }
        std::string exp_base58string = test[0].get_str();

        // must be invalid as public and as private key
        addr.SetString(exp_base58string);
        BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest);
        secret.SetString(exp_base58string);
        BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
    }
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>#include <cstdint>

#include "clockUtils/errors.h"
#include "clockUtils/argparser/ArgumentParser.h"

#include "gtest/gtest.h"

TEST(ArgumentParser, parseBool) {
	REGISTER_VARIABLE(bool, b, false, "A test boolean");
	REGISTER_VARIABLE(bool, d, false, "A test boolean");
	REGISTER_VARIABLE(bool, foo, false, "A test boolean");
	REGISTER_VARIABLE(bool, bar, false, "A test boolean");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-b" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-b", "-d", "-foo", "-bar" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	EXPECT_EQ(false, b);

	EXPECT_EQ(clockUtils::ClockError::INVALID_ARGUMENT, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());
	EXPECT_EQ(false, b);

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(true, b);

	b = false;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(true, b);
	EXPECT_EQ(true, d);
	EXPECT_EQ(true, foo);
	EXPECT_EQ(true, bar);
}

TEST(ArgumentParser, parseString) {
	REGISTER_VARIABLE(std::string, s, "test", "A test string");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-s" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-s", "blafoo" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	char * buffer4[] = { "-sblafoo" };
	int length4 = sizeof(buffer4) / sizeof(char *);

	char * buffer5[] = { "-s=blafoo" };
	int length5 = sizeof(buffer5) / sizeof(char *);

	EXPECT_EQ("test", s);

	EXPECT_EQ(clockUtils::ClockError::INVALID_ARGUMENT, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());

	EXPECT_EQ("test", s);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("test", s);
	EXPECT_EQ("s requires a value: -s <value> or -s<value> or -s=<value>", GETLASTPARSERERROR());

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer4, length4));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer5, length5));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);
}

TEST(ArgumentParser, parseInt) {
	REGISTER_VARIABLE(int32_t, i, -1, "A test integer");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-i" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-i", "blafoo" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	char * buffer4[] = { "-i", "10" };
	int length4 = sizeof(buffer4) / sizeof(char *);

	char * buffer5[] = { "-i11" };
	int length5 = sizeof(buffer5) / sizeof(char *);

	char * buffer6[] = { "-i=12" };
	int length6 = sizeof(buffer6) / sizeof(char *);

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_ARGUMENT, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("i requires a value: -i <value> or -i<value> or -i=<value>", GETLASTPARSERERROR());

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("blafoo is not a valid value for variable i", GETLASTPARSERERROR());

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer4, length4));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(10, i);

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer5, length5));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(11, i);

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer6, length6));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(12, i);
}

TEST(ArgumentParser, parseMultiple) {
	REGISTER_VARIABLE(int32_t, i, -1, "A test integer");
	REGISTER_VARIABLE(std::string, s, "empty", "A test string");
	REGISTER_VARIABLE(bool, b, false, "A test bool");
	REGISTER_VARIABLE(double, d, 1.23, "A test double");

	char * buffer1[] = { "-i", "1234", "-s", "readString", "-b", "-d=3.14" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(1234, i);
	EXPECT_EQ("readString", s);
	EXPECT_EQ(true, b);
	EXPECT_DOUBLE_EQ(3.14, d);
}
<commit_msg>CU-14 (argparser) fixed tests<commit_after>#include <cstdint>

#include "clockUtils/errors.h"
#include "clockUtils/argparser/ArgumentParser.h"

#include "gtest/gtest.h"

TEST(ArgumentParser, parseBool) {
	REGISTER_VARIABLE(bool, b, false, "A test boolean");
	REGISTER_VARIABLE(bool, d, false, "A test boolean");
	REGISTER_VARIABLE(bool, foo, false, "A test boolean");
	REGISTER_VARIABLE(bool, bar, false, "A test boolean");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-b" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-b", "-d", "-foo", "-bar" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	EXPECT_EQ(false, b);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());
	EXPECT_EQ(false, b);

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(true, b);

	b = false;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(true, b);
	EXPECT_EQ(true, d);
	EXPECT_EQ(true, foo);
	EXPECT_EQ(true, bar);
}

TEST(ArgumentParser, parseString) {
	REGISTER_VARIABLE(std::string, s, "test", "A test string");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-s" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-s", "blafoo" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	char * buffer4[] = { "-sblafoo" };
	int length4 = sizeof(buffer4) / sizeof(char *);

	char * buffer5[] = { "-s=blafoo" };
	int length5 = sizeof(buffer5) / sizeof(char *);

	EXPECT_EQ("test", s);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());

	EXPECT_EQ("test", s);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("test", s);
	EXPECT_EQ("s requires a value: -s <value> or -s<value> or -s=<value>", GETLASTPARSERERROR());

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer4, length4));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);

	s = "";

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer5, length5));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ("blafoo", s);
}

TEST(ArgumentParser, parseInt) {
	REGISTER_VARIABLE(int32_t, i, -1, "A test integer");

	char * buffer1[] = { "-c", "-e", "3" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	char * buffer2[] = { "-i" };
	int length2 = sizeof(buffer2) / sizeof(char *);

	char * buffer3[] = { "-i", "blafoo" };
	int length3 = sizeof(buffer3) / sizeof(char *);

	char * buffer4[] = { "-i", "10" };
	int length4 = sizeof(buffer4) / sizeof(char *);

	char * buffer5[] = { "-i11" };
	int length5 = sizeof(buffer5) / sizeof(char *);

	char * buffer6[] = { "-i=12" };
	int length6 = sizeof(buffer6) / sizeof(char *);

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("argument -c not registered!", GETLASTPARSERERROR());

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer2, length2));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("i requires a value: -i <value> or -i<value> or -i=<value>", GETLASTPARSERERROR());

	EXPECT_EQ(-1, i);

	EXPECT_EQ(clockUtils::ClockError::INVALID_USAGE, PARSE_ARGUMENTS(buffer3, length3));

	EXPECT_FALSE(GETLASTPARSERERROR().empty());
	EXPECT_EQ("blafoo is not a valid value for variable i", GETLASTPARSERERROR());

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer4, length4));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(10, i);

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer5, length5));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(11, i);

	i = -1;

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer6, length6));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(12, i);
}

TEST(ArgumentParser, parseMultiple) {
	REGISTER_VARIABLE(int32_t, i, -1, "A test integer");
	REGISTER_VARIABLE(std::string, s, "empty", "A test string");
	REGISTER_VARIABLE(bool, b, false, "A test bool");
	REGISTER_VARIABLE(double, d, 1.23, "A test double");

	char * buffer1[] = { "-i", "1234", "-s", "readString", "-b", "-d=3.14" };
	int length1 = sizeof(buffer1) / sizeof(char *);

	EXPECT_EQ(clockUtils::ClockError::SUCCESS, PARSE_ARGUMENTS(buffer1, length1));

	EXPECT_TRUE(GETLASTPARSERERROR().empty());

	EXPECT_EQ(1234, i);
	EXPECT_EQ("readString", s);
	EXPECT_EQ(true, b);
	EXPECT_DOUBLE_EQ(3.14, d);
}
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_COMMON_EXCEPTIONS_HH
#define DUNE_STUFF_COMMON_EXCEPTIONS_HH

#include <dune/common/exceptions.hh>

#include <dune/stuff/common/color.hh>

/**
 *  \brief Macro to throw a colorfull exception.
 *
 *  Example:
\code
#include <dune/stuff/common/exceptions.hh>

if (a.size() != b.size())
  DUNE_THROW_COLORFULLY(Exceptions::shapes_do_not_match,
                       "size of a (" << a.size() << ") does not match the size of b (" << b.size() << ")!");
\endcode
 *  This macro is essentially copied from dune-common with added color functionality.
 *  \param  E Exception class, derived from Dune::Exception.
 *  \param  m Message in ostream notation.
 *  \see DUNE_THROW, Dune::Exception
 */
#define DUNE_THROW_COLORFULLY(E, m) \
  do { \
    E th__ex; \
    std::ostringstream th__msg; \
    th__msg << m; \
    std::ostringstream th__out; \
    th__out << Dune::Stuff::Common::Colors::red << # E << "\033[0m\n"; \
    th__out << Dune::Stuff::Common::Colors::red << "[\033[0m"; \
    th__out << __func__; \
    th__out << Dune::Stuff::Common::Colors::red << "|\033[0m"; \
    th__out << __FILE__ << Dune::Stuff::Common::Colors::red << ":" << __LINE__ << "]\033[0m"; \
    if (!th__msg.str().empty()) th__out << "\n" << Dune::Stuff::Common::Colors::red << "=>\033[0m " << th__msg.str(); \
      th__ex.message(th__out.str()); \
    throw th__ex; \
  } while (0)
// DUNE_THROW_COLORFULLY

namespace Dune {
namespace Stuff {
namespace Exceptions {

class CRTP_check_failed : public Dune::Exception {};

class shapes_do_not_match : public Dune::Exception {};

class index_out_of_range : public Dune::Exception {};

class you_are_using_this_wrong : public Dune::Exception {};

class wrong_input_given : public you_are_using_this_wrong {};

class requirements_not_met: public you_are_using_this_wrong {};

class configuration_error : public Dune::Exception {};

class results_are_not_as_expected : public Dune::Exception {};

class internal_error : public Dune::Exception {};

class external_error : public Dune::Exception {};

class linear_solver_failed : public Dune::Exception {};

} // namespace Exceptions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_EXCEPTIONS_HH
<commit_msg>[common.exceptions] * give mpi info in parallel runs * overwrite DUNE_THROW<commit_after>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_COMMON_EXCEPTIONS_HH
#define DUNE_STUFF_COMMON_EXCEPTIONS_HH

#include <dune/common/exceptions.hh>
#include <dune/common/parallel/mpihelper.hh>

/**
 *  \brief Macro to throw a colorfull exception.
 *
 *  Example:
\code
#include <dune/stuff/common/exceptions.hh>

if (a.size() != b.size())
  DUNE_THROW_COLORFULLY(Exceptions::shapes_do_not_match,
                       "size of a (" << a.size() << ") does not match the size of b (" << b.size() << ")!");
\endcode
 *  This macro is essentially copied from dune-common with added color functionality.
 *  \param  E Exception class, derived from Dune::Exception.
 *  \param  m Message in ostream notation.
 *  \see DUNE_THROW, Dune::Exception
 */
#define DUNE_THROW_COLORFULLY(E, m) \
  do { \
    const std::string red = "\033[31m"; \
    const std::string clear = "\033[0m"; \
    E th__ex; \
    std::ostringstream th__msg; \
    th__msg << m; \
    std::ostringstream th__out; \
    th__out << red << # E << clear; \
    if (Dune::MPIHelper::getCollectiveCommunication().size() > 0) \
      th__out << " (on rank " << Dune::MPIHelper::getCollectiveCommunication().rank() << ")"; \
    th__out << "\n"; \
    th__out << red << "[" << clear; \
    th__out << __func__; \
    th__out << red << "|" << clear; \
    th__out << __FILE__ << red << ":" << __LINE__ << "]" << clear; \
    if (!th__msg.str().empty()) th__out << "\n" << red << "=>" << clear << " " << th__msg.str(); \
      th__ex.message(th__out.str()); \
    throw th__ex; \
  } while (0)
// DUNE_THROW_COLORFULLY

#ifdef DUNE_THROW
# undef DUNE_THROW
# define DUNE_THROW DUNE_THROW_COLORFULLY
#endif // DUNE_THROW

namespace Dune {
namespace Stuff {
namespace Exceptions {

class CRTP_check_failed : public Dune::Exception {};

class shapes_do_not_match : public Dune::Exception {};

class index_out_of_range : public Dune::Exception {};

class you_are_using_this_wrong : public Dune::Exception {};

class wrong_input_given : public you_are_using_this_wrong {};

class requirements_not_met: public you_are_using_this_wrong {};

class configuration_error : public Dune::Exception {};

class results_are_not_as_expected : public Dune::Exception {};

class internal_error : public Dune::Exception {};

class external_error : public Dune::Exception {};

class linear_solver_failed : public Dune::Exception {};

} // namespace Exceptions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_EXCEPTIONS_HH
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static SigSpec or_generator(Module *module, const SigSpec &sig)
{
	switch (GetSize(sig))
	{
	case 0:
		return State::S0;
	case 1:
		return sig;
	case 2:
		return module->Or(NEW_ID, sig[0], sig[1]);
	default:
		return module->ReduceOr(NEW_ID, sig);
	}
}

static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or)
{
	if (GetSize(sig_sel) == 1) {
		sig_or.append(sig_sel);
		return sig_data;
	}

	int left_size = GetSize(sig_sel) / 2;
	int right_size = GetSize(sig_sel) - left_size;
	int stride = GetSize(sig_data) / GetSize(sig_sel);

	SigSpec left_data = sig_data.extract(0, stride*left_size);
	SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size);

	SigSpec left_sel = sig_sel.extract(0, left_size);
	SigSpec right_sel = sig_sel.extract(left_size, right_size);

	SigSpec left_or, left_result, right_result;

	left_result = recursive_mux_generator(module, left_data, left_sel, left_or);
	right_result = recursive_mux_generator(module, right_data, right_sel, sig_or);
	left_or = or_generator(module, left_or);
	sig_or.append(left_or);

	return module->Mux(NEW_ID, right_result, left_result, left_or);
}

struct PmuxtreePass : public Pass {
	PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    pmuxtree [options] [selection]\n");
		log("\n");
		log("This pass transforms $pmux cells to a trees of $mux cells.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing PMUXTREE pass.\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		for (auto cell : module->selected_cells())
		{
			if (cell->type != "$pmux")
				continue;

			SigSpec sig_data = cell->getPort("\\B");
			SigSpec sig_sel = cell->getPort("\\S");

			if (!cell->getPort("\\A").is_fully_undef()) {
				sig_data.append(cell->getPort("\\A"));
				SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
				sig_sel.append(module->Not(NEW_ID, sig_sel_or));
			}

			SigSpec result, result_or;
			result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
			module->connect(cell->getPort("\\Y"), result);
			module->remove(cell);
		}
	}
} PmuxtreePass;

PRIVATE_NAMESPACE_END
<commit_msg>Spelling fixes<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static SigSpec or_generator(Module *module, const SigSpec &sig)
{
	switch (GetSize(sig))
	{
	case 0:
		return State::S0;
	case 1:
		return sig;
	case 2:
		return module->Or(NEW_ID, sig[0], sig[1]);
	default:
		return module->ReduceOr(NEW_ID, sig);
	}
}

static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or)
{
	if (GetSize(sig_sel) == 1) {
		sig_or.append(sig_sel);
		return sig_data;
	}

	int left_size = GetSize(sig_sel) / 2;
	int right_size = GetSize(sig_sel) - left_size;
	int stride = GetSize(sig_data) / GetSize(sig_sel);

	SigSpec left_data = sig_data.extract(0, stride*left_size);
	SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size);

	SigSpec left_sel = sig_sel.extract(0, left_size);
	SigSpec right_sel = sig_sel.extract(left_size, right_size);

	SigSpec left_or, left_result, right_result;

	left_result = recursive_mux_generator(module, left_data, left_sel, left_or);
	right_result = recursive_mux_generator(module, right_data, right_sel, sig_or);
	left_or = or_generator(module, left_or);
	sig_or.append(left_or);

	return module->Mux(NEW_ID, right_result, left_result, left_or);
}

struct PmuxtreePass : public Pass {
	PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    pmuxtree [selection]\n");
		log("\n");
		log("This pass transforms $pmux cells to trees of $mux cells.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing PMUXTREE pass.\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		for (auto cell : module->selected_cells())
		{
			if (cell->type != "$pmux")
				continue;

			SigSpec sig_data = cell->getPort("\\B");
			SigSpec sig_sel = cell->getPort("\\S");

			if (!cell->getPort("\\A").is_fully_undef()) {
				sig_data.append(cell->getPort("\\A"));
				SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
				sig_sel.append(module->Not(NEW_ID, sig_sel_or));
			}

			SigSpec result, result_or;
			result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
			module->connect(cell->getPort("\\Y"), result);
			module->remove(cell);
		}
	}
} PmuxtreePass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "mimdummyinputcontext.h"
#include "minputcontextglibdbusconnection.h"
#include "mimserver.h"

#if defined(Q_WS_X11)
#include "mimxapplication.h"
#endif

#include <QApplication>
#include <QtDebug>
#include <QPalette>
#include <QCommonStyle>
#include <stdlib.h>

using namespace std::tr1;

namespace {
    void disableMInputContextPlugin()
    {
        // prevent loading of minputcontext because we don't need it and starting
        // it might trigger starting of this service by the d-bus. not nice if that is
        // already happening :)
        if (-1 == unsetenv("QT_IM_MODULE")) {
            qWarning("meego-im-uiserver: unable to unset QT_IM_MODULE.");
        }

        // TODO: Check if hardwiring the QStyle can be removed at a later stage.
        QApplication::setStyle(new QCommonStyle);
    }
}

int main(int argc, char **argv)
{
    // QT_IM_MODULE, MApplication and QtMaemo5Style all try to load
    // MInputContext, which is fine for the application. For the passthrough
    // server itself, we absolutely need to prevent that.
    disableMInputContextPlugin();

#if defined(Q_WS_X11)
    MImXApplication app(argc, argv);
#elif defined(Q_WS_QPA)
    QApplication app(argc, argv);
#endif

    // Set a dummy input context so that Qt does not create a default input
    // context (qimsw-multi) which is expensive and not required by
    // meego-im-uiserver.
    app.setInputContext(new MIMDummyInputContext);

    // DBus Input Context Connection
    shared_ptr<MInputContextConnection> icConnection(new MInputContextGlibDBusConnection);

    MImServer imServer(icConnection);
    Q_UNUSED(imServer);

    return app.exec();
}

<commit_msg>Standardized debug output for Maliit - Server<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "mimdummyinputcontext.h"
#include "minputcontextglibdbusconnection.h"
#include "mimserver.h"

#if defined(Q_WS_X11)
#include "mimxapplication.h"
#endif

#include <QApplication>
#include <QtDebug>
#include <QPalette>
#include <QCommonStyle>
#include <stdlib.h>

using namespace std::tr1;

namespace {
    void disableMInputContextPlugin()
    {
        // prevent loading of minputcontext because we don't need it and starting
        // it might trigger starting of this service by the d-bus. not nice if that is
        // already happening :)
        if (-1 == unsetenv("QT_IM_MODULE")) {
            qWarning("meego-im-uiserver: unable to unset QT_IM_MODULE.");
        }

        // TODO: Check if hardwiring the QStyle can be removed at a later stage.
        QApplication::setStyle(new QCommonStyle);
    }

    bool isDebugEnabled()
    {
        static int debugEnabled = -1;

        if (debugEnabled == -1) {
            QByteArray debugEnvVar = qgetenv("MALIIT_DEBUG");
            if (debugEnvVar.toLower() == "enabled") {
                debugEnabled = 1;
            } else {
                debugEnabled = 0;
            }
        }

        return debugEnabled == 1;
    }

    void ouputMessagesToStdErr(QtMsgType type, const char *msg)
    {
        switch (type) {
        case QtDebugMsg:
            if (isDebugEnabled()) {
                fprintf(stderr, "DEBUG: %s\n", msg);
            }
            break;
        case QtWarningMsg:
            fprintf(stderr, "WARNING: %s\n", msg);
            break;
        case QtCriticalMsg:
            fprintf(stderr, "CRITICAL: %s\n", msg);
            break;
        case QtFatalMsg:
            fprintf(stderr, "FATAL: %s\n", msg);
            abort();
        }
    }
}

int main(int argc, char **argv)
{
    qInstallMsgHandler(ouputMessagesToStdErr);

    // QT_IM_MODULE, MApplication and QtMaemo5Style all try to load
    // MInputContext, which is fine for the application. For the passthrough
    // server itself, we absolutely need to prevent that.
    disableMInputContextPlugin();

#if defined(Q_WS_X11)
    MImXApplication app(argc, argv);
#elif defined(Q_WS_QPA)
    QApplication app(argc, argv);
#endif

    // Set a dummy input context so that Qt does not create a default input
    // context (qimsw-multi) which is expensive and not required by
    // meego-im-uiserver.
    app.setInputContext(new MIMDummyInputContext);

    // DBus Input Context Connection
    shared_ptr<MInputContextConnection> icConnection(new MInputContextGlibDBusConnection);

    MImServer imServer(icConnection);
    Q_UNUSED(imServer);

    return app.exec();
}

<|endoftext|>