transliteration: use double pointers on syllable chain

This commit is contained in:
Vlasta Vesely 2018-06-03 15:59:16 +02:00
parent f2d74710d6
commit 9093211ae3
3 changed files with 21 additions and 41 deletions

View file

@ -3,17 +3,18 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "syllable.h" #include "syllable.h"
#include "utf8.h"
struct syllable *syllable_alloc(const char *data) struct syllable *syllable_alloc(const char *data, unsigned int code)
{ {
struct syllable *ptr = malloc(sizeof(*ptr)); struct syllable *ptr = malloc(sizeof(*ptr));
if (ptr == NULL) if (ptr == NULL)
goto out; goto out;
ptr->data = strdup(data); ptr->data = data != NULL ? strdup(data) : utf8_code_to_string(code);
ptr->code = 0; ptr->code = code;
ptr->prev = NULL; ptr->prev = NULL;
ptr->next = NULL; ptr->next = NULL;
@ -30,17 +31,6 @@ void syllable_drop(struct syllable *ptr)
free(ptr); free(ptr);
} }
struct syllable *syllable_append(struct syllable *tail, const char *data)
{
struct syllable *ptr;
ptr = syllable_alloc(data);
ptr->prev = tail;
tail->next = ptr;
return ptr;
}
unsigned int syllable_chain_length(struct syllable *head) unsigned int syllable_chain_length(struct syllable *head)
{ {
struct syllable *walk = head; struct syllable *walk = head;

View file

@ -10,11 +10,9 @@ struct syllable {
struct syllable *next; struct syllable *next;
}; };
struct syllable *syllable_alloc(); struct syllable *syllable_alloc(const char *data, unsigned int code);
void syllable_drop(struct syllable *syllable); void syllable_drop(struct syllable *syllable);
struct syllable *syllable_append(struct syllable *tail, const char *data);
unsigned int syllable_chain_length(struct syllable *head); unsigned int syllable_chain_length(struct syllable *head);
char *syllable_chain_to_string(struct syllable *head); char *syllable_chain_to_string(struct syllable *head);
void syllable_chain_drop(struct syllable *head); void syllable_chain_drop(struct syllable *head);

View file

@ -28,6 +28,9 @@ static void syllable_modify(struct syllable *syllable, const char *data)
{ {
char buffer[10]; char buffer[10];
if (syllable == NULL)
return;
strcpy(buffer, syllable->data); strcpy(buffer, syllable->data);
buffer[strlen(buffer) - 1] = 0; buffer[strlen(buffer) - 1] = 0;
strcat(buffer, data); strcat(buffer, data);
@ -47,46 +50,35 @@ static void apply_transliteration_filters(struct syllable *head,
} }
} }
char *transliterate_devanagari_to_latin(const char *text, char *transliterate_devanagari_to_latin(const char *devanagari,
const struct transliteration_context *context) const struct transliteration_context *context)
{ {
unsigned int length = strlen(text); struct syllable *head = NULL, *tail = NULL, **indirect = &head;
const char *ptr = text;
const char *end = ptr + length;
char *tmp;
unsigned int code;
struct syllable *head, *tail;
const struct transliteration_letter *letter; const struct transliteration_letter *letter;
const char *ptr = devanagari;
head = syllable_alloc(""); const char *end = ptr + strlen(devanagari);
tail = head; unsigned int code;
char *retval;
while (ptr < end) { while (ptr < end) {
code = utf8_unpack_char(ptr); code = utf8_unpack_char(ptr);
ptr += utf8_char_length(code); ptr += utf8_char_length(code);
letter = find_letter_by_code(code, context->table); letter = find_letter_by_code(code, context->table);
if (letter != NULL) { if (letter && letter->flags & FLAG_MODIFIER) {
if (letter->flags & FLAG_REGULAR) {
tail = syllable_append(tail, letter->data);
tail->code = code;
} else if (letter->flags & FLAG_MODIFIER) {
syllable_modify(tail, letter->data); syllable_modify(tail, letter->data);
}
continue; continue;
} }
tmp = utf8_code_to_string(code); *indirect = syllable_alloc(letter ? letter->data : NULL, code);
tail = syllable_append(tail, tmp); tail = *indirect;
free(tmp); indirect = &(*indirect)->next;
} }
apply_transliteration_filters(head, context->filters); apply_transliteration_filters(head, context->filters);
tmp = syllable_chain_to_string(head); retval = syllable_chain_to_string(head);
syllable_chain_drop(head); syllable_chain_drop(head);
return tmp; return retval;
} }