PageRenderTime 60ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vrq-1.0.88/src/cobstack.cc

#
C++ | 365 lines | 229 code | 36 blank | 100 comment | 25 complexity | 8b0ea399ce13f5bec5e03a7e1e6a41dd MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. /*****************************************************************************
  2. * Copyright (C) 1997-2007, Mark Hummel
  3. * This file is part of Vrq.
  4. *
  5. * Vrq is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * Vrq is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. * Boston, MA 02110-1301 USA
  19. *****************************************************************************
  20. */
  21. /******************************************************************************
  22. *
  23. *
  24. * cobstack.cpp
  25. * - methods for stack-like bulk allocation
  26. *
  27. *
  28. ******************************************************************************
  29. */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include "glue.h"
  33. #include "cobstack.h"
  34. #include "lex.h"
  35. list<CObstack*>* CObstack::obstackList = NULL; ///< list of all obstacks
  36. /*****************************************************************************
  37. OnExitDumpStats
  38. - on exit dump memory allocation stats
  39. *****************************************************************************/
  40. void CObstack::_OnExitDumpStats()
  41. {
  42. printf( "Obstack Statistics\n" );
  43. printf( "==================\n" );
  44. if( !obstackList ) {
  45. return;
  46. }
  47. list<CObstack*>::iterator ptr;
  48. for( ptr = obstackList->begin(); ptr != obstackList->end(); ++ptr ) {
  49. (*ptr)->DumpStats();
  50. }
  51. }
  52. void CObstack::OnExitDumpStats()
  53. {
  54. atexit( _OnExitDumpStats );
  55. }
  56. /*****************************************************************************
  57. DumpStats
  58. - dump memory allocation stats
  59. *****************************************************************************/
  60. void CObstack::DumpStats()
  61. {
  62. printf( "obstack: %s\n", name.c_str() );
  63. Chunk_t* cptr = currentChunk;
  64. int finalChunkCount = 0;
  65. int finalByteCount = 0;
  66. while( cptr ) {
  67. finalChunkCount++;
  68. finalByteCount += cptr->freeOffset;
  69. cptr = cptr->next;
  70. }
  71. printf( " final chunk count: %d\n", finalChunkCount );
  72. printf( " final byte count: %d\n", finalByteCount );
  73. printf( " max byte count: %d\n", maxChunkCount * defaultSize );
  74. }
  75. /*****************************************************************************
  76. Constructor
  77. - initialize obstack with given chunksize
  78. *****************************************************************************/
  79. CObstack::CObstack( const char* name, int defaultChunkSize ) :
  80. name(name)
  81. {
  82. Chunk_t *chunk;
  83. defaultSize = defaultChunkSize;
  84. chunk = (Chunk_t*) shell_xmalloc( defaultSize );
  85. chunkCount = 1;
  86. maxChunkCount = 1;
  87. chunk->next = NULL;
  88. chunk->freeOffset = 0;
  89. chunk->objectOffset = 0;
  90. chunk->size = defaultSize - (sizeof(Chunk_t) - 4);
  91. alignment = 8; /* Sparcs like 8 */
  92. currentChunk = chunk;
  93. if( !obstackList ) {
  94. obstackList = new list<CObstack*>();
  95. }
  96. obstackList->push_back( this );
  97. }
  98. /*****************************************************************************
  99. Destructor
  100. - free memory
  101. *****************************************************************************/
  102. CObstack::~CObstack( void )
  103. {
  104. Chunk_t* chunk;
  105. while( currentChunk ) {
  106. chunk = currentChunk;
  107. currentChunk = chunk->next;
  108. shell_xfree( chunk, defaultSize );
  109. }
  110. obstackList->remove( this );
  111. }
  112. /****************************************************************************
  113. NextFree
  114. - return next free byte
  115. ****************************************************************************/
  116. void* CObstack::NextFree( void )
  117. {
  118. Chunk_t *chunk;
  119. MASSERT( currentChunk != NULL );
  120. chunk = currentChunk;
  121. MASSERT( chunk->freeOffset <= chunk->size );
  122. MASSERT( chunk->objectOffset <= chunk->size );
  123. MASSERT( chunk->freeOffset >= 0 );
  124. MASSERT( chunk->objectOffset >= 0 );
  125. return( &chunk->data[chunk->freeOffset] );
  126. }
  127. /***************************************************************************
  128. GetBase
  129. - return base of current object
  130. ***************************************************************************/
  131. void* CObstack::GetBase( void )
  132. {
  133. Chunk_t *chunk;
  134. MASSERT( currentChunk != NULL );
  135. chunk = currentChunk;
  136. MASSERT( chunk->freeOffset <= chunk->size );
  137. MASSERT( chunk->objectOffset <= chunk->size );
  138. MASSERT( chunk->freeOffset >= 0 );
  139. MASSERT( chunk->objectOffset >= 0 );
  140. return( &chunk->data[chunk->objectOffset] );
  141. }
  142. /*************************************************************************
  143. PtrGrow
  144. - grow obstack by one pointer and copy object ptr into it
  145. *************************************************************************/
  146. void CObstack::PtrGrow( void *object )
  147. {
  148. Grow( &object, sizeof(object) );
  149. }
  150. /************************************************************************
  151. GetObjectSize
  152. - return size of current object
  153. ************************************************************************/
  154. INT32 CObstack::GetObjectSize( void )
  155. {
  156. Chunk_t *chunk;
  157. MASSERT( currentChunk != NULL );
  158. chunk = currentChunk;
  159. MASSERT( chunk->freeOffset <= chunk->size );
  160. MASSERT( chunk->objectOffset <= chunk->size );
  161. MASSERT( chunk->freeOffset >= 0 );
  162. MASSERT( chunk->objectOffset >= 0 );
  163. return( chunk->freeOffset - chunk->objectOffset );
  164. }
  165. /***********************************************************************
  166. Copy
  167. - copy object into obstack, returns ptr to data in obstack
  168. ***********************************************************************/
  169. void* CObstack::Copy( const void *object, INT32 size )
  170. {
  171. void *ptr;
  172. ptr = Alloc( size );
  173. memcpy( ptr, object, size );
  174. return( ptr );
  175. }
  176. /****************************************************************************
  177. Copy0
  178. - copy object into obstack with null terminator, returns
  179. ptr to data in obstack
  180. ****************************************************************************/
  181. void* CObstack::Copy0( const void *object, INT32 size )
  182. {
  183. void *ptr;
  184. ptr = Alloc( size+1 );
  185. memcpy( ptr, object, size );
  186. ((char*)ptr)[size] = 0;
  187. return( ptr );
  188. }
  189. /***************************************************************************
  190. Finish
  191. - finalize object by advance object base to next free
  192. spot(aligned)
  193. ***************************************************************************/
  194. void* CObstack::Finish( void )
  195. {
  196. Chunk_t* chunk;
  197. INT32 offset;
  198. INT32 startOffset;
  199. MASSERT( currentChunk != NULL );
  200. chunk = currentChunk;
  201. MASSERT( chunk->freeOffset <= chunk->size );
  202. MASSERT( chunk->objectOffset <= chunk->size );
  203. MASSERT( chunk->freeOffset >= 0 );
  204. MASSERT( chunk->objectOffset >= 0 );
  205. offset = chunk->freeOffset;
  206. startOffset = chunk->objectOffset;
  207. offset = ((offset + alignment -1 )/alignment) * alignment;
  208. if( offset > chunk->size ) {
  209. offset = chunk->size;
  210. }
  211. chunk->freeOffset = offset;
  212. chunk->objectOffset = offset;
  213. return( &chunk->data[startOffset] );
  214. }
  215. /*************************************************************************
  216. Alloc
  217. - allocate space and advance object. return start of object
  218. **************************************************************************/
  219. void* CObstack::Alloc( INT32 size )
  220. {
  221. void *ptr;
  222. ptr = GrowChunk( size );
  223. MASSERT( ptr == GetBase() );
  224. return( Finish() );
  225. }
  226. /**************************************************************************
  227. Grow
  228. - append data to current object
  229. **************************************************************************/
  230. void CObstack::Grow( const void *data, INT32 size )
  231. {
  232. void *ptr;
  233. ptr = GrowChunk( size );
  234. memcpy( ptr, data, size );
  235. }
  236. /**************************************************************************
  237. Grow
  238. - append empty space to current object
  239. **************************************************************************/
  240. void CObstack::Grow( INT32 size )
  241. {
  242. GrowChunk( size );
  243. }
  244. /**************************************************************************
  245. Free
  246. - free all storage after and including object
  247. if object is NULL, free all
  248. ***************************************************************************/
  249. void CObstack::Free( void *object )
  250. {
  251. Chunk_t *chunk;
  252. MASSERT( currentChunk != NULL );
  253. chunk = currentChunk;
  254. while( chunk && chunk->next ) {
  255. MASSERT( chunk->freeOffset >= 0 );
  256. MASSERT( chunk->objectOffset >= 0 );
  257. MASSERT( chunk->freeOffset <= chunk->size );
  258. MASSERT( chunk->objectOffset <= chunk->size );
  259. if( (char*)object >= &chunk->data[0] && ((char*)object <= (&chunk->data[0] + chunk->size)) ) {
  260. break;
  261. }
  262. currentChunk = chunk->next;
  263. shell_xfree( chunk, defaultSize );
  264. chunkCount--;
  265. chunk = currentChunk;
  266. }
  267. if( object == NULL ) {
  268. chunk->freeOffset = 0;
  269. chunk->objectOffset = 0;
  270. } else {
  271. MASSERT( (char*)object >= &chunk->data[0] && ((char*)object <= (&chunk->data[0] + chunk->size)) );
  272. chunk->objectOffset = (char*)object - &chunk->data[0];
  273. chunk->freeOffset = chunk->objectOffset;
  274. }
  275. }
  276. /***************************************************************************
  277. GrowChunk
  278. - make room for data, allocate new hunk if needed
  279. ****************************************************************************/
  280. void* CObstack::GrowChunk( INT32 size )
  281. {
  282. Chunk_t *chunk;
  283. Chunk_t *newChunk;
  284. INT32 currentSize;
  285. INT32 newSize;
  286. void* ptr;
  287. MASSERT( currentChunk != NULL );
  288. chunk = currentChunk;
  289. MASSERT( chunk->freeOffset <= chunk->size );
  290. MASSERT( chunk->objectOffset <= chunk->size );
  291. MASSERT( chunk->freeOffset >= 0 );
  292. MASSERT( chunk->objectOffset >= 0 );
  293. if( chunk->size - chunk->freeOffset < size ) {
  294. newSize = defaultSize - (sizeof(Chunk_t) + 4);
  295. if( newSize < size + GetObjectSize() ) {
  296. newSize = (size + GetObjectSize())*4;
  297. }
  298. currentSize = chunk->freeOffset - chunk->objectOffset;
  299. newChunk = (Chunk_t*) shell_xmalloc( newSize + (sizeof(Chunk_t)-4) );
  300. chunkCount++;
  301. if( chunkCount > maxChunkCount ) {
  302. maxChunkCount = chunkCount;
  303. }
  304. newChunk->next = chunk;
  305. newChunk->freeOffset = currentSize;
  306. newChunk->objectOffset = 0;
  307. newChunk->size = newSize;
  308. memcpy( &newChunk->data[0], &chunk->data[chunk->objectOffset], currentSize );
  309. currentChunk = newChunk;
  310. chunk = newChunk;
  311. }
  312. MASSERT( chunk->freeOffset+size <= chunk->size );
  313. ptr = &chunk->data[chunk->freeOffset];
  314. chunk->freeOffset += size;
  315. return( ptr );
  316. }
  317. /***************************************************************************
  318. IsOwner
  319. - return non-zero if this pointer was allocated from this obstack
  320. ****************************************************************************/
  321. int CObstack::IsOwner( void* ptr)
  322. {
  323. for( Chunk_t *chunk = currentChunk; chunk; chunk = chunk->next ) {
  324. if( ptr >= &chunk->data[0] && ptr < &chunk->data[chunk->freeOffset] ) {
  325. return TRUE;
  326. }
  327. }
  328. return FALSE;
  329. }