Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
EST_Chunk.cc
1
2 /************************************************************************/
3 /* */
4 /* Centre for Speech Technology Research */
5 /* University of Edinburgh, UK */
6 /* Copyright (c) 1997 */
7 /* All Rights Reserved. */
8 /* */
9 /* Permission is hereby granted, free of charge, to use and distribute */
10 /* this software and its documentation without restriction, including */
11 /* without limitation the rights to use, copy, modify, merge, publish, */
12 /* distribute, sublicense, and/or sell copies of this work, and to */
13 /* permit persons to whom this work is furnished to do so, subject to */
14 /* the following conditions: */
15 /* 1. The code must retain the above copyright notice, this list of */
16 /* conditions and the following disclaimer. */
17 /* 2. Any modifications must be clearly marked as such. */
18 /* 3. Original authors' names are not deleted. */
19 /* 4. The authors' names are not used to endorse or promote products */
20 /* derived from this software without specific prior written */
21 /* permission. */
22 /* */
23 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
24 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
25 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
26 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
27 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
28 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
29 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
30 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
31 /* THIS SOFTWARE. */
32 /* */
33 /************************************************************************/
34 /* */
35 /* Author: Richard Caley (rjc@cstr.ed.ac.uk) */
36 /* Date: February 1997 */
37 /* -------------------------------------------------------------------- */
38 /* */
39 /* Use counted memory chunks and smart pointers to them. */
40 /* */
41 /************************************************************************/
42
43#include <cstdlib>
44#include <iostream>
45#include <cstring>
46#include "EST_Chunk.h"
47
48EST_Chunk::EST_Chunk ()
49{
50 count = 0;
51 memory[0] = '\0';
52 // cerr<<"created " << hex << (int)&memory << "," << dec << size <<"\n";
53}
54
55EST_Chunk::~EST_Chunk ()
56{
57 if (count > 0)
58 {
59 cerr << "deleting chunk with non-zero count\n";
60 exit(1);
61 }
62
63 // cerr << "deleted "<< hex << (int)&memory << "," << dec << size <<"\n";
64}
65
66// private address-of operator - up to friends to keep use counts correct.
67
68EST_Chunk *EST_Chunk::operator & ()
69{
70 return this;
71}
72
73#if !defined(__CHUNK_INLINE_AGGRESSIVELY__)
74
75void EST_Chunk:: operator ++ ()
76{
77#if 0
78 if (++count > MAX_CHUNK_COUNT)
79 {
80 cerr<<"max count exceeded\n";
81 exit(1);
82 }
83#endif
84
85 if (count < MAX_CHUNK_COUNT)
86 {
87 ++count;
88 }
89}
90
91void EST_Chunk::operator -- ()
92{
93 if (count-- == 0)
94 {
95 cerr<<"negative count\n";
96 exit(1);
97 }
98 else if (count == 0)
99 {
100 // cerr<<"deleting\n";
101 delete this;
102 }
103}
104#endif
105
106void *EST_Chunk::operator new (size_t size, int bytes)
107{
108
109 if (bytes > MAX_CHUNK_SIZE)
110 {
111 cerr<<"trying to make chunk of size "<<bytes<<"\n";
112 }
113
114#if defined(__CHUNK_USE_WALLOC__)
115 void *it = walloc(char, size+bytes);
116 ((EST_Chunk *)it) -> malloc_flag = 1;
117#else
118 void *it = new char[size + bytes];
119#endif
120
121 // cerr<<"allocated "<<bytes+size<<" byte for chunk\n";
122
123 ((EST_Chunk *)it) -> size = bytes;
124
125 return it;
126}
127
128void EST_Chunk::operator delete (void *it)
129{
130
131#if defined(__CHUNK_USE_WALLOC__)
132 wfree(it);
133#else
134 delete it;
135#endif
136
137}
138
139 /************************************************************************/
140 /* */
141 /* Now the smart pointers. */
142 /* */
143 /************************************************************************/
144
145#if !defined(__CHUNK_INLINE_AGGRESSIVELY__)
146
147EST_ChunkPtr::EST_ChunkPtr (EST_Chunk *chp)
148{
149 ptr=chp;
150 if (ptr)
151 ++ *ptr;
152}
153
154EST_ChunkPtr::EST_ChunkPtr (const EST_ChunkPtr &cp)
155{
156 ptr=cp.ptr;
157 if (ptr)
158 ++ *ptr;
159}
160
161EST_ChunkPtr::~EST_ChunkPtr (void)
162{
163 if (ptr)
164 {
165 -- *ptr;
166 }
167}
168
169EST_ChunkPtr &EST_ChunkPtr::operator = (EST_ChunkPtr cp)
170{
171 // doing it in this order means self assignment is safe.
172 if (cp.ptr)
173 ++ *(cp.ptr);
174 if (ptr)
175 -- *ptr;
176 ptr=cp.ptr;
177 return *this;
178}
179
180EST_ChunkPtr &EST_ChunkPtr::operator = (EST_Chunk *chp)
181{
182 // doing it in this order means self assignment is safe.
183 if (chp)
184 ++ *chp;
185 if (ptr)
186 -- *ptr;
187 ptr=chp;
188 return *this;
189}
190
191EST_ChunkPtr::operator const char*() const
192{
193 if (ptr)
194 return &(ptr->memory[0]);
195 else
196 return NULL;
197}
198
199EST_ChunkPtr::operator char const*()
200{
201 return ptr?&(ptr->memory[0]):(const char *)NULL;
202}
203
204EST_ChunkPtr::operator char*()
205{
206 if (ptr)
207 {
208 if (ptr->count > 1)
209 {
210 CHUNK_WARN("getting writable version of shared chunk");
211 cp_make_updatable(*this);
212 }
213
214 return &(ptr->memory[0]);
215 }
216 else
217 return NULL;
218}
219
220char &EST_ChunkPtr::operator () (int i) {
221 if (ptr->count>1)
222 {
223 CHUNK_WARN("getting writable version of shared chunk");
224 cp_make_updatable(*this);
225 }
226 return ptr->memory[i];
227 }
228
229#endif
230
231 /************************************************************************/
232 /* */
233 /* Friend function to allocate a chunk in a non count-aware program. */
234 /* */
235 /************************************************************************/
236
237EST_ChunkPtr chunk_allocate(int bytes)
238{
239 EST_Chunk *cp = new(bytes) EST_Chunk;
240
241 return (EST_ChunkPtr)cp;
242}
243
244EST_ChunkPtr chunk_allocate(int bytes, const char *initial, int initial_len)
245{
246 if (initial_len >= bytes)
247 {
248 cerr<<"initialiser too long\n";
249 abort();
250 }
251
252 EST_Chunk *cp = new(bytes) EST_Chunk;
253
254 memcpy(cp->memory, initial, initial_len);
255
256 cp->memory[initial_len] = '\0';
257
258 return (EST_ChunkPtr)cp;
259}
260
261EST_ChunkPtr chunk_allocate(int bytes, const EST_ChunkPtr &initial, int initial_start, int initial_len)
262{
263 if (initial_len >= bytes)
264 {
265 cerr<<"initialiser too long\n";
266 abort();
267 }
268
269 EST_Chunk *cp = new(bytes) EST_Chunk;
270
271 memcpy(cp->memory, initial.ptr->memory + initial_start, initial_len);
272
273 cp->memory[initial_len] = '\0';
274
275 return (EST_ChunkPtr)cp;
276}
277
278 /************************************************************************/
279 /* */
280 /* And one which ensures that a chunk is not shared. Do this before */
281 /* writing to the memory. The first version is told how much of the */
282 /* memory to copy, the second just copies it all. */
283 /* */
284 /************************************************************************/
285
286void cp_make_updatable(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse)
287{
288 if (cp.ptr && cp.ptr->count > 1)
289 {
290 /* Changed 2017/02/17 as ptr-size is often zero (gcc6-O2) */
291 EST_Chunk *newchunk = new(inuse /* cp.ptr->size */) EST_Chunk;
292
293 memcpy(newchunk->memory, cp.ptr->memory, inuse);
294
295 cp = newchunk;
296 }
297}
298
299void cp_make_updatable(EST_ChunkPtr &cp)
300{
301 if (cp.ptr && cp.ptr->count > 1)
302 {
303 EST_Chunk *newchunk = new(cp.ptr->size) EST_Chunk;
304
305 memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
306
307 cp = newchunk;
308 }
309}
310
311 /************************************************************************/
312 /* */
313 /* Make more room in a chunk. If the chunk is already big enough and */
314 /* is unshared then nothing is done. */
315 /* */
316 /************************************************************************/
317
318void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size newsize)
319{
320 if (!cp.ptr || cp.ptr->size < newsize)
321 {
322 if (cp.ptr)
323 cp_make_updatable(cp);
324 EST_Chunk *newchunk = new(newsize) EST_Chunk;
325 memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
326 cp = newchunk;
327 }
328}
329
330void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse, EST_Chunk::EST_chunk_size newsize)
331{
332 if (!cp.ptr || cp.ptr->size < newsize)
333 {
334 if (cp.ptr)
335 cp_make_updatable(cp, inuse);
336 EST_Chunk *newchunk = new(newsize) EST_Chunk;
337 memcpy(newchunk->memory, cp.ptr->memory, inuse);
338 cp = newchunk;
339 }
340}
341
342ostream &operator << (ostream &s, const EST_Chunk &ch)
343{
344 char buff[21];
345
346 if (ch.size<20)
347 {
348 memcpy(buff, ch.memory, ch.size);
349 buff[ch.size]='\0';
350 }
351 else
352 {
353 memcpy(buff, ch.memory, 20);
354 buff[20]='\0';
355 }
356
357 return (s<< "[" << ch.size << "!" << ch.count << "!" << buff << "]");
358}
359
360