1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdint.h> 2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <inttypes.h> 3663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdlib.h> 4663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <string.h> 5663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdio.h> 6663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "opcodes.h" 7663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#ifndef M3 9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define M3 0 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif 11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* The abstracted result of an CU12 insn */ 13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef struct { 14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint64_t addr1; // target 15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint64_t len1; 16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint64_t addr2; // source 17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint64_t len2; 18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint32_t cc; 19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} cu12_t; 20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Define various input buffers. */ 22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 1-byte UTF-8 character */ 24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern1[] = { 25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x00, 0x01, 0x02, 0x03 26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}; 27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 2-byte UTF-8 character */ 29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern2[] = { 30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x80, 31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x81, 32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x82, 33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x83, 34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}; 35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 3-byte UTF-8 character */ 37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern3[] = { 38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x80, 0x80, 39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x80, 0x81, 40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x80, 0x82, 41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x80, 0x83, 42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}; 43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 4-byte UTF-8 character */ 45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern4[] = { 46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x80, 0x80, 47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x80, 0x81, 48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x80, 0x82, 49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x80, 0x83, 50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}; 51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Mixed bytes */ 54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t mixed[] = { 55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x01, // 1 byte 56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc3, 0x80, // 2 bytes 57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x12, // 1 byte 58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x90, 0x93, // 3 bytes 59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x23, // 1 byte 60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x34, // 1 byte 62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc4, 0x8c, // 2 bytes 63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x91, 0x94, // 3 bytes 64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc5, 0x8a, // 2 bytes 65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc5, 0x8a, // 2 bytes 67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x91, 0x94, // 3 bytes 68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf4, 0x80, 0x90, 0x8a, // 4 bytes 69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x91, 0x94, // 3 bytes 70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}; 71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is the buffer for the converted bytes. */ 73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t buff[1000]; /* Large so we con'don't have to worry about it */ 74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic cu12_t 77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengdo_cu12(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len) 78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int cc = 42; 80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng cu12_t regs; 81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* build up the register pairs */ 83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng register uint8_t *source asm("4") = src; 84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng register uint64_t source_len asm("5") = src_len; 85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng register uint16_t *dest asm("2") = dst; 86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng register uint64_t dest_len asm("3") = dst_len; 87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng asm volatile( 89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng CU12(M3,2,4) 90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "ipm %2\n\t" 91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "srl %2,28\n\t" 92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : "+d"(dest), "+d"(source), "=d"(cc), 93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "+d"(source_len), "+d"(dest_len) 94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : 95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : "memory", "cc"); 96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Capture register contents at end of cu12 */ 98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng regs.addr1 = (uint64_t)dest; 99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng regs.len1 = dest_len; 100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng regs.addr2 = (uint64_t)source; 101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng regs.len2 = source_len; 102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng regs.cc = cc; 103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return regs; 105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid 108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengrun_test(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len) 109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int i; 111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng cu12_t result; 112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("UTF8: "); 114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (src_len == 0) 115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" <none>"); 116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else { 117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for(i = 0; i < src_len; ++i) 118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" %02x", src[i]); 119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n"); 121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng result = do_cu12(dst, dst_len, src, src_len); 123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Write out the converted byte, if any 125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("UTF16: "); 126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (dst_len - result.len1 == 0) 127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" <none>"); 128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else { 129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint64_t num_bytes = dst_len - result.len1; 130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The number of bytes that were written must be divisible by 2 */ 132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (num_bytes % 2 != 0) 133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fprintf(stderr, "*** number of bytes is not a multiple of 2\n"); 134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i < num_bytes / 2; i++) { 136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" %04x", dst[i]); 137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n"); 140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" cc = %d\n", result.cc); 142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (dst != NULL) 143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" dst address difference: %"PRId64, result.addr1 - (uint64_t)dst); 144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" dst len: %"PRId64"\n", result.len1); 145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (src != NULL) 147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" src address difference: %"PRId64, result.addr2 - (uint64_t)src); 148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf(" src len: %"PRId64"\n", result.len2); 149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a one-byte character 152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid convert_1_byte(void) 153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int i; 155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("===== Conversion of a one-byte character =====\n"); 157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters -----\n"); 159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid[] = { 160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x00, 0x7f, // corner cases 161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x01, 0x10, 0x7e, 0x5d // misc 162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // As conversion stops upon encountering an invalid character, we 166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // need to test each invalid character separately, to make sure it 167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is recognized as invalid. 168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters -----\n"); 170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t always_invalid[] = { 171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x80, 0xbf, // corner cases 172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf8, 0xff, // corner cases 173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x81, 0xbe, 0x95, 0xab // misc 174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i < sizeof always_invalid; ++i) { 176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t invalid_char[1]; 177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng invalid_char[0] = always_invalid[i]; 178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // In case of m3 == 0 we get cc=0 indicating exhaustion of source 182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters if m3 == 1 -----\n"); 183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t invalid_if_m3[] = { // contains all such invalid characters 184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc0, 0xc1, 185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf5, 0xf6, 0xf7 186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i < sizeof invalid_if_m3; ++i) { 188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t invalid_char[1]; 189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng invalid_char[0] = invalid_if_m3[i]; 190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- 1st char valid, 2nd char invalid -----\n"); 194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_invalid[] = { 195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0x10, // valid 196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xaa // invalid 197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a two-byte character 202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid convert_2_bytes(void) 203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int i; 205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n===== Conversion of a two-byte character =====\n"); 207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters -----\n"); 209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid[] = { 210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x80, // corner case 211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0xbf, // corner case 212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xdf, 0x80, // corner case 213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xdf, 0xbf, // corner case 214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc3, 0xbe, 0xda, 0xbc // misc 215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters if m3 == 0 -----\n"); 219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // First char is 0xc0 or 0xc1 220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_if_not_m3[] = { 221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc0, 0x80, 222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc0, 0xbf, 223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc1, 0x80, 224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc0, 0xbf 225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3); 227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Test for invalid two-byte characters where the 1st byte is valid 229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // The 2nd byte is invalid if not in range 0x80..0xbf, inclusive 230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // As conversion stops upon encountering an invalid character, we 232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // need to test each invalid character separately, to make sure it 233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is recognized as invalid. 234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters if m3 == 1 -----\n"); 236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t always_invalid[] = { 237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x00, 238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0x7f, 239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0xc0, 240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc2, 0xff 241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i < sizeof always_invalid; i += 2) { 243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t invalid_char[2]; 244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng invalid_char[0] = always_invalid[i]; 245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng invalid_char[1] = always_invalid[i+1]; 246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, invalid_char, sizeof invalid_char); 247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Nb: for a two-byte character we need not test the case where 250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng invalidity of the character (cc=2) takes precedence over exhaustion 251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng of the 1st operand (cc=1). Invalidity of the character has already 252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng been tested when testing the 1st byte. */ 253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- 1st char valid, 2nd char invalid -----\n"); 255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_invalid[] = { 256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc3, 0x81, // valid 257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xc4, 0x00 // invalid 258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a three-byte character 263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid 264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengconvert_3_bytes(void) 265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int i; 267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n===== Conversion of a three-byte character =====\n"); 269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Exhaustively test the 1st byte E0 - EF, and the interval boundaries for 271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the 2nd and 3rd bytes */ 272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters -----\n"); 273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t e0[] = { 274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0xa0, 0x80, 275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0xbf, 0x80, 276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0xa0, 0xbf, 277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0xbf, 0xbf, 278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0xaa, 0xbb, // random e0 .. .. 279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, e0, sizeof e0); 281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t ed[] = { 283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xed, 0x80, 0x80, 284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xed, 0x9f, 0x80, 285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xed, 0x80, 0xbf, 286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xed, 0x9f, 0xbf, 287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xed, 0x8a, 0xbb, // random ed .. .. 288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, ed, sizeof ed); 290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0xf; ++i) { 292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_1[3] = { 0x0, 0x80, 0x80 }; 293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_2[3] = { 0x0, 0xbf, 0x80 }; 294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_3[3] = { 0x0, 0x80, 0xbf }; 295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_4[3] = { 0x0, 0xbf, 0xbf }; 296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0x00) continue; // special case e0 298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0x0d) continue; // special case ed 299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_1[0] = 0xe0 | i; 301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_2[0] = 0xe0 | i; 302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_3[0] = 0xe0 | i; 303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_4[0] = 0xe0 | i; 304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_3, sizeof exxx_3); 307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_4, sizeof exxx_4); 308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters (2nd byte is invalid) -----\n"); 311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Test for invalid three-byte characters where the 1st byte is valid 312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // The 2nd byte is invalid. 313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // As conversion stops upon encountering an invalid character, we 315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // need to test each invalid character separately, to make sure it 316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is recognized as invalid. 317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng e0[0] = 0xe0; // valid 319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng e0[1] = 0x9f; // invalid because outside [0xa0 .. 0xbf] 320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng e0[2] = 0x80; // valid 321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, e0, sizeof e0); 322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng e0[1] = 0xc0; // invalid because outside [0xa0 .. 0xbf] 323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, e0, sizeof e0); 324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ed[0] = 0xed; // valid 326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ed[1] = 0x7f; // invalid because outside [0x80 .. 0x9f] 327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ed[2] = 0x80; // valid 328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, ed, sizeof ed); 329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ed[1] = 0xa0; // invalid because outside [0x80 .. 0x9f] 330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, ed, sizeof ed); 331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0xf; ++i) { 333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_1[3] = { 0x0, 0x7f, 0x80 }; 334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_2[3] = { 0x0, 0xc0, 0x80 }; 335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0x00) continue; // special case e0 337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0x0d) continue; // special case ed 338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_1[0] = 0xe0 | i; 340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_2[0] = 0xe0 | i; 341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters (3rd byte is invalid) -----\n"); 346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // For all 1st bytes 0xe0 .. 0xef the 3rd bytes must be in [0x80 .. 0xbf] 347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // No need to special case 0xe0 and 0xed 348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0xf; ++i) { 349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_1[3] = { 0x0, 0xab, 0x7f }; 350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t exxx_2[3] = { 0x0, 0xab, 0xc0 }; 351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_1[0] = 0xe0 | i; 353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exxx_2[0] = 0xe0 | i; 354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_1, sizeof exxx_1); 355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, exxx_2, sizeof exxx_2); 356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid 2nd char AND output exhausted -----\n"); 359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The character is invalid in its 2nd byte AND the output buffer is 360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exhausted (2 bytes are needed) */ 361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t pat1[] = { 362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe0, 0x00, 0x80 363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 1, pat1, 3); 365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid 3rd char AND output exhausted -----\n"); 367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The character is invalid in its 3rd byte AND the output buffer is 368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exhausted (2 bytes are needed) */ 369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t pat2[] = { 370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe4, 0x84, 0x00 371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 1, pat2, 3); 373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- 1st char valid, 2nd char invalid -----\n"); 375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_invalid[] = { 376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x90, 0x90, // valid 377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xe1, 0x00, 0x90 // invalid 378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a four-byte character 383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid 384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengconvert_4_bytes(void) 385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng int i, j; 387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n===== Conversion of a four-byte character =====\n"); 389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters -----\n"); 391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 4; ++i) { 392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid[4]; 393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[0] = 0xf0 | i; 395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (j = 0; j <= 1; ++j) { 397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Byte 2 398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0) { 399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[1] = j == 0 ? 0x90 : 0xbf; // 0xf0 400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else if (i == 4) { 401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[1] = j == 0 ? 0x80 : 0x8f; // 0xf4 402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[1] = j == 0 ? 0x80 : 0xbf; // 0xf1 .. 0xf3 404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Byte 3 and byte 4 have same interval 0x80 .. 0xbf 406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[2] = 0x80; 407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[3] = 0x80; 408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[2] = 0x80; 410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[3] = 0xbf; 411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[2] = 0xbf; 413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[3] = 0x80; 414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[2] = 0xbf; 416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng valid[3] = 0xbf; 417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid, sizeof valid); 418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Valid characters if m3 == 0 -----\n"); 422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // First char is 0xf5 .. 0xf7 423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_if_not_m3[] = { 424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf5, 0x00, 0x00, 0x00, 425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf6, 0x11, 0x22, 0x33, 426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf7, 0x44, 0x55, 0x66, 427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3); 429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // As conversion stops upon encountering an invalid character, we 431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // need to test each invalid character separately, to make sure it 432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is recognized as invalid. 433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters (2nd byte is invalid) -----\n"); 435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Test for invalid four-byte characters where the 2nd byte is invalid. 436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // All other bytes are valid 437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t f0[4], f4[4]; 438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f0[0] = 0xf0; // valid 440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f0[1] = 0x8f; // invalid because outside [0x90 .. 0xbf] 441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f0[2] = 0x80; // valid 442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f0[3] = 0x80; // valid 443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, f0, sizeof f0); 444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f0[1] = 0xc0; // invalid because outside [0x90 .. 0xbf] 445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, f0, sizeof f0); 446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f4[0] = 0xf4; // valid 448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f4[1] = 0x7f; // invalid because outside [0x80 .. 0x8f] 449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f4[2] = 0x80; // valid 450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f4[3] = 0x80; // valid 451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, f4, sizeof f4); 452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng f4[1] = 0x90; // invalid because outside [0x80 .. 0x9f] 453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, f4, sizeof f4); 454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0x4; ++i) { 456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t fxxx_1[4] = { 0x0, 0x7f, 0x80, 0x80 }; 457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t fxxx_2[4] = { 0x0, 0xc0, 0x80, 0x80 }; 458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 0) continue; // special case f0 460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (i == 4) continue; // special case f4 461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx_1[0] = 0xf0 | i; 463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx_2[0] = 0xf0 | i; 464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx_1, sizeof fxxx_1); 465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx_2, sizeof fxxx_2); 466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters (3rd byte is invalid) -----\n"); 469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Test for invalid four-byte characters where the 3rd byte is invalid. 470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // All other bytes are valid 471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0x4; ++i) { 472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t fxxx[4] = { 0x0, 0x0, 0x0, 0x80 }; 473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[0] = 0xf0 | i; 475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[1] = (i == 0) ? 0x94 : 0x84; 476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[2] = 0x7f; 477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx, sizeof fxxx); 478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[2] = 0xc0; 479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx, sizeof fxxx); 480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid characters (4th byte is invalid) -----\n"); 483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Test for invalid four-byte characters where the 3rd byte is invalid. 484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // All other bytes are valid 485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i <= 0x4; ++i) { 486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t fxxx[4] = { 0x0, 0x0, 0x80, 0x0 }; 487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[0] = 0xf0 | i; 489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[1] = (i == 0) ? 0x94 : 0x84; 490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[3] = 0x7f; 491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx, sizeof fxxx); 492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fxxx[3] = 0xc0; 493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, fxxx, sizeof fxxx); 494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid 2nd char AND output exhausted -----\n"); 497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The character is invalid in its 2nd byte AND the output buffer is 498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exhausted (4 bytes are needed) */ 499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t pat1[] = { 500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf0, 0x00, 0x80, 0x80 501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 1, pat1, 4); 503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid 3rd char AND output exhausted -----\n"); 505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The character is invalid in its 3rd byte AND the output buffer is 506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exhausted (4 bytes are needed) */ 507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t pat2[] = { 508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf0, 0xaa, 0x00, 0x80 509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 3, pat2, 4); 511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- Invalid 4th char AND output exhausted -----\n"); 513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The character is invalid in its 4th byte AND the output buffer is 514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng exhausted (4 bytes are needed) */ 515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t pat3[] = { 516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf0, 0xaa, 0xaa, 0x00 517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 3, pat3, 4); 519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n----- 1st char valid, 2nd char invalid -----\n"); 521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng uint8_t valid_invalid[] = { 522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf0, 0xaa, 0xaa, 0xaa, // valid 523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xf0, 0x00, 0x00, 0x00 // invalid 524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng }; 525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid); 526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main() 530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng convert_1_byte(); 532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng convert_2_bytes(); 533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng convert_3_bytes(); 534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng convert_4_bytes(); 535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Length == 0, no memory should be read or written */ 537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test1 ----------------\n"); 538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 0, NULL, 0); 539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Test exhaustion of source length (source bytes are valid) */ 541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test2.1 ----------------\n"); 542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* No character will be written to BUFF, i.e. loop in jitted code 544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is not iterated */ 545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, NULL, 0); 546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern1, 0); 547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern2, 0); 548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern2, 1); 549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern3, 0); 550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern3, 1); 551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern3, 2); 552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern4, 0); 553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern4, 1); 554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern4, 2); 555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern4, 3); 556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test2.2 ----------------\n"); 558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* At least one character will be written to BUFF, i.e. loop in jitted 559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng code is iterated */ 560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern1, 2); 561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern2, 5); 562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern3, 6); 563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, pattern4, 9); 564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Test exhaustion of destination length (source bytes are valid) */ 566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test3.1 ----------------\n"); 567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* No character will be written to BUFF, i.e. loop in jitted code 569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is not iterated */ 570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Want to write 2 or 4 bytes at a time */ 572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 0, pattern1, sizeof pattern1); // 2-byte result 573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 0, pattern2, sizeof pattern2); // 2-byte result 574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 1, pattern2, sizeof pattern2); // 2-byte result 575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 0, pattern3, sizeof pattern3); // 2-byte result 576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 1, pattern3, sizeof pattern3); // 2-byte result 577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 0, pattern4, sizeof pattern4); // 4-byte result 578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 1, pattern4, sizeof pattern4); // 4-byte result 579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 2, pattern4, sizeof pattern4); // 4-byte result 580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(NULL, 3, pattern4, sizeof pattern4); // 4-byte result 581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test3.2 ----------------\n"); 583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* At least one character will be written to BUFF, i.e. loop in jitted 584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng code is iterated */ 585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 4, pattern1, sizeof pattern1); 586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 5, pattern1, sizeof pattern2); 587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 6, pattern1, sizeof pattern3); 588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, 7, pattern1, sizeof pattern4); 589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Convert buffer with mixed characters */ 591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng printf("\n------------- test4 ----------------\n"); 592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_test(buff, sizeof buff, mixed, sizeof mixed); 593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return 0; 595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 596