jellyfish/cjellyfish/nysiis.c

183 lines
3.8 KiB
C

#include "jellyfish.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define ISVOWEL(a) ((a) == 'A' || (a) == 'E' || (a) == 'I' || (a) == 'O' || (a) == 'U')
char *nysiis(const char *str) {
size_t len = strlen(str);
char c1, c2, c3;
char *copy = alloca((len + 1) * sizeof(char));
char *code = NULL;
char *p, *cp;
memcpy(copy, str, len+1);
if (!copy) {
return NULL;
}
if (!*copy) {
return calloc(1, sizeof(char));
}
code = calloc(len + 1, sizeof(char));
if (!code) {
return NULL;
}
// Step 1
if (!strncmp(copy, "MAC", 3)) {
copy[1] = 'C';
} else if (!strncmp(copy, "KN", 3)) {
copy[0] = 'N';
} else if (copy[0] == 'K') {
copy[0] = 'C';
} else if (!strncmp(copy, "PH", 2)) {
copy[0] = 'F';
copy[1] = 'F';
} else if (!strncmp(copy, "SCH", 3)) {
copy[1] = 'S';
copy[2] = 'S';
}
// Step 2
c1 = copy[len - 1];
if (c1 == 'E') {
c2 = copy[len - 2];
if (c2 == 'E' || c2 == 'I') {
copy[len - 1] = ' ';
copy[len - 2] = 'Y';
}
} else if (c1 == 'T') {
c2 = copy[len - 2];
if (c2 == 'D' || c2 == 'R' || c2 == 'N') {
copy[len - 1] = ' ';
copy[len - 2] = 'D';
}
} else if (c1 == 'D') {
c2 = copy[len - 2];
if (c2 == 'R' || c2 == 'N') {
copy[len - 1] = ' ';
copy[len - 2] = 'D';
}
}
cp = code;
p = copy;
// Step 3
*(cp++) = toupper(*(p++));
while ((c1 = toupper(*p))) {
if (c1 == ' ') {
break;
}
// Step 5
switch(c1) {
case 'E':
if (toupper(*(p + 1)) == 'V') {
*cp = 'A';
*(++cp) = 'F';
++p;
break;
}
case 'A':
case 'I':
case 'O':
case 'U':
*cp = 'A';
break;
case 'Q':
*cp = 'G';
break;
case 'Z':
*cp = 'S';
break;
case 'M':
*cp = 'N';
break;
case 'K':
if (toupper(*(p + 1)) == 'N') {
*cp = 'N';
} else {
*cp = 'C';
}
break;
case 'S':
if (toupper(*(p + 1)) == 'C' && toupper(*(p + 2)) == 'H') {
*(cp++) = 'S';
*(cp++) = 'S';
*cp = 'S';
p += 2;
} else {
*cp = 'S';
}
break;
case 'P':
if (toupper(*(p + 1)) == 'H') {
*cp = 'F';
*(++cp) = 'F';
p++;
} else {
*cp = 'P';
}
break;
case 'H':
c2 = toupper(*(p + 1));
c3 = toupper(*(p - 1));
if (!ISVOWEL(c2) || !ISVOWEL(c3)) {
if ISVOWEL(c3) {
*cp = 'A';
} else {
*cp = c3;
}
} else {
*cp = 'H';
}
break;
case 'W':
c2 = toupper(*(p - 1));
if (ISVOWEL(c2)) {
*cp = c2;
} else {
*cp = 'W';
}
break;
default:
*cp = toupper(c1);
}
// Step 6
if (*cp != *(cp - 1)) {
cp++;
}
p++;
}
*cp = '\0';
// Step 7
c1 = *(cp - 1);
if (c1 == 'S') {
*(--cp) = '\0';
} else if (c1 == 'Y') {
if (*(cp - 2) == 'A') {
*(--cp) = '\0';
*(--cp) = 'Y';
}
}
// There is no step 8!
// Step 9
if (*(cp - 1) == 'A') {
*(cp - 1) = '\0';
}
return code;
}