// =======================================================================
#define MAKEDONIZACIJA
void utf8ascii (const char* input, char* output){
// =======================================================================
// OPTIMIZOVANA VERZIJA 2: KOD ZA MEŠOVITA SLOVA (BRZA MATEMATIKA)
// =======================================================================
const char C1[] PROGMEM = "CueaaaaceeeiiiAAEaAooouuyOUcPYPfaiounNao?<>//!<>";
const char C3[] PROGMEM = "AAAAAAACEEEEIIIIDNOOOOOx0UUUUYTsaaaaaaaceeeeiiiidnooooo/ouuuuyty";
const char C4[] PROGMEM = "AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlL";
const char C5[] PROGMEM = "lLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzs";
const char CE[] PROGMEM = "????''A'EII?O?YOiAVGDEZITIKLMNXOPR?STYFHPOIYaeiiuavgdezitiklmnxo";
const char CF[] PROGMEM = "prsstyfhpoiyoyoK";
#ifdef MAKEDONIZACIJA
const char D0[] PROGMEM = "EJDGJDIJJLNCKIUDABVGDEZZIJKLMNOPRSTUFHCCSSYIJEJJabvgdezzijklmnop";
const char D1[] PROGMEM = "rstufhccssyijejjejdgjdijjlnckiud";
#define slovo_j 'j'
#define slovo_J 'J'
#else
const char D0[] PROGMEM = "EYDGYSIYJLNCKIUDABVGDEZZIYKLMNOPRSTUFHCCSSWIYEYYabvgdezziyklmnop";
const char D1[] PROGMEM = "rstufhccsswiyeyyeydgydiyjlnckiud";
#define slovo_j 'y'
#define slovo_J 'Y'
#endif
unsigned char c,l;
unsigned char up_c=0, up_l=0;
char case_offset = 0;
bool all_caps = true;
bool bug_jat = false;
bool l_uc,l_lc,c_uc,c_lc;
int j=0; int i=0,
last_l=0, last_j=0,
curr_l=0, curr_j=0,
first_l=0, first_j=0;
for (; input[i]!='\0'; i++) {
unsigned char a = (unsigned char)input[i];
if (all_caps && a>='a' && a<='z') all_caps=false;
if (a <= 0x7F) output[j++] = a;
else if (a < 0xB0) output[j++] = C1[a-128];
else if (a == 0xC2) {
if (i > 1 && input[i-1] == 0x83)
switch ((unsigned char)input[++i]){
case 0x89: output[j-1] = 'E'; break; // Mojibake É
case 0x81: output[j-1] = 'A'; break; // Mojibake Á
case 0x96: output[j-1] = 'O'; break; // Mojibake Ö
case 0x9C: output[j-1] = 'U'; break; // Mojibake Ü
case 0xA0: output[j-1] = 'a'; break; // Mojibake à
case 0xA1: output[j-1] = 'a'; break; // Mojibake á
case 0xA2: output[j-1] = 'a'; break; // Mojibake â
case 0xA7: output[j-1] = 'c'; break; // Mojibake ç
case 0xA6: output[j-1] = 'c'; break; // Popravlja Ň -> ć/c
case 0xA8: output[j-1] = 'e'; break; // Mojibake è
case 0xA9: output[j-1] = 'e'; break; // Mojibake é
case 0xAD: output[j-1] = 'i'; break; // Mojibake í
case 0xB1: output[j-1] = 'n'; break; // Mojibake ñ
case 0xB3: output[j-1] = 'o'; break; // Mojibake à
case 0xBC: output[j-1] = 'u'; break; // Mojibake à
case 0xAB: output[j-1] = 'e'; break; // Popravlja Noël (Noal -> Noel)
case 0xB8: output[j-1] = 'o'; break; // Popravlja Jørgen i Søren (Jargen/Saren -> Jorgen/Soren)
case 0xB6: output[j-1] = 'o'; break; // Popravlja Nyögő (Nyaga -> Nyogo)
}
else if (i > 1 && input[i-1] == 0x84)
switch ((unsigned char)input[++i]){
case 0xA0: output[j-1] = 'c'; break; // Popravlja Ň -> ć/c
case 0x8C: output[j-1] = 'c'; break; // Popravlja ÅŒ -> č/c
}else if (i > 1 && input[i-1] == 0x85)
switch ((unsigned char)input[++i]){
case 0xA1: output[j-1] = 's'; break; // Popravlja Å¡ -> š/s
case 0xBE: output[j-1] = 'z'; break; // Popravlja ž -> ž/z
case 0xA0: output[j-1] = 'S'; break; // Popravlja Å -> Š/S
case 0xBD: output[j-1] = 'Z'; break; // Popravlja Ž -> Ž/Z
case 0x94: output[j-1] = 'D'; break;
}
else if (i > 3 && input[i-4] == 0xA2)
switch ((unsigned char)input[++i]){
case 0xAC: output[--j-1] = 'e'; break; // Popravlja € -> e
}
else
switch ((unsigned char)input[++i]){
case 0x80: output[j++] = 'e'; break; // €
case 0x8A: output[j++] = 'S'; break; // Š
case 0x8C: output[j++] = 'O'; output[j++] = 'e'; break; // Œ
case 0x8E: output[j++] = 'z'; break; // Ž
case 0x99: output[j++] = '['; output[j++] = 'T'; output[j++] = 'M'; output[j++] = ']'; break; // ™
case 0x9A: output[j++] = 's'; break; // š
case 0x9C: output[j++] = 'O'; output[j++] = 'e'; break; // œ
case 0xA2: output[j++] = 'c'; break; // ¢
case 0x9F: case 0xA5: output[j++] = 'Y'; break; // Ÿ,¥
case 0xA0: output[j++] = ' '; break; // No-break Space
case 0xA9: if (input[i-2]==0x82) j--;
output[j++] = '('; output[j++] = 'C'; output[j++] = ')'; break; // ©
case 0xAE: if (input[i-2]==0x82) j--;
output[j++] = '('; output[j++] = 'R'; output[j++] = ')'; break; // ®
}
} else if (a == 0xE2)
if (i > 1 && input[i-1] == 0x84)
switch ((unsigned char)input[++i]){
case 0x80:
switch ((unsigned char)input[++i]){
case 0x98: output[j-1] = 'd'; output[j++] = 'j';break; // Popravlja Å• -> đ/d (Malo)
} break;
}
else {
unsigned char u = (unsigned char)input[++i];
curr_j = j;
if (j>0) up_l = output[j-1] & 0b11011111;
switch (a) {
case 0xC3:
c = C3[u-128];
output[j++] = c;
if (u == 0x86 || u == 0xA6)
output[j++] = 'e'-case_offset; // Æ,æ Letter AE
else if (u == 0x9E || u == 0xBE)
output[j++] = 'h'-case_offset; // Þ,þ Letter Thorn
break;
case 0xC4:
c = C4[u-128];
output[j++] = c;
if (u == 0x90 || u == 0x91 || u == 0xB2 || u == 0xB3)
output[j++] = 'j'-case_offset; // Đ,đ,IJ,ij - Dj,dj,Ij,ij // Letters D With Stroke & Ligature Ij
break;
case 0xC5:
c = C5[u-128];
output[j++] = c;
if (u == 0x98 || u == 0x99)
output[j++] = 'z'-case_offset; // Ř,ř - Rz,rz
else if (u == 0x92 || u == 0x93)
output[j++] = 'e'-case_offset; // Œ,œ - Oe,oe // Ligature Oe
break;
case 0xCE:
c = CE[u-128];
up_c = c & 0b11011111;
if ((up_l=='M') && (up_c=='P')) output[j-1] = 'B'+output[j-1]-up_l;
else if ((up_l=='N') && (up_c=='T')) output[j-1] = 'D'+output[j-1]-up_l;
else{
output[j++] = c;
if (u == 0x98 || u == 0xB8) output[j++] = 'h'; // Θ,θ - Th,th // Letter Theta
else if (u == 0xA8) output[j++] = 's'; // Ψ - Ps,ps // Capital Letter Psi
}
break;
case 0xCF:
c = CF[u-128];
up_c = c & 0b11011111;
if (u < 0x90) {
if ((up_l=='M') && (up_c=='P')) output[j-1] = 'B'+output[j-1]-up_l;
else if ((up_l=='N') && (up_c=='T')) output[j-1] = 'D'+output[j-1]-up_l;
else{
output[j++] = c;
if (u == 0x88) output[j++] = 's'; // ψ - ps // Small Letter Psi
}
}
break;
case 0xD0:
c = D0[u-128];
up_c = c & 0b11011111;
if (bug_jat){
if (up_c==slovo_J) j--;
else if (up_c=='A' || up_c=='E' || up_c=='I' || up_c=='O' || up_c=='U') output[j-1] = slovo_j;
} bug_jat=false;
if ((up_l=='E' || up_l=='I' || up_l=='A'/* || up_l=='O' || up_l=='U'*/) && (up_c=='E' || up_c=='I'))
output[j++] = slovo_j;
if (u != 0xAC || up_l == 'L' || up_l == 'N') output[j++] = c; //not a ь - Soft Sign
switch (u){
case 0xAA: bug_jat=true; break; // Ъ - Hard Sign
case 0x81: output[j++] = 'o'; break; // Ё - Yo
case 0x84: output[j++] = 'e'; break; // Є - Ye //Ukrainian Ie
case 0x85: output[j++] = 'z'; break; // Ѕ - Dz //Macedonian Dze
case 0x87: output[j++] = 'i'; break; // Ї - Yi //Ukrainian Yi
case 0x8F: output[j++] = 'z';
output[j++] = 'h'; break; // Џ - Dz //Serbian Letter Dzhe
case 0xAE: output[j++] = 'u'; break; // Ю - Yu
case 0xAF: output[j++] = 'a'; break; // Я - Ya
case 0xA9: output[j++] = 'c'; // Щ - Sch
case 0x96: case 0xA7: case 0xA8: case 0xB6:
output[j++] = 'h'; break; // Ж,Ч,Ш,ж - Zh,Ch,Sh,zh
case 0x82: case 0x83: case 0x89: case 0x8A: case 0x8C:
output[j++] = 'j'; break; // Ђ,Ѓ,Љ,Њ,Ќ - Dj,Gj,Lj,Nj,Kj // SR & MK Letters
} break;
case 0xD1:
c = D1[u-128];
up_c = c & 0b11011111;
if (u < 0xA0) {
if (bug_jat){
if (up_c==slovo_J) j--;
else if (up_c=='A' || up_c=='E' || up_c=='I' || up_c=='O' || up_c=='U') output[j-1] = slovo_j;
} bug_jat=false;
if ((up_l=='E' || up_l=='I' || up_l=='A'/* || up_l=='O' || up_l=='U'*/) && (up_c=='E' || up_c=='I'))
output[j++] = slovo_j;
if (u != 0x8C || up_l == 'L' || up_l == 'N') output[j++] = c; //not a ь - Soft Sign
}switch (u){
case 0x8A: bug_jat=true; break; // ъ - Hard Sign
case 0x8E: output[j++] = 'u'; break; // ю - yu
case 0x8F: output[j++] = 'a'; break; // я - ya
case 0x91: output[j++] = 'o'; break; // ё - yo
case 0x94: output[j++] = 'e'; break; // є - ye
case 0x95: output[j++] = 'z'; break; // ѕ - dz
case 0x97: output[j++] = 'i'; break; // ї - yi
case 0x9F: output[j++] = 'z';
output[j++] = 'h'; break; // џ - dz //Serbian Letter Dzhe
case 0x89: output[j++] = 'c'; // щ - sch
case 0x87: case 0x9B: case 0x88:
output[j++] = 'h'; break; // ч,ћ,ш - ch,ch,sh
case 0x92: case 0x93: case 0x99: case 0x9A: case 0x9C:
output[j++] = 'j'; break; // ђ,ѓ,љ,њ,ќ //dj,gj,lj,nj,kj // SR & MK Letters
} break;
}
if (all_caps && curr_j>0 && c>='a' && c<='z') all_caps=false;
}
}
if (all_caps) for(int k=0; k<j; k++) if (output[k]>='a' && output[k]<='z')output[k]&=0b1011111;
output[j] = '\0';
}
static char input[256],output[256];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
}
void loop() {
if (Serial.available()) {
int len = Serial.readBytesUntil('\n', (char*) input, sizeof(input)-1);
input[len] = '\0';
// Uklanjanje \r ako postoji
if (len > 0 && input[len-1] == '\r') {
input[len-1] = '\0';
}
utf8ascii(input, output);
//Serial.println();
//Serial.println(input);
//Serial.println();
Serial.println(output);
}
delay(10);
}