libgrapheme

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

util.c (2703B)


      1/* See LICENSE file for copyright and license details. */
      2#include <math.h>
      3#include <stdio.h>
      4#include <stdlib.h>
      5#include <time.h>
      6
      7#include "../gen/types.h"
      8#include "../grapheme.h"
      9#include "util.h"
     10
     11uint_least32_t *
     12generate_cp_test_buffer(const struct break_test *test, size_t testlen,
     13                        size_t *buflen)
     14{
     15	size_t i, j, off;
     16	uint_least32_t *buf;
     17
     18	/* allocate and generate buffer */
     19	for (i = 0, *buflen = 0; i < testlen; i++) {
     20		*buflen += test[i].cplen;
     21	}
     22	if (!(buf = calloc(*buflen, sizeof(*buf)))) {
     23		fprintf(stderr,
     24		        "generate_test_buffer: calloc: Out of memory.\n");
     25		exit(1);
     26	}
     27	for (i = 0, off = 0; i < testlen; i++) {
     28		for (j = 0; j < test[i].cplen; j++) {
     29			buf[off + j] = test[i].cp[j];
     30		}
     31		off += test[i].cplen;
     32	}
     33
     34	return buf;
     35}
     36
     37char *
     38generate_utf8_test_buffer(const struct break_test *test, size_t testlen,
     39                          size_t *buflen)
     40{
     41	size_t i, j, off, ret;
     42	char *buf;
     43
     44	/* allocate and generate buffer */
     45	for (i = 0, *buflen = 0; i < testlen; i++) {
     46		for (j = 0; j < test[i].cplen; j++) {
     47			*buflen += grapheme_encode_utf8(test[i].cp[j], NULL, 0);
     48		}
     49	}
     50	(*buflen)++; /* terminating NUL-byte */
     51	if (!(buf = malloc(*buflen))) {
     52		fprintf(stderr,
     53		        "generate_test_buffer: malloc: Out of memory.\n");
     54		exit(1);
     55	}
     56	for (i = 0, off = 0; i < testlen; i++) {
     57		for (j = 0; j < test[i].cplen; j++, off += ret) {
     58			if ((ret = grapheme_encode_utf8(
     59				     test[i].cp[j], buf + off, *buflen - off)) >
     60			    (*buflen - off)) {
     61				/* shouldn't happen */
     62				fprintf(stderr, "generate_utf8_test_buffer: "
     63				                "Buffer too small.\n");
     64				exit(1);
     65			}
     66		}
     67	}
     68	buf[*buflen - 1] = '\0';
     69
     70	return buf;
     71}
     72
     73static double
     74time_diff(clock_t a, clock_t b)
     75{
     76	return (double)(b - a) / CLOCKS_PER_SEC;
     77}
     78
     79void
     80run_benchmark(void (*func)(const void *), const void *payload, const char *name,
     81              const char *comment, const char *unit, double *baseline,
     82              size_t num_iterations, size_t units_per_iteration)
     83{
     84	clock_t start, end;
     85	size_t i;
     86	double diff;
     87
     88	printf("\t%s ", name);
     89	fflush(stdout);
     90
     91	start = clock();
     92	for (i = 0; i < num_iterations; i++) {
     93		func(payload);
     94
     95		if (i % (num_iterations / 10) == 0) {
     96			printf(".");
     97			fflush(stdout);
     98		}
     99	}
    100	end = clock();
    101	diff = time_diff(start, end) / (double)num_iterations /
    102	       (double)units_per_iteration;
    103
    104	if (isnan(*baseline)) {
    105		*baseline = diff;
    106		printf(" avg. %.3es/%s (baseline)\n", diff, unit);
    107	} else {
    108		printf(" avg. %.3es/%s (%.2f%% %s%s%s)\n", diff, unit,
    109		       fabs(1.0 - diff / *baseline) * 100,
    110		       (diff < *baseline) ? "faster" : "slower",
    111		       comment ? ", " : "", comment ? comment : "");
    112	}
    113}