Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
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 
48 EST_Chunk::EST_Chunk ()
49 {
50  count = 0;
51  memory[0] = '\0';
52  // cerr<<"created " << hex << (int)&memory << "," << dec << size <<"\n";
53 }
54 
55 EST_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 
68 EST_Chunk *EST_Chunk::operator & ()
69 {
70  return this;
71 }
72 
73 #if !defined(__CHUNK_INLINE_AGGRESSIVELY__)
74 
75 void 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 
91 void 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 
106 void *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 
128 void 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 
147 EST_ChunkPtr::EST_ChunkPtr (EST_Chunk *chp)
148 {
149  ptr=chp;
150  if (ptr)
151  ++ *ptr;
152 }
153 
154 EST_ChunkPtr::EST_ChunkPtr (const EST_ChunkPtr &cp)
155 {
156  ptr=cp.ptr;
157  if (ptr)
158  ++ *ptr;
159 }
160 
161 EST_ChunkPtr::~EST_ChunkPtr (void)
162 {
163  if (ptr)
164  {
165  -- *ptr;
166  }
167 }
168 
169 EST_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 
180 EST_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 
191 EST_ChunkPtr::operator const char*() const
192 {
193  if (ptr)
194  return &(ptr->memory[0]);
195  else
196  return NULL;
197 }
198 
199 EST_ChunkPtr::operator char const*()
200 {
201  return ptr?&(ptr->memory[0]):(const char *)NULL;
202 }
203 
204 EST_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 
220 char &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 
237 EST_ChunkPtr chunk_allocate(int bytes)
238 {
239  EST_Chunk *cp = new(bytes) EST_Chunk;
240 
241  return (EST_ChunkPtr)cp;
242 }
243 
244 EST_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 
261 EST_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 
286 void cp_make_updatable(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse)
287 {
288  if (cp.ptr && cp.ptr->count > 1)
289  {
290  EST_Chunk *newchunk = new(cp.ptr->size) EST_Chunk;
291 
292  memcpy(newchunk->memory, cp.ptr->memory, inuse);
293 
294  cp = newchunk;
295  }
296 }
297 
298 void cp_make_updatable(EST_ChunkPtr &cp)
299 {
300  if (cp.ptr && cp.ptr->count > 1)
301  {
302  EST_Chunk *newchunk = new(cp.ptr->size) EST_Chunk;
303 
304  memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
305 
306  cp = newchunk;
307  }
308 }
309 
310  /************************************************************************/
311  /* */
312  /* Make more room in a chunk. If the chunk is already big enough and */
313  /* is unshared then nothing is done. */
314  /* */
315  /************************************************************************/
316 
317 void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size newsize)
318 {
319  if (!cp.ptr || cp.ptr->size < newsize)
320  {
321  if (cp.ptr)
322  cp_make_updatable(cp);
323  EST_Chunk *newchunk = new(newsize) EST_Chunk;
324  memcpy(newchunk->memory, cp.ptr->memory, cp.ptr->size);
325  cp = newchunk;
326  }
327 }
328 
329 void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse, EST_Chunk::EST_chunk_size newsize)
330 {
331  if (!cp.ptr || cp.ptr->size < newsize)
332  {
333  if (cp.ptr)
334  cp_make_updatable(cp, inuse);
335  EST_Chunk *newchunk = new(newsize) EST_Chunk;
336  memcpy(newchunk->memory, cp.ptr->memory, inuse);
337  cp = newchunk;
338  }
339 }
340 
341 ostream &operator << (ostream &s, const EST_Chunk &ch)
342 {
343  char buff[21];
344 
345  if (ch.size<20)
346  {
347  memcpy(buff, ch.memory, ch.size);
348  buff[ch.size]='\0';
349  }
350  else
351  {
352  memcpy(buff, ch.memory, 20);
353  buff[20]='\0';
354  }
355 
356  return (s<< "[" << ch.size << "!" << ch.count << "!" << buff << "]");
357 }
358 
359