1965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include <stdint.h> 2965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include <inttypes.h> 3965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include <stdlib.h> 4965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include <string.h> 5965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include <stdio.h> 6965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#include "opcodes.h" 7965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 8965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#ifndef M3 9965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#define M3 0 10965977c3facb05dc36068fdc5cdfaaac4630f40eflorian#endif 11965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 12965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* The abstracted result of an CU12 insn */ 13965977c3facb05dc36068fdc5cdfaaac4630f40efloriantypedef struct { 14965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint64_t addr1; // target 15965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint64_t len1; 16965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint64_t addr2; // source 17965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint64_t len2; 18965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint32_t cc; 19965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} cu12_t; 20965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 21965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* Define various input buffers. */ 22965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 23965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* 1-byte UTF-8 character */ 24965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint8_t pattern1[] = { 25965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x00, 0x01, 0x02, 0x03 26965977c3facb05dc36068fdc5cdfaaac4630f40eflorian}; 27965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 28965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* 2-byte UTF-8 character */ 29965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint8_t pattern2[] = { 30965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x80, 31965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x81, 32965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x82, 33965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x83, 34965977c3facb05dc36068fdc5cdfaaac4630f40eflorian}; 35965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 36965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* 3-byte UTF-8 character */ 37965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint8_t pattern3[] = { 38965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x80, 0x80, 39965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x80, 0x81, 40965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x80, 0x82, 41965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x80, 0x83, 42965977c3facb05dc36068fdc5cdfaaac4630f40eflorian}; 43965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 44965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* 4-byte UTF-8 character */ 45965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint8_t pattern4[] = { 46965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x80, 0x80, 47965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x80, 0x81, 48965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x80, 0x82, 49965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x80, 0x83, 50965977c3facb05dc36068fdc5cdfaaac4630f40eflorian}; 51965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 52965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 53965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* Mixed bytes */ 54965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint8_t mixed[] = { 55965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x01, // 1 byte 56965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc3, 0x80, // 2 bytes 57965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x12, // 1 byte 58965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x90, 0x93, // 3 bytes 59965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x23, // 1 byte 60965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 61965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x34, // 1 byte 62965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc4, 0x8c, // 2 bytes 63965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x91, 0x94, // 3 bytes 64965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc5, 0x8a, // 2 bytes 65965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 66965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc5, 0x8a, // 2 bytes 67965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x91, 0x94, // 3 bytes 68965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 69965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x91, 0x94, // 3 bytes 70965977c3facb05dc36068fdc5cdfaaac4630f40eflorian}; 71965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 72965977c3facb05dc36068fdc5cdfaaac4630f40eflorian/* This is the buffer for the converted bytes. */ 73965977c3facb05dc36068fdc5cdfaaac4630f40eflorianuint16_t buff[1000]; /* Large so we con'don't have to worry about it */ 74965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 75965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 76965977c3facb05dc36068fdc5cdfaaac4630f40eflorianstatic cu12_t 77965977c3facb05dc36068fdc5cdfaaac4630f40efloriando_cu12(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len) 78965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 79965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int cc = 42; 80965977c3facb05dc36068fdc5cdfaaac4630f40eflorian cu12_t regs; 81965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 82965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* build up the register pairs */ 83965977c3facb05dc36068fdc5cdfaaac4630f40eflorian register uint8_t *source asm("4") = src; 84965977c3facb05dc36068fdc5cdfaaac4630f40eflorian register uint64_t source_len asm("5") = src_len; 85965977c3facb05dc36068fdc5cdfaaac4630f40eflorian register uint16_t *dest asm("2") = dst; 86965977c3facb05dc36068fdc5cdfaaac4630f40eflorian register uint64_t dest_len asm("3") = dst_len; 87965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 88965977c3facb05dc36068fdc5cdfaaac4630f40eflorian asm volatile( 89965977c3facb05dc36068fdc5cdfaaac4630f40eflorian CU12(M3,2,4) 90965977c3facb05dc36068fdc5cdfaaac4630f40eflorian "ipm %2\n\t" 91965977c3facb05dc36068fdc5cdfaaac4630f40eflorian "srl %2,28\n\t" 92965977c3facb05dc36068fdc5cdfaaac4630f40eflorian : "+d"(dest), "+d"(source), "=d"(cc), 93965977c3facb05dc36068fdc5cdfaaac4630f40eflorian "+d"(source_len), "+d"(dest_len) 94965977c3facb05dc36068fdc5cdfaaac4630f40eflorian : 95965977c3facb05dc36068fdc5cdfaaac4630f40eflorian : "memory", "cc"); 96965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 97965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Capture register contents at end of cu12 */ 98965977c3facb05dc36068fdc5cdfaaac4630f40eflorian regs.addr1 = (uint64_t)dest; 99965977c3facb05dc36068fdc5cdfaaac4630f40eflorian regs.len1 = dest_len; 100965977c3facb05dc36068fdc5cdfaaac4630f40eflorian regs.addr2 = (uint64_t)source; 101965977c3facb05dc36068fdc5cdfaaac4630f40eflorian regs.len2 = source_len; 102965977c3facb05dc36068fdc5cdfaaac4630f40eflorian regs.cc = cc; 103965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 104965977c3facb05dc36068fdc5cdfaaac4630f40eflorian return regs; 105965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 106965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 107965977c3facb05dc36068fdc5cdfaaac4630f40eflorianvoid 108965977c3facb05dc36068fdc5cdfaaac4630f40eflorianrun_test(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len) 109965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 110965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int i; 111965977c3facb05dc36068fdc5cdfaaac4630f40eflorian cu12_t result; 112965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 113965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("UTF8: "); 114965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (src_len == 0) 115965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" <none>"); 116965977c3facb05dc36068fdc5cdfaaac4630f40eflorian else { 117965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for(i = 0; i < src_len; ++i) 118965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" %02x", src[i]); 119965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 120965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n"); 121965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 122965977c3facb05dc36068fdc5cdfaaac4630f40eflorian result = do_cu12(dst, dst_len, src, src_len); 123965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 124965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Write out the converted byte, if any 125965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("UTF16: "); 126965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (dst_len - result.len1 == 0) 127965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" <none>"); 128965977c3facb05dc36068fdc5cdfaaac4630f40eflorian else { 129965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint64_t num_bytes = dst_len - result.len1; 130965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 131965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The number of bytes that were written must be divisible by 2 */ 132965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (num_bytes % 2 != 0) 133965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fprintf(stderr, "*** number of bytes is not a multiple of 2\n"); 134965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 135965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i < num_bytes / 2; i++) { 136965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" %04x", dst[i]); 137965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 138965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 139965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n"); 140965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 141965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" cc = %d\n", result.cc); 142965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (dst != NULL) 143965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" dst address difference: %"PRId64, result.addr1 - (uint64_t)dst); 144965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" dst len: %"PRId64"\n", result.len1); 145965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 146965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (src != NULL) 147965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" src address difference: %"PRId64, result.addr2 - (uint64_t)src); 148965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf(" src len: %"PRId64"\n", result.len2); 149965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 150965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 151965977c3facb05dc36068fdc5cdfaaac4630f40eflorian// Test conversion of a one-byte character 152965977c3facb05dc36068fdc5cdfaaac4630f40eflorianvoid convert_1_byte(void) 153965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 154965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int i; 155965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 156965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("===== Conversion of a one-byte character =====\n"); 157965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 158965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters -----\n"); 159965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid[] = { 160965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x00, 0x7f, // corner cases 161965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x01, 0x10, 0x7e, 0x5d // misc 162965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 163965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 164965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 165965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // As conversion stops upon encountering an invalid character, we 166965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // need to test each invalid character separately, to make sure it 167965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // is recognized as invalid. 168965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 169965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters -----\n"); 170965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t always_invalid[] = { 171965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x80, 0xbf, // corner cases 172965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf8, 0xff, // corner cases 173965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x81, 0xbe, 0x95, 0xab // misc 174965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 175965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i < sizeof always_invalid; ++i) { 176965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t invalid_char[1]; 177965977c3facb05dc36068fdc5cdfaaac4630f40eflorian invalid_char[0] = always_invalid[i]; 178965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 179965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 180965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 181965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // In case of m3 == 0 we get cc=0 indicating exhaustion of source 182965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters if m3 == 1 -----\n"); 183965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t invalid_if_m3[] = { // contains all such invalid characters 184965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc0, 0xc1, 185965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf5, 0xf6, 0xf7 186965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 187965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i < sizeof invalid_if_m3; ++i) { 188965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t invalid_char[1]; 189965977c3facb05dc36068fdc5cdfaaac4630f40eflorian invalid_char[0] = invalid_if_m3[i]; 190965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 191965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 192965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 193965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- 1st char valid, 2nd char invalid -----\n"); 194965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_invalid[] = { 195965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0x10, // valid 196965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xaa // invalid 197965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 198965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 199965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 200965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 201965977c3facb05dc36068fdc5cdfaaac4630f40eflorian// Test conversion of a two-byte character 202965977c3facb05dc36068fdc5cdfaaac4630f40eflorianvoid convert_2_bytes(void) 203965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 204965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int i; 205965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 206965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n===== Conversion of a two-byte character =====\n"); 207965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 208965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters -----\n"); 209965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid[] = { 210965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x80, // corner case 211965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0xbf, // corner case 212965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xdf, 0x80, // corner case 213965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xdf, 0xbf, // corner case 214965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc3, 0xbe, 0xda, 0xbc // misc 215965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 216965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 217965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 218965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters if m3 == 0 -----\n"); 219965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // First char is 0xc0 or 0xc1 220965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_if_not_m3[] = { 221965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc0, 0x80, 222965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc0, 0xbf, 223965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc1, 0x80, 224965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc0, 0xbf 225965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 226965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3); 227965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 228965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Test for invalid two-byte characters where the 1st byte is valid 229965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // The 2nd byte is invalid if not in range 0x80..0xbf, inclusive 230965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 231965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // As conversion stops upon encountering an invalid character, we 232965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // need to test each invalid character separately, to make sure it 233965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // is recognized as invalid. 234965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 235965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters if m3 == 1 -----\n"); 236965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t always_invalid[] = { 237965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x00, 238965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0x7f, 239965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0xc0, 240965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc2, 0xff 241965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 242965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i < sizeof always_invalid; i += 2) { 243965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t invalid_char[2]; 244965977c3facb05dc36068fdc5cdfaaac4630f40eflorian invalid_char[0] = always_invalid[i]; 245965977c3facb05dc36068fdc5cdfaaac4630f40eflorian invalid_char[1] = always_invalid[i+1]; 246965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 247965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 248965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 249965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Nb: for a two-byte character we need not test the case where 250965977c3facb05dc36068fdc5cdfaaac4630f40eflorian invalidity of the character (cc=2) takes precedence over exhaustion 251965977c3facb05dc36068fdc5cdfaaac4630f40eflorian of the 1st operand (cc=1). Invalidity of the character has already 252965977c3facb05dc36068fdc5cdfaaac4630f40eflorian been tested when testing the 1st byte. */ 253965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 254965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- 1st char valid, 2nd char invalid -----\n"); 255965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_invalid[] = { 256965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc3, 0x81, // valid 257965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xc4, 0x00 // invalid 258965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 259965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 260965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 261965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 262965977c3facb05dc36068fdc5cdfaaac4630f40eflorian// Test conversion of a three-byte character 263965977c3facb05dc36068fdc5cdfaaac4630f40eflorianvoid 264965977c3facb05dc36068fdc5cdfaaac4630f40eflorianconvert_3_bytes(void) 265965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 266965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int i; 267965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 268965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n===== Conversion of a three-byte character =====\n"); 269965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 270965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Exhaustively test the 1st byte E0 - EF, and the interval boundaries for 271965977c3facb05dc36068fdc5cdfaaac4630f40eflorian the 2nd and 3rd bytes */ 272965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters -----\n"); 273965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t e0[] = { 274965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0xa0, 0x80, 275965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0xbf, 0x80, 276965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0xa0, 0xbf, 277965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0xbf, 0xbf, 278965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0xaa, 0xbb, // random e0 .. .. 279965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 280965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, e0, sizeof e0); 281965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 282965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t ed[] = { 283965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xed, 0x80, 0x80, 284965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xed, 0x9f, 0x80, 285965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xed, 0x80, 0xbf, 286965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xed, 0x9f, 0xbf, 287965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xed, 0x8a, 0xbb, // random ed .. .. 288965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 289965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, ed, sizeof ed); 290965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 291965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0xf; ++i) { 292965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_1[3] = { 0x0, 0x80, 0x80 }; 293965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_2[3] = { 0x0, 0xbf, 0x80 }; 294965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_3[3] = { 0x0, 0x80, 0xbf }; 295965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_4[3] = { 0x0, 0xbf, 0xbf }; 296965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 297965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0x00) continue; // special case e0 298965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0x0d) continue; // special case ed 299965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 300965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_1[0] = 0xe0 | i; 301965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_2[0] = 0xe0 | i; 302965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_3[0] = 0xe0 | i; 303965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_4[0] = 0xe0 | i; 304965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 305965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 306965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_3, sizeof exxx_3); 307965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_4, sizeof exxx_4); 308965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 309965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 310965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters (2nd byte is invalid) -----\n"); 311965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Test for invalid three-byte characters where the 1st byte is valid 312965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // The 2nd byte is invalid. 313965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 314965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // As conversion stops upon encountering an invalid character, we 315965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // need to test each invalid character separately, to make sure it 316965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // is recognized as invalid. 317965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 318965977c3facb05dc36068fdc5cdfaaac4630f40eflorian e0[0] = 0xe0; // valid 319965977c3facb05dc36068fdc5cdfaaac4630f40eflorian e0[1] = 0x9f; // invalid because outside [0xa0 .. 0xbf] 320965977c3facb05dc36068fdc5cdfaaac4630f40eflorian e0[2] = 0x80; // valid 321965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, e0, sizeof e0); 322965977c3facb05dc36068fdc5cdfaaac4630f40eflorian e0[1] = 0xc0; // invalid because outside [0xa0 .. 0xbf] 323965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, e0, sizeof e0); 324965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 325965977c3facb05dc36068fdc5cdfaaac4630f40eflorian ed[0] = 0xed; // valid 326965977c3facb05dc36068fdc5cdfaaac4630f40eflorian ed[1] = 0x7f; // invalid because outside [0x80 .. 0x9f] 327965977c3facb05dc36068fdc5cdfaaac4630f40eflorian ed[2] = 0x80; // valid 328965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, ed, sizeof ed); 329965977c3facb05dc36068fdc5cdfaaac4630f40eflorian ed[1] = 0xa0; // invalid because outside [0x80 .. 0x9f] 330965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, ed, sizeof ed); 331965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 332965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0xf; ++i) { 333965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_1[3] = { 0x0, 0x7f, 0x80 }; 334965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_2[3] = { 0x0, 0xc0, 0x80 }; 335965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 336965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0x00) continue; // special case e0 337965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0x0d) continue; // special case ed 338965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 339965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_1[0] = 0xe0 | i; 340965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_2[0] = 0xe0 | i; 341965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 342965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 343965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 344965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 345965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters (3rd byte is invalid) -----\n"); 346965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // For all 1st bytes 0xe0 .. 0xef the 3rd bytes must be in [0x80 .. 0xbf] 347965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // No need to special case 0xe0 and 0xed 348965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0xf; ++i) { 349965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_1[3] = { 0x0, 0xab, 0x7f }; 350965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t exxx_2[3] = { 0x0, 0xab, 0xc0 }; 351965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 352965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_1[0] = 0xe0 | i; 353965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exxx_2[0] = 0xe0 | i; 354965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 355965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 356965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 357965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 358965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid 2nd char AND output exhausted -----\n"); 359965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The character is invalid in its 2nd byte AND the output buffer is 360965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exhausted (2 bytes are needed) */ 361965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t pat1[] = { 362965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe0, 0x00, 0x80 363965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 364965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 1, pat1, 3); 365965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 366965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid 3rd char AND output exhausted -----\n"); 367965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The character is invalid in its 3rd byte AND the output buffer is 368965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exhausted (2 bytes are needed) */ 369965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t pat2[] = { 370965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe4, 0x84, 0x00 371965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 372965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 1, pat2, 3); 373965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 374965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- 1st char valid, 2nd char invalid -----\n"); 375965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_invalid[] = { 376965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x90, 0x90, // valid 377965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xe1, 0x00, 0x90 // invalid 378965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 379965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 380965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 381965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 382965977c3facb05dc36068fdc5cdfaaac4630f40eflorian// Test conversion of a four-byte character 383965977c3facb05dc36068fdc5cdfaaac4630f40eflorianvoid 384965977c3facb05dc36068fdc5cdfaaac4630f40eflorianconvert_4_bytes(void) 385965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 386965977c3facb05dc36068fdc5cdfaaac4630f40eflorian int i, j; 387965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 388965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n===== Conversion of a four-byte character =====\n"); 389965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 390965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters -----\n"); 391965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 4; ++i) { 392965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid[4]; 393965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 394965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[0] = 0xf0 | i; 395965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 396965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (j = 0; j <= 1; ++j) { 397965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Byte 2 398965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0) { 399965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[1] = j == 0 ? 0x90 : 0xbf; // 0xf0 400965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } else if (i == 4) { 401965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[1] = j == 0 ? 0x80 : 0x8f; // 0xf4 402965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } else { 403965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[1] = j == 0 ? 0x80 : 0xbf; // 0xf1 .. 0xf3 404965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 405965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Byte 3 and byte 4 have same interval 0x80 .. 0xbf 406965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[2] = 0x80; 407965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[3] = 0x80; 408965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 409965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[2] = 0x80; 410965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[3] = 0xbf; 411965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 412965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[2] = 0xbf; 413965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[3] = 0x80; 414965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 415965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[2] = 0xbf; 416965977c3facb05dc36068fdc5cdfaaac4630f40eflorian valid[3] = 0xbf; 417965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid, sizeof valid); 418965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 419965977c3facb05dc36068fdc5cdfaaac4630f40eflorian } 420965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 421965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Valid characters if m3 == 0 -----\n"); 422965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // First char is 0xf5 .. 0xf7 423965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_if_not_m3[] = { 424965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf5, 0x00, 0x00, 0x00, 425965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf6, 0x11, 0x22, 0x33, 426965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf7, 0x44, 0x55, 0x66, 427965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 428965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3); 429965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 430965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // As conversion stops upon encountering an invalid character, we 431965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // need to test each invalid character separately, to make sure it 432965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // is recognized as invalid. 433965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 434965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters (2nd byte is invalid) -----\n"); 435965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Test for invalid four-byte characters where the 2nd byte is invalid. 436965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // All other bytes are valid 437965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t f0[4], f4[4]; 438965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 439965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f0[0] = 0xf0; // valid 440965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f0[1] = 0x8f; // invalid because outside [0x90 .. 0xbf] 441965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f0[2] = 0x80; // valid 442965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f0[3] = 0x80; // valid 443965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, f0, sizeof f0); 444965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f0[1] = 0xc0; // invalid because outside [0x90 .. 0xbf] 445965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, f0, sizeof f0); 446965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 44703129681ef833f5d2461437a48f162dddd4d0c6fflorian f4[0] = 0xf4; // valid 448965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f4[1] = 0x7f; // invalid because outside [0x80 .. 0x8f] 449965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f4[2] = 0x80; // valid 45003129681ef833f5d2461437a48f162dddd4d0c6fflorian f4[3] = 0x80; // valid 451965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, f4, sizeof f4); 452965977c3facb05dc36068fdc5cdfaaac4630f40eflorian f4[1] = 0x90; // invalid because outside [0x80 .. 0x9f] 453965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, f4, sizeof f4); 454965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 455965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0x4; ++i) { 456965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t fxxx_1[4] = { 0x0, 0x7f, 0x80, 0x80 }; 457965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t fxxx_2[4] = { 0x0, 0xc0, 0x80, 0x80 }; 458965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 459965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 0) continue; // special case f0 460965977c3facb05dc36068fdc5cdfaaac4630f40eflorian if (i == 4) continue; // special case f4 461965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 462965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx_1[0] = 0xf0 | i; 463965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx_2[0] = 0xf0 | i; 464965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx_1, sizeof fxxx_1); 465965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx_2, sizeof fxxx_2); 466965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 467965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 468965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters (3rd byte is invalid) -----\n"); 469965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Test for invalid four-byte characters where the 3rd byte is invalid. 470965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // All other bytes are valid 471965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0x4; ++i) { 472965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t fxxx[4] = { 0x0, 0x0, 0x0, 0x80 }; 473965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 474965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[0] = 0xf0 | i; 475965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[1] = (i == 0) ? 0x94 : 0x84; 476965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[2] = 0x7f; 477965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx, sizeof fxxx); 478965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[2] = 0xc0; 479965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx, sizeof fxxx); 480965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 481965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 482965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid characters (4th byte is invalid) -----\n"); 483965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // Test for invalid four-byte characters where the 3rd byte is invalid. 484965977c3facb05dc36068fdc5cdfaaac4630f40eflorian // All other bytes are valid 485965977c3facb05dc36068fdc5cdfaaac4630f40eflorian for (i = 0; i <= 0x4; ++i) { 486965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t fxxx[4] = { 0x0, 0x0, 0x80, 0x0 }; 487965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 488965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[0] = 0xf0 | i; 489965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[1] = (i == 0) ? 0x94 : 0x84; 490965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[3] = 0x7f; 491965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx, sizeof fxxx); 492965977c3facb05dc36068fdc5cdfaaac4630f40eflorian fxxx[3] = 0xc0; 493965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, fxxx, sizeof fxxx); 494965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 495965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 496965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid 2nd char AND output exhausted -----\n"); 497965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The character is invalid in its 2nd byte AND the output buffer is 498965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exhausted (4 bytes are needed) */ 499965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t pat1[] = { 500965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf0, 0x00, 0x80, 0x80 501965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 502965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 1, pat1, 4); 503965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 504965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid 3rd char AND output exhausted -----\n"); 505965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The character is invalid in its 3rd byte AND the output buffer is 506965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exhausted (4 bytes are needed) */ 507965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t pat2[] = { 508965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf0, 0xaa, 0x00, 0x80 509965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 510965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 3, pat2, 4); 511965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 512965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- Invalid 4th char AND output exhausted -----\n"); 513965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* The character is invalid in its 4th byte AND the output buffer is 514965977c3facb05dc36068fdc5cdfaaac4630f40eflorian exhausted (4 bytes are needed) */ 515965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t pat3[] = { 516965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf0, 0xaa, 0xaa, 0x00 517965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 518965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 3, pat3, 4); 519965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 520965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n----- 1st char valid, 2nd char invalid -----\n"); 521965977c3facb05dc36068fdc5cdfaaac4630f40eflorian uint8_t valid_invalid[] = { 522965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf0, 0xaa, 0xaa, 0xaa, // valid 523965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 0xf0, 0x00, 0x00, 0x00 // invalid 524965977c3facb05dc36068fdc5cdfaaac4630f40eflorian }; 525965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 526965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 527965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 528965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 529965977c3facb05dc36068fdc5cdfaaac4630f40eflorianint main() 530965977c3facb05dc36068fdc5cdfaaac4630f40eflorian{ 531965977c3facb05dc36068fdc5cdfaaac4630f40eflorian convert_1_byte(); 532965977c3facb05dc36068fdc5cdfaaac4630f40eflorian convert_2_bytes(); 533965977c3facb05dc36068fdc5cdfaaac4630f40eflorian convert_3_bytes(); 534965977c3facb05dc36068fdc5cdfaaac4630f40eflorian convert_4_bytes(); 535965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 536965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Length == 0, no memory should be read or written */ 537965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test1 ----------------\n"); 538965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 0, NULL, 0); 539965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 540965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Test exhaustion of source length (source bytes are valid) */ 541965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test2.1 ----------------\n"); 542965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 543965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* No character will be written to BUFF, i.e. loop in jitted code 544965977c3facb05dc36068fdc5cdfaaac4630f40eflorian is not iterated */ 545965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, NULL, 0); 546965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern1, 0); 547965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern2, 0); 548965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern2, 1); 549965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern3, 0); 550965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern3, 1); 551965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern3, 2); 552965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern4, 0); 553965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern4, 1); 554965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern4, 2); 555965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern4, 3); 556965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 557965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test2.2 ----------------\n"); 558965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* At least one character will be written to BUFF, i.e. loop in jitted 559965977c3facb05dc36068fdc5cdfaaac4630f40eflorian code is iterated */ 560965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern1, 2); 561965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern2, 5); 562965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern3, 6); 563965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, pattern4, 9); 564965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 565965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Test exhaustion of destination length (source bytes are valid) */ 566965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test3.1 ----------------\n"); 567965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 568965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* No character will be written to BUFF, i.e. loop in jitted code 569965977c3facb05dc36068fdc5cdfaaac4630f40eflorian is not iterated */ 570965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 571965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Want to write 2 or 4 bytes at a time */ 572965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 0, pattern1, sizeof pattern1); // 2-byte result 573965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 0, pattern2, sizeof pattern2); // 2-byte result 574965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 1, pattern2, sizeof pattern2); // 2-byte result 575965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 0, pattern3, sizeof pattern3); // 2-byte result 576965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 1, pattern3, sizeof pattern3); // 2-byte result 577965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 0, pattern4, sizeof pattern4); // 4-byte result 578965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 1, pattern4, sizeof pattern4); // 4-byte result 579965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 2, pattern4, sizeof pattern4); // 4-byte result 580965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(NULL, 3, pattern4, sizeof pattern4); // 4-byte result 581965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 582965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test3.2 ----------------\n"); 583965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* At least one character will be written to BUFF, i.e. loop in jitted 584965977c3facb05dc36068fdc5cdfaaac4630f40eflorian code is iterated */ 585965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 4, pattern1, sizeof pattern1); 586965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 5, pattern1, sizeof pattern2); 587965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 6, pattern1, sizeof pattern3); 588965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, 7, pattern1, sizeof pattern4); 589965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 590965977c3facb05dc36068fdc5cdfaaac4630f40eflorian /* Convert buffer with mixed characters */ 591965977c3facb05dc36068fdc5cdfaaac4630f40eflorian printf("\n------------- test4 ----------------\n"); 592965977c3facb05dc36068fdc5cdfaaac4630f40eflorian run_test(buff, sizeof buff, mixed, sizeof mixed); 593965977c3facb05dc36068fdc5cdfaaac4630f40eflorian 594965977c3facb05dc36068fdc5cdfaaac4630f40eflorian return 0; 595965977c3facb05dc36068fdc5cdfaaac4630f40eflorian} 596