blob: 6cd5220d372c1675ce524fef80442351bb3d85fd [file] [log] [blame]
//========================================================================
//
// This file is under the GPLv2 or later license
//
// Copyright (C) 2005-2006 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2005, 2009, 2014 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2011 Simon Kellner <kellner@kit.edu>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
/* http://mathworld.wolfram.com/RomanNumerals.html */
#include "goo/GooString.h"
#include "Error.h"
static int fromRoman(const char *buffer) {
int digit_value, prev_digit_value, value;
int i;
prev_digit_value = INT_MAX;
value = 0;
for (i = 0; buffer[i] != '\0'; i++) {
switch (buffer[i]) {
case 'm':
case 'M':
digit_value = 1000;
break;
case 'd':
case 'D':
digit_value = 500;
break;
case 'c':
case 'C':
digit_value = 100;
break;
case 'l':
case 'L':
digit_value = 50;
break;
case 'x':
case 'X':
digit_value = 10;
break;
case 'v':
case 'V':
digit_value = 5;
break;
case 'i':
case 'I':
digit_value = 1;
break;
default:
return -1;
}
if (digit_value <= prev_digit_value)
value += digit_value;
else
value += digit_value - prev_digit_value * 2;
prev_digit_value = digit_value;
}
return value;
}
static void toRoman(int number, GooString *str, GBool uppercase) {
static const char uppercaseNumerals[] = "IVXLCDM";
static const char lowercaseNumerals[] = "ivxlcdm";
int divisor;
int i, j, k;
const char *wh;
if (number >= 4000) {
error(errUnimplemented, -1, "Conversion to roman numberals of numbers >= 4000 not implemented");
return;
}
if (uppercase)
wh = uppercaseNumerals;
else
wh = lowercaseNumerals;
divisor = 1000;
for (k = 3; k >= 0; k--) {
i = number / divisor;
number = number % divisor;
switch (i) {
case 0:
break;
case 5:
str->append(wh[2 * k + 1]);
break;
case 9:
str->append(wh[2 * k + 0]);
str->append(wh[ 2 * k + 2]);
break;
case 4:
str->append(wh[2 * k + 0]);
str->append(wh[2 * k + 1]);
break;
default:
if (i > 5) {
str->append(wh[2 * k + 1]);
i -= 5;
}
for (j = 0; j < i; j++) {
str->append(wh[2 * k + 0]);
}
}
divisor = divisor / 10;
}
}
static int fromLatin(const char *buffer)
{
int count;
const char *p;
for (p = buffer; *p; p++) {
if (*p != buffer[0])
return -1;
}
count = p - buffer;
if (buffer[0] >= 'a' && buffer[0] <= 'z')
return 26 * (count - 1) + buffer[0] - 'a' + 1;
if (buffer[0] >= 'A' && buffer[0] <= 'Z')
return 26 * (count - 1) + buffer[0] - 'A' + 1;
return -1;
}
static void toLatin(int number, GooString *str, GBool uppercase) {
char base, letter;
int i, count;
if (uppercase)
base = 'A';
else
base = 'a';
count = (number - 1) / 26 + 1;
letter = base + (number - 1) % 26;
for (i = 0; i < count; i++)
str->append(letter);
}