/* Roman.c, convert to Roman numerals for LCARS 24 Unit Conversion
	This module provides the two functions itor() and rtoi(), for
	converting integers into roman numbers and vice versa.
	Prototypes: int rtoi(char *rom);
			void itor(int num, char *str);
	Currently supports numbers only in the range of 0-3999.
	Released under the MIT (a qualified open source) license
	(C) Kristof Kovacs, 1999
*/

#ifndef ROMAN_H
#define ROMAN_H

#endif

#include "roman.h"

struct roman_number {
	char letter;
	int value;
};

static struct roman_number roman[] = {
	{'I', 1},
	{'V', 5},
	{'X', 10},
	{'L', 50},
	{'C', 100},
	{'D', 500},
	{'M', 1000},
	{'\0', 0}
};

int rtoi(char *rom)
{
	int num = 0;
	int state = 0;
	char *p;
	int idx;

	p = rom + strlen(rom);
	while (p >= rom){
		idx = 0;
		while (roman[idx].value > 0) {
			if (*p == roman[idx].letter || *p == roman[idx].letter + (char)32)
				if (state > roman[idx].value)
					num -= roman[idx].value;
					else {
						num += roman[idx].value;
						state = roman[idx].value;
					}
				idx++;
		}
		p--;
	}
	return num;
}

void itor(int num, char *str)
{
	int idx;
	int foo;
	char *p;
	p = str;
	idx = sizeof(roman) / sizeof(struct roman_number) - 2;
	while (idx >= 0) {
		foo = num / roman[idx].value;
		if (foo != 0) num = num % (foo * roman[idx].value);
		if (foo > 4 && foo < 9) {
			*p = roman[idx+1].letter;
			p++;
			foo -= 5;
		}
		if (foo == 4) {
			*p = roman[idx].letter;
			p++;
			*p = roman[idx+1].letter;
			p++;
		} else if (foo == 9) {
			*p = roman[idx].letter;
			p++;
			*p = roman[idx+2].letter;
			p++;
		} else
			while (foo != 0) {
				*p = roman[idx].letter;
				p++;
				foo--;
			}
		idx-=2;
	}
	*p = (char)0;
}

/*
Only for testing purposes

int main(int argc, char **argv)
{
	char foo[80];
	int num;
	if (argc == 1) scanf("%d", &num);
	else sscanf(argv[1],"%d", &num);
	itor(num, foo);
	printf("%s\n", foo);
	printf("%d\n", rtoi(foo));
}
*/

/* eof */

