1 /*
2  * Utilities for efficient access to the TTFfile
3  *
4  * Copyright © 1997-1998 Herbert Duerr
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free Softaware
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 //#define DEBUG 1
23 #include "ttf.h"
24 
25 #include <fcntl.h>
26 #include <sys/mman.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 
30 #include <cstddef>
31 #include <cstdlib>
32 #include <cstring>
33 
34 void *
allocMem(int size)35 allocMem(int size)
36 {
37 	return malloc(size);
38 }
39 
40 void *
shrinkMem(void * ptr,int newsize)41 shrinkMem(void *ptr, int newsize)
42 {
43 	return realloc(ptr, newsize);
44 }
45 
46 void
deallocMem(void * ptr,int size XFSTT_ATTR_UNUSED)47 deallocMem(void *ptr, int size XFSTT_ATTR_UNUSED)
48 {
49 	free(ptr);
50 }
51 
52 #ifdef MEMDEBUG
53 
54 #define MEMPTRS 8192
55 
56 typedef struct {
57 	void *ptr;
58 	int len;
59 } memstruct;
60 
61 static memstruct memdbg[MEMPTRS];
62 static int memidx = 0;
63 static int memcount = 0;
64 static int memused = 0;
65 
66 void
cleanupMem()67 cleanupMem()
68 {
69 	debug("Memory holes:\n");
70 	for (int i = 0; i < memidx; ++i)
71 		if (memdbg[i].ptr)
72 			debug("MEM hole[%3d] = %p\n", i, memdbg[i].ptr);
73 
74 	if (memcount != 0)
75 		debug("MEM hole: memcount = %d\n", memcount);
76 }
77 
78 void *
operator new[](size_t size)79 operator new[](size_t size)
80 {
81 	void *ptr = malloc(size);
82 
83 	memused += size;
84 
85 	debug("MEM new[](%5d) = %p", size, ptr);
86 	debug(", memcount = %d, memidx = %d", ++memcount, memidx);
87 
88 	int i = memidx;
89 
90 	while (--i >= 0 && memdbg[i].ptr);
91 	if (i <= 0)
92 		i = memidx++;
93 
94 	debug(", idx = %d, used %d\n", i, memused);
95 
96 	memdbg[i].ptr = ptr;
97 	memdbg[i].len = size;
98 
99 	return ptr;
100 }
101 
102 void
operator delete[](void * ptr)103 operator delete[](void *ptr)
104 {
105 	debug("MEM delete[](%p)", ptr);
106 	debug(", memcount = %d, memidx = %d\n", --memcount, memidx);
107 
108 	int i = memidx;
109 	while (--i >= 0 && memdbg[i].ptr != ptr);
110 	if (i >= 0) {
111 		memdbg[i].ptr = 0;
112 		memused -= memdbg[i].len;
113 		debug(", idx = %d, used %d\n", i, memused);
114 		if (++i == memidx)
115 			--memidx;
116 	} else
117 		debug("Cannot delete!\n");
118 
119 	free(ptr);
120 }
121 
122 void *
operator new(size_t size)123 operator new(size_t size)
124 {
125 	void *ptr = malloc(size);
126 	memused += size;
127 
128 	debug("MEM new(%7d) = %p", size, ptr);
129 	debug(", memcount = %d, memidx = %d", ++memcount, memidx);
130 
131 	int i = memidx;
132 	while (--i >= 0 && memdbg[i].ptr);
133 	if (i <= 0)
134 		i = memidx++;
135 
136 	debug(", idx = %d, used %d\n", i, memused);
137 
138 	memdbg[i].ptr = ptr;
139 	memdbg[i].len = size;
140 
141 	return ptr;
142 }
143 
144 void
operator delete(void * ptr)145 operator delete(void *ptr)
146 {
147 	debug("MEM delete(%p)", ptr);
148 	debug(", memcount = %d, memidx = %d", --memcount, memidx);
149 
150 	int i = memidx;
151 	while (--i >= 0 && memdbg[i].ptr != ptr);
152 	if (i >= 0) {
153 		memdbg[i].ptr = 0;
154 		memused -= memdbg[i].len;
155 		debug(", idx = %d, used %d\n", i, memused);
156 		if (++i == memidx)
157 			--memidx;
158 	} else
159 		debug("Cannot delete!\n");
160 
161 	free(ptr);
162 }
163 
164 #endif /* MEMDEBUG */
165 
RandomAccessFile(const char * fileName)166 RandomAccessFile::RandomAccessFile(const char *fileName)
167 {
168 	int fd = open(fileName, O_RDONLY);
169 	if (fd < 0) {
170 		debug("Cannot open \"%s\"\n", fileName);
171 		ptr = absbase = base = nullptr;
172 		length = 0;
173 		return;
174 	}
175 	struct stat st;
176 	if (fstat(fd, &st) < 0) {
177 		debug("Cannot stat \"%s\"\n", fileName);
178 		ptr = absbase = base = nullptr;
179 		length = 0;
180 		close(fd);
181 		return;
182 	}
183 	length = st.st_size;
184 	base = (uint8_t *)mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, 0L);
185 	close(fd);
186 	if (base == MAP_FAILED) {
187 		debug("MMap failed '%s'\n", strerror(errno));
188 		ptr = absbase = base = nullptr;
189 		length = 0;
190 		return;
191 	}
192 	ptr = absbase = base;
193 }
194 
195 void
closeRAFile()196 RandomAccessFile::closeRAFile()
197 {
198 	if (absbase && absbase == base && length > 0) {
199 		munmap(base, length);
200 	}
201 }
202 
203 uint32_t
calcChecksum()204 RandomAccessFile::calcChecksum()
205 {
206 	uint32_t checksum = 0;
207 	uint8_t *saveptr = ptr;
208 
209 	for (int len = length >> 2; --len >= 0;)
210 		checksum += readUInt();
211 	if (length & 3)
212 		checksum += readUInt() & (-1 << ((-length & 3) << 3));
213 	ptr = saveptr;
214 
215 	debug("Checksum is %08X\n", calcChecksum());
216 
217 	return checksum;
218 }
219