summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/bk/bkblock.c
blob: 577048a4293ee9aae8384293ba47de89fa98efd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "bkblock.h"

static void bkblock_acells(bk_Block *b, uint32_t len) {
	if (len <= b->length + b->free) {
		// We have enough space
		b->free -= len - b->length;
		b->length = len;
	} else {
		// allocate space
		b->length = len;
		b->free = (len >> 1) & 0xFFFFFF;
		RESIZE(b->cells, b->length + b->free);
	}
}
bool bk_cellIsPointer(bk_Cell *cell) {
	return cell->t >= p16;
}

static bk_Cell *bkblock_grow(bk_Block *b, uint32_t len) {
	uint32_t olen = b->length;
	bkblock_acells(b, olen + len);
	return &(b->cells[olen]);
}

bk_Block *_bkblock_init() {
	bk_Block *b;
	NEW(b);
	bkblock_acells(b, 0);
	return b;
}

static void bkblock_pushint(bk_Block *b, bk_CellType type, uint32_t x) {
	bk_Cell *cell = bkblock_grow(b, 1);
	cell->t = type;
	cell->z = x;
}
static void bkblock_pushptr(bk_Block *b, bk_CellType type, bk_Block *p) {
	bk_Cell *cell = bkblock_grow(b, 1);
	cell->t = type;
	cell->p = p;
}

static void vbkpushitems(bk_Block *b, bk_CellType type0, va_list ap) {
	bk_CellType curtype = type0;
	while (curtype) {
		if (curtype == bkcopy || curtype == bkembed) {
			bk_Block *par = va_arg(ap, bk_Block *);
			if (par && par->cells) {
				for (uint32_t j = 0; j < par->length; j++) {
					if (bk_cellIsPointer(par->cells + j)) {
						bkblock_pushptr(b, par->cells[j].t, par->cells[j].p);
					} else {
						bkblock_pushint(b, par->cells[j].t, par->cells[j].z);
					}
				}
			}
			if (curtype == bkembed && par) {
				FREE(par->cells);
				FREE(par);
			}
		} else if (curtype < p16) {
			uint32_t par = va_arg(ap, int);
			bkblock_pushint(b, curtype, par);
		} else {
			bk_Block *par = va_arg(ap, bk_Block *);
			bkblock_pushptr(b, curtype, par);
		}
		curtype = va_arg(ap, int);
	}
}

bk_Block *bk_new_Block(int type0, ...) {
	va_list ap;
	va_start(ap, type0);
	bk_Block *b = _bkblock_init();
	vbkpushitems(b, type0, ap);
	va_end(ap);
	return b;
}

bk_Block *bk_push(bk_Block *b, int type0, ...) {
	va_list ap;
	va_start(ap, type0);
	vbkpushitems(b, type0, ap);
	va_end(ap);
	return b;
}

bk_Block *bk_newBlockFromStringLen(size_t len, const char *str) {
	if (!str) return NULL;
	bk_Block *b = bk_new_Block(bkover);
	for (size_t j = 0; j < len; j++) {
		bkblock_pushint(b, b8, str[j]);
	}
	return b;
}

bk_Block *bk_newBlockFromBuffer(MOVE caryll_Buffer *buf) {
	if (!buf) return NULL;
	bk_Block *b = bk_new_Block(bkover);
	for (size_t j = 0; j < buf->size; j++) {
		bkblock_pushint(b, b8, buf->data[j]);
	}
	buffree(buf);
	return b;
}
bk_Block *bk_newBlockFromBufferCopy(OBSERVE caryll_Buffer *buf) {
	if (!buf) return NULL;
	bk_Block *b = bk_new_Block(bkover);
	for (size_t j = 0; j < buf->size; j++) {
		bkblock_pushint(b, b8, buf->data[j]);
	}
	return b;
}

void bk_printBlock(bk_Block *b) {
	fprintf(stderr, "Block size %08x\n", (uint32_t)b->length);
	fprintf(stderr, "------------------\n");
	for (uint32_t j = 0; j < b->length; j++) {
		if (bk_cellIsPointer(b->cells + j)) {
			if (b->cells[j].p) {
				fprintf(stderr, "  %3d %p[%d]\n", b->cells[j].t, b->cells[j].p,
				        b->cells[j].p->_index);
			} else {
				fprintf(stderr, "  %3d [NULL]\n", b->cells[j].t);
			}
		} else {
			fprintf(stderr, "  %3d %d\n", b->cells[j].t, b->cells[j].z);
		}
	}
	fprintf(stderr, "------------------\n");
}