diff --git a/src/include/espeak-ng/espeak_ng.h b/src/include/espeak-ng/espeak_ng.h index f8ddc58e..c9d87835 100644 --- a/src/include/espeak-ng/espeak_ng.h +++ b/src/include/espeak-ng/espeak_ng.h @@ -60,6 +60,7 @@ typedef enum { /* eSpeak NG 1.49.2 */ ENS_UNKNOWN_PHONEME_FEATURE = 0x10000FFF, + ENS_UNKNOWN_TEXT_ENCODING = 0x100010FF, } espeak_ng_STATUS; typedef enum { diff --git a/src/libespeak-ng/encoding.c b/src/libespeak-ng/encoding.c index 63673976..5f651315 100644 --- a/src/libespeak-ng/encoding.c +++ b/src/libespeak-ng/encoding.c @@ -52,6 +52,8 @@ espeak_ng_EncodingFromName(const char *encoding) struct espeak_ng_TEXT_DECODER_ { + const char *current; + const char *end; }; espeak_ng_TEXT_DECODER * @@ -60,6 +62,8 @@ create_text_decoder(void) espeak_ng_TEXT_DECODER *decoder = malloc(sizeof(espeak_ng_TEXT_DECODER)); if (!decoder) return NULL; + decoder->current = NULL; + decoder->end = NULL; return decoder; } @@ -69,14 +73,43 @@ destroy_text_decoder(espeak_ng_TEXT_DECODER *decoder) if (decoder) free(decoder); } +static int +initialize_encoding(espeak_ng_TEXT_DECODER *decoder, + espeak_ng_ENCODING encoding) +{ + switch (encoding) + { + case ESPEAKNG_ENCODING_US_ASCII: + break; + default: + return 0; + } + return 1; +} + +espeak_ng_STATUS +text_decoder_decode_string(espeak_ng_TEXT_DECODER *decoder, + const char *string, + int length, + espeak_ng_ENCODING encoding) +{ + if (!initialize_encoding(decoder, encoding)) + return ENS_UNKNOWN_TEXT_ENCODING; + + decoder->current = string; + decoder->end = string + length; + return ENS_OK; +} + int text_decoder_eof(espeak_ng_TEXT_DECODER *decoder) { - return 1; + return decoder->current == decoder->end; } uint32_t text_decoder_getc(espeak_ng_TEXT_DECODER *decoder) { - return 0; + uint8_t c = *decoder->current++ & 0xFF; + return (c >= 0x80) ? 0xFFFD : c; } diff --git a/src/libespeak-ng/encoding.h b/src/libespeak-ng/encoding.h index de57ef59..830344df 100644 --- a/src/libespeak-ng/encoding.h +++ b/src/libespeak-ng/encoding.h @@ -30,6 +30,12 @@ create_text_decoder(void); void destroy_text_decoder(espeak_ng_TEXT_DECODER *decoder); +espeak_ng_STATUS +text_decoder_decode_string(espeak_ng_TEXT_DECODER *decoder, + const char *string, + int length, + espeak_ng_ENCODING encoding); + int text_decoder_eof(espeak_ng_TEXT_DECODER *decoder); diff --git a/src/libespeak-ng/error.c b/src/libespeak-ng/error.c index c1c5ceb6..b83f2214 100644 --- a/src/libespeak-ng/error.c +++ b/src/libespeak-ng/error.c @@ -135,6 +135,9 @@ espeak_ng_GetStatusCodeMessage(espeak_ng_STATUS status, case ENS_UNKNOWN_PHONEME_FEATURE: strncpy0(buffer, "The phoneme feature is not recognised", length); break; + case ENS_UNKNOWN_TEXT_ENCODING: + strncpy0(buffer, "The text encoding is not supported", length); + break; default: if ((status & ENS_GROUP_MASK) == ENS_GROUP_ERRNO) strerror_r(status, buffer, length); diff --git a/tests/encoding.c b/tests/encoding.c index a47c26b7..185c9bd2 100644 --- a/tests/encoding.c +++ b/tests/encoding.c @@ -35,7 +35,6 @@ test_unbound_text_decoder() assert(decoder != NULL); assert(text_decoder_eof(decoder) == 1); - assert(text_decoder_getc(decoder) == 0); destroy_text_decoder(decoder); } @@ -49,6 +48,13 @@ test_unknown_encoding() assert(espeak_ng_EncodingFromName("") == ESPEAKNG_ENCODING_UNKNOWN); assert(espeak_ng_EncodingFromName("abcxyz") == ESPEAKNG_ENCODING_UNKNOWN); assert(espeak_ng_EncodingFromName("US") == ESPEAKNG_ENCODING_UNKNOWN); // wrong case + + espeak_ng_TEXT_DECODER *decoder = create_text_decoder(); + + assert(text_decoder_decode_string(decoder, "aG\x92\xA0\xDE", 5, ESPEAKNG_ENCODING_UNKNOWN) == ENS_UNKNOWN_TEXT_ENCODING); + assert(text_decoder_eof(decoder) == 1); + + destroy_text_decoder(decoder); } void @@ -66,6 +72,23 @@ test_us_ascii_encoding() assert(espeak_ng_EncodingFromName("IBM367") == ESPEAKNG_ENCODING_US_ASCII); assert(espeak_ng_EncodingFromName("cp367") == ESPEAKNG_ENCODING_US_ASCII); assert(espeak_ng_EncodingFromName("csASCII") == ESPEAKNG_ENCODING_US_ASCII); + + espeak_ng_TEXT_DECODER *decoder = create_text_decoder(); + + assert(text_decoder_decode_string(decoder, "aG\x92\xA0\xDE", 5, ESPEAKNG_ENCODING_US_ASCII) == ENS_OK); + assert(text_decoder_eof(decoder) == 0); + assert(text_decoder_getc(decoder) == 'a'); + assert(text_decoder_eof(decoder) == 0); + assert(text_decoder_getc(decoder) == 'G'); + assert(text_decoder_eof(decoder) == 0); + assert(text_decoder_getc(decoder) == 0xFFFD); + assert(text_decoder_eof(decoder) == 0); + assert(text_decoder_getc(decoder) == 0xFFFD); + assert(text_decoder_eof(decoder) == 0); + assert(text_decoder_getc(decoder) == 0xFFFD); + assert(text_decoder_eof(decoder) == 1); + + destroy_text_decoder(decoder); } int