libgrapheme

Freestanding C library for unicode string handling
git clone https://git.sinitax.com/suckless/libgrapheme
Log | Files | Refs | README | LICENSE | sfeed.txt

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
     13static inline int_least16_t
     14get_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
     23int
     24main(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;
    101err:
    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}