| @@ -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 { | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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 | |||