2018-04-25 19:30:49 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
|
2018-04-25 16:13:34 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "transliteration.h"
|
|
|
|
#include "syllable.h"
|
|
|
|
#include "utf8.h"
|
|
|
|
|
2018-04-29 08:21:46 +02:00
|
|
|
static const struct transliteration_letter *find_letter_by_code(unsigned int c,
|
2018-04-25 18:54:47 +02:00
|
|
|
const struct transliteration_letter *table)
|
2018-04-25 18:11:56 +02:00
|
|
|
{
|
2018-04-25 18:54:47 +02:00
|
|
|
const struct transliteration_letter *walk = table;
|
|
|
|
|
|
|
|
if (c == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (walk->code != 0) {
|
|
|
|
if (c == walk->code)
|
|
|
|
return walk;
|
|
|
|
walk++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-04-27 18:58:07 +02:00
|
|
|
static void syllable_modify(struct syllable *syllable, const char *data)
|
2018-04-25 18:54:47 +02:00
|
|
|
{
|
2018-04-27 18:58:07 +02:00
|
|
|
char buffer[10];
|
2018-04-25 18:54:47 +02:00
|
|
|
|
2018-06-03 15:59:16 +02:00
|
|
|
if (syllable == NULL)
|
|
|
|
return;
|
|
|
|
|
2018-04-27 18:58:07 +02:00
|
|
|
strcpy(buffer, syllable->data);
|
|
|
|
buffer[strlen(buffer) - 1] = 0;
|
|
|
|
strcat(buffer, data);
|
2018-04-25 18:11:56 +02:00
|
|
|
|
2018-04-27 18:58:07 +02:00
|
|
|
free(syllable->data);
|
|
|
|
syllable->data = strdup(buffer);
|
2018-04-25 18:11:56 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 18:14:39 +02:00
|
|
|
static void apply_transliteration_filters(struct syllable *head,
|
|
|
|
const transliteration_filter_t *filters)
|
|
|
|
{
|
|
|
|
const transliteration_filter_t *filter = filters;
|
|
|
|
|
|
|
|
while (*filter) {
|
|
|
|
(*filter)(head);
|
|
|
|
filter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-03 15:59:16 +02:00
|
|
|
char *transliterate_devanagari_to_latin(const char *devanagari,
|
2018-05-20 08:29:33 +02:00
|
|
|
const struct transliteration_context *context)
|
2018-04-25 16:13:34 +02:00
|
|
|
{
|
2018-06-03 15:59:16 +02:00
|
|
|
struct syllable *head = NULL, *tail = NULL, **indirect = &head;
|
2018-04-25 18:54:47 +02:00
|
|
|
const struct transliteration_letter *letter;
|
2018-06-03 15:59:16 +02:00
|
|
|
const char *ptr = devanagari;
|
|
|
|
const char *end = ptr + strlen(devanagari);
|
|
|
|
unsigned int code;
|
|
|
|
char *retval;
|
2018-04-25 16:13:34 +02:00
|
|
|
|
|
|
|
while (ptr < end) {
|
2018-04-29 14:12:41 +02:00
|
|
|
code = utf8_unpack_char(ptr);
|
|
|
|
ptr += utf8_char_length(code);
|
2018-04-25 16:13:34 +02:00
|
|
|
|
2018-04-29 14:12:41 +02:00
|
|
|
letter = find_letter_by_code(code, context->table);
|
2018-06-03 15:59:16 +02:00
|
|
|
if (letter && letter->flags & FLAG_MODIFIER) {
|
|
|
|
syllable_modify(tail, letter->data);
|
2018-04-25 18:54:47 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-06-03 15:59:16 +02:00
|
|
|
*indirect = syllable_alloc(letter ? letter->data : NULL, code);
|
|
|
|
tail = *indirect;
|
|
|
|
indirect = &(*indirect)->next;
|
2018-04-25 16:13:34 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 18:14:39 +02:00
|
|
|
apply_transliteration_filters(head, context->filters);
|
|
|
|
|
2018-06-03 15:59:16 +02:00
|
|
|
retval = syllable_chain_to_string(head);
|
2018-05-18 10:09:06 +02:00
|
|
|
syllable_chain_drop(head);
|
|
|
|
|
2018-06-03 15:59:16 +02:00
|
|
|
return retval;
|
2018-04-25 16:13:34 +02:00
|
|
|
}
|