libgrapheme

unicode string library
git clone git://git.suckless.org/libgrapheme
Log | Files | Refs | README | LICENSE

bidirectional.c (3630B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <inttypes.h>
      3 #include <stdbool.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 
      7 #include "../gen/bidirectional-test.h"
      8 #include "../gen/bidirectional.h"
      9 #include "../gen/types.h"
     10 #include "../grapheme.h"
     11 #include "util.h"
     12 
     13 static inline int_least16_t
     14 get_mirror_offset(uint_least32_t cp)
     15 {
     16 	if (cp <= UINT32_C(0x10FFFF)) {
     17 		return mirror_minor[mirror_major[cp >> 8] + (cp & 0xFF)];
     18 	} else {
     19 		return 0;
     20 	}
     21 }
     22 
     23 int
     24 main(int argc, char *argv[])
     25 {
     26 	enum grapheme_bidirectional_direction resolved;
     27 	uint_least32_t data[512], output[512],
     28 		target; /* TODO iterate and get max, allocate */
     29 	int_least8_t lev[512];
     30 	size_t i, num_tests, failed, datalen, levlen, outputlen, ret, j, m,
     31 		ret2;
     32 
     33 	datalen = LEN(data);
     34 	levlen = LEN(lev);
     35 	outputlen = LEN(output);
     36 
     37 	(void)argc;
     38 
     39 	for (i = 0, num_tests = 0; i < LEN(bidirectional_test); i++) {
     40 		num_tests += bidirectional_test[i].modelen;
     41 	}
     42 
     43 	for (i = 0, failed = 0; i < LEN(bidirectional_test); i++) {
     44 		for (m = 0; m < bidirectional_test[i].modelen; m++) {
     45 			ret = grapheme_bidirectional_preprocess_paragraph(
     46 				bidirectional_test[i].cp,
     47 				bidirectional_test[i].cplen,
     48 				bidirectional_test[i].mode[m], data, datalen,
     49 				&resolved);
     50 			ret2 = 0;
     51 
     52 			if (ret != bidirectional_test[i].cplen ||
     53 			    ret > datalen) {
     54 				goto err;
     55 			}
     56 
     57 			/* resolved paragraph level (if specified in the test)
     58 			 */
     59 			if (bidirectional_test[i].resolved !=
     60 			            GRAPHEME_BIDIRECTIONAL_DIRECTION_NEUTRAL &&
     61 			    resolved != bidirectional_test[i].resolved) {
     62 				goto err;
     63 			}
     64 
     65 			/* line levels */
     66 			ret = grapheme_bidirectional_get_line_embedding_levels(
     67 				data, ret, lev, levlen);
     68 
     69 			if (ret > levlen) {
     70 				goto err;
     71 			}
     72 
     73 			for (j = 0; j < ret; j++) {
     74 				if (lev[j] != bidirectional_test[i].level[j]) {
     75 					goto err;
     76 				}
     77 			}
     78 
     79 			/* reordering */
     80 			ret2 = grapheme_bidirectional_reorder_line(
     81 				bidirectional_test[i].cp, data, ret, output,
     82 				outputlen);
     83 
     84 			if (ret2 != bidirectional_test[i].reorderlen) {
     85 				goto err;
     86 			}
     87 
     88 			for (j = 0; j < ret2; j++) {
     89 				target = bidirectional_test[i]
     90 				                 .cp[bidirectional_test[i]
     91 				                             .reorder[j]];
     92 				if (output[j] !=
     93 				    (uint_least32_t)((int_least32_t)target +
     94 				                     get_mirror_offset(
     95 							     target))) {
     96 					goto err;
     97 				}
     98 			}
     99 
    100 			continue;
    101 err:
    102 			fprintf(stderr,
    103 			        "%s: Failed conformance test %zu (mode %i) [",
    104 			        argv[0], i, bidirectional_test[i].mode[m]);
    105 			for (j = 0; j < bidirectional_test[i].cplen; j++) {
    106 				fprintf(stderr, " 0x%04" PRIXLEAST32,
    107 				        bidirectional_test[i].cp[j]);
    108 			}
    109 			fprintf(stderr, " ],\n\tlevels: got      (");
    110 			for (j = 0; j < ret; j++) {
    111 				fprintf(stderr, " %" PRIdLEAST8,
    112 				        (int_least8_t)lev[j]);
    113 			}
    114 			fprintf(stderr, " ),\n\tlevels: expected (");
    115 			for (j = 0; j < ret; j++) {
    116 				fprintf(stderr, " %" PRIdLEAST8,
    117 				        bidirectional_test[i].level[j]);
    118 			}
    119 			fprintf(stderr, " ).\n");
    120 
    121 			fprintf(stderr, "\treordering: got      (");
    122 			for (j = 0; j < ret2; j++) {
    123 				fprintf(stderr, " 0x%04" PRIxLEAST32,
    124 				        output[j]);
    125 			}
    126 			fprintf(stderr, " ),\n\treordering: expected (");
    127 			for (j = 0; j < bidirectional_test[i].reorderlen; j++) {
    128 				fprintf(stderr, " 0x%04" PRIxLEAST32,
    129 				        bidirectional_test[i]
    130 				                .cp[bidirectional_test[i]
    131 				                            .reorder[j]]);
    132 			}
    133 			fprintf(stderr, " ).\n");
    134 
    135 			failed++;
    136 		}
    137 	}
    138 	printf("%s: %zu/%zu conformance tests passed.\n", argv[0],
    139 	       num_tests - failed, num_tests);
    140 
    141 	return 0;
    142 }