%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file File and memory encodings for characters. CRT on Windows: Optional, disabling CRT degrades performance. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif /** Encodings for text files. */ enum { /** ASCII character set. */ DK4_FILE_ENCODING_ASCII = 0, /** ANSII encoding (used ie on Windows). */ DK4_FILE_ENCODING_ANSI , /** UTF-8 encoding used on Linux and Unix. */ DK4_FILE_ENCODING_UTF8 , /** UTF-16 encoding, least significant byte first. */ DK4_FILE_ENCODING_UTF16_LE , /** UTF-16 encoding, most significant byte first. */ DK4_FILE_ENCODING_UTF16_BE , /** 32-bit unicode characters, least significant byte first. */ DK4_FILE_ENCODING_32_LE , /** 32-bit unicode characters, most significant byte first. */ DK4_FILE_ENCODING_32_BE }; /** Encoding for characters in memory. */ enum { /** ASCII character set (0 to 255) in ISO-LATIN-8859-1. */ DK4_ENCODING_ASCII = DK4_FILE_ENCODING_ASCII, /** ANSII encoding (used ie on Windows). */ DK4_ENCODING_ANSI = DK4_FILE_ENCODING_ANSI, /** UTF-8 encoding used on Linux and Unix. */ DK4_ENCODING_UTF8 = DK4_FILE_ENCODING_UTF8, #if DK4_WORDS_BIGENDIAN /** UTF-16 encoding. */ DK4_ENCODING_UTF16 = DK4_FILE_ENCODING_UTF16_BE, /** 32-bit unicode characters. */ DK4_ENCODING_32 = DK4_FILE_ENCODING_32_BE #else /** UTF-16 encoding. */ DK4_ENCODING_UTF16 = DK4_FILE_ENCODING_UTF16_LE, /** 32-bit unicode characters. */ DK4_ENCODING_32 = DK4_FILE_ENCODING_32_LE #endif }; #ifdef __cplusplus extern "C" { #endif /** Find encoding by name. @param encptr Pointer to result variable for encoding. @param bomptr Pointer to result variable for BOM writing. @param src Source text containing encoding name. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if encptr or src is NULL, - DK4_E_BUFFER_TOO_SMALL
if the text is too long to create a local copy for modification, or - DK4_E_SYNTAX
if invalid encoding, options or encoding/option combinations are specified. */ int dk4enc_find(int *encptr, int *bomptr, const dkChar *src, dk4_er_t *erp); #ifdef __cplusplus } #endif %% module #include "dk4enc.h" #include "dk4mem.h" #include "dk4strd.h" /** Encoding names in variations. */ static const dkChar * const dk4enc_encoding_names[] = { $!string-table macro=dkT # # 0 ... 1 ASCII # plain ascii # # 2 ANSI, used on Windows systems # ansi # # 3 ... 4 UTF-8 # utf-8 utf8 # # 5 ... 6 UTF-16, systems native endianness # utf-16 utf16 # # 7 ... 12 UTF-16LE # utf-16-le utf-16le utf16le utf-16-lsb utf-16lsb utf16lsb # # 13 ... 18 UTF-16BE # utf-16-be utf-16be utf16be utf-16-msb utf-16msb utf16msb # # 19 32 bit in systems native endianness # c32 # # 20 ... 23 32 bit little endian # c32-le c32le c32-lsb c32lsb # # 24 ... 27 32 bit big endian # c32-be c32be c32-msb c32msb # # 28 ... 34 Backward compatibility # utf-16.msb utf-16.lsb uc32 uc32.msb uc32.lsb iso-latin-1 iso-8859-1 $!end }; /** Keywords for further options. */ static const dkChar * const dk4enc_option_keywords[] = { $!string-table macro=dkT le lsb be msb bom nobom $!end }; int dk4enc_find(int *encptr, int *bomptr, const dkChar *src, dk4_er_t *erp) { dkChar buf[64]; /* Private copy for modification */ dkChar *p1; /* Start of text */ dkChar *p2; /* Start of options */ int res = 0; /* Array index */ int back = 0; /* Function result */ int ae = 0; /* Flag: Allow ending specification */ int enc = 0; /* Encoding found */ int bom = 0; /* Flag: BOM keyword found */ int bom_f = 0; /* Flag: BOM information found */ if ((NULL != encptr) && (NULL != src)) { if (0 != dk4str_cpy_s(buf, DK4_SIZEOF(buf,dkChar), src, erp)) { p1 = dk4str_start(buf, NULL); if (NULL != p1) { p2 = dk4str_chr(buf, dkT(',')); if (NULL == p2) { p2 = dk4str_chr(buf, dkT('.')); } if (NULL != p2) { *(p2++) = dkT('\0'); p2 = dk4str_start(p2, NULL); } dk4str_normalize(p1, NULL); switch (dk4str_array_index(dk4enc_encoding_names, p1, 0)) { case 0: case 1: case 33: case 34: { enc = DK4_FILE_ENCODING_ASCII; back = 1; } break; case 2: { enc = DK4_FILE_ENCODING_ANSI; back = 1; } break; case 3: case 4: { enc = DK4_FILE_ENCODING_UTF8; back = 1; } break; case 5: case 6: { enc = DK4_ENCODING_UTF16; ae = 1; back = 1; bom = 1; } break; case 7: case 8: case 9: case 10: case 11: case 12: case 29: { enc = DK4_FILE_ENCODING_UTF16_LE; back = 1; bom = 1; } break; case 13: case 14: case 15: case 16: case 17: case 18: case 28: { enc = DK4_FILE_ENCODING_UTF16_BE; back = 1; bom = 1; } break; case 19: case 30: { enc = DK4_ENCODING_32; ae = 1; back = 1; bom = 1; } break; case 20: case 21: case 22: case 23: case 32: { enc = DK4_FILE_ENCODING_32_LE; back = 1; bom = 1; } break; case 24: case 25: case 26: case 27: case 31: { enc = DK4_FILE_ENCODING_32_BE; back = 1; bom = 1; } break; default: { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } break; } if (1 == back) { while (NULL != p2) { p1 = dk4str_chr(p2, dkT(',')); if (NULL != p1) { *(p1++) = dkT('\0'); p1 = dk4str_start(p1,NULL); } dk4str_normalize(p2, NULL); switch (res = dk4str_array_index(dk4enc_option_keywords, p2, 0)) { case 0: case 1: case 2: case 3: { if (0 != ae) { switch (enc) { case DK4_ENCODING_UTF16: { enc = ( ((2 == res) || (3 == res)) ? DK4_FILE_ENCODING_UTF16_BE : DK4_FILE_ENCODING_UTF16_LE ); } break; case DK4_ENCODING_32: { enc = ( ((2 == res) || (3 == res)) ? DK4_FILE_ENCODING_32_BE : DK4_FILE_ENCODING_32_LE ); } break; } ae = 0; } else { back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } break; case 4: { switch (enc) { case DK4_FILE_ENCODING_UTF8: case DK4_FILE_ENCODING_UTF16_LE: case DK4_FILE_ENCODING_UTF16_BE: case DK4_FILE_ENCODING_32_LE: case DK4_FILE_ENCODING_32_BE: { bom = 1; bom_f = 1; } break; default: { back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } break; } } break; case 5: { bom = 0; bom_f = 1; } break; default: { back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } break; } p2 = p1; } } } else { /* ERROR: Empty string */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } if (NULL != encptr) { *encptr = enc; } if (0 != bom_f) { if (NULL != bomptr) { *bomptr = bom; } } return back; }