// SimpleHeap.cpp
//
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
typedef struct __HeapHdr__ {
<ul class="see-also">
<li>truct __HeapHdr__ *next;</li>
<li>truct __HeapHdr__ *prev;</li>
</ul>
unsigned int size;
unsigned int used;
// Usable data area starts here
} HeapHdr_t;
HeapHdr_t *Init_SimpleHeap( void *memory, unsigned int initial_size) {
HeapHdr_t *root;
root = (HeapHdr_t *) memory;
root->next = NULL;
root->prev = NULL;
root->size = initial_size - sizeof(HeapHdr_t);
root->used = 0;
return root;
}
void *SimpleHeap_alloc( size_t s, HeapHdr_t *root ) {
HeapHdr_t *p;
HeapHdr_t *np;
p = root;
// run through the whole list of blocks to the end
while ( NULL != p ) {
// if this block is not used and large enough
if ( (0 == p->used) && (s < p->size + sizeof(HeapHdr_t)) ) {
// a new block is generated for the remaining
// free memory and added to the end of the memory to be used
// in the list
np = (HeapHdr_t *) ((unsigned char *)p + sizeof(HeapHdr_t) + s);
// the successor remains the same
np->next = p->next;
// the successor of block p now has to refer to the new
// block np if there is a successor
if ( NULL != p->next )
p->next->prev = np;
// The predecessor of np is p
np->prev = p;
// the new block is the same size as the memory that is still free
// and unused
np->size = p->size - s - sizeof(HeapHdr_t);
np->used = 0;
// once the new block has been created for the remaining
// memory, the old block can be used
p->size = s;
p->used = 1;
p->next = np;
// the pointer for the usable data area is returned to the
// user
return (void*) ((unsigned char*)p + sizeof(HeapHdr_t) );
}
// view next block
p = p->next;
} // while
// if no useful block is found, the
// function returns NULL
return NULL;
}
void SimpleHeap_free( void *userp ) {
HeapHdr_t *hdr;
// the pointer transferred to the user is actually a pointer to
// hdr->usermem. You can get the correct pointer for hdr by
// moving the user pointer forwards by the size of the
// header
hdr = (HeapHdr_t *) ( (unsigned char *)userp - sizeof(HeapHdr_t) );
// the following step releases the memory area again
// so that it can be reused
hdr->used = 0;
// Tests whether the subsequent block is free
if ( 0 == hdr->next->used ) {
// new size of this block from the sum of both
hdr->size += hdr->next->size + sizeof(HeapHdr_t);
// Now, the next block has to be removed from the doubly
// linked list. First the prev pointer for the
// predecessor of the next block is changed for this block:
if ( NULL != hdr->next->next )
hdr->next->next->prev = hdr->next->prev;
// Now, the current successor is made into the successor of
// the next block:
hdr->next = hdr->next->next
// Now, the block hdr->next is removed from the doubly linked
// list
}
}
#define HEAP_SIZE ( 4096 * 1024 )
int _tmain(int argc, _TCHAR* argv[])
{
void *myHeap;
HeapHdr_t *myRoot;
HANDLE hFile;
unsigned int width, height;
unsigned int bytesIn;
unsigned char *image;
if ( 2 != argc )
{
fprintf( stderr, "Usage: %s <filename>\n", argv[0] );
return ( -2 );
}
if ( NULL == ( myHeap = LocalAlloc( LPTR, HEAP_SIZE ) ) )
{
fprintf( stderr, "LocalAlloc failed\n");
return ( -1 );
}
printf( "Initialize SimpleHeap ...\n" );
myRoot = Init_SimpleHeap( myHeap, HEAP_SIZE );
// Open file
if ( INVALID_HANDLE_VALUE ==
( hFile = CreateFile( argv[1], FILE_READ_DATA, 0, 0,
OPEN_EXISTING, 0, 0 ) ) )
{
fprintf( stderr, "Failed to open %s\n", argv[1] );
return ( -3 );
}
// Read width of image
if ( ! ReadFile( hFile, &width, sizeof(width), (LPDWORD) &bytesIn, 0 ) ) {
fprintf( stderr, "Failed to read width from file\n" );
return ( -4 );
}
// Read height of image
if ( ! ReadFile(hFile, &height, sizeof(height), (LPDWORD) &bytesIn, 0 ) ) {
fprintf( stderr, "Failed to read height from file\n" );
return ( -5 );
}
// Reserve memory on SimpleHeap
printf("Reserve memory for %u x %u Pixel: %u Bytes\n", width, height, width*height);
image = ( unsigned char * ) SimpleHeap_alloc( width * height, myRoot );
printf( "pointer *image = %p\n", image );
// Read image
for ( unsigned int i = 0; i < height; i++ ) {
// Reserve memory for a line of image
printf( "Reserve %u bytes for one image line\n", width );
line = ( unsigned char *) SimpleHeap_alloc( width, myRoot );
printf( "pointer *line = %p\n", line );
if ( ! ReadFile( hFile, line, width, (LPDWORD) &bytesIn, 0 ) ) {
fprintf( stderr, "Failed to read image line %u\n", i );
return ( -6 );
}
// Copy data to image
memcpy( image + ( i * width ), line, bytesIn );
// Release memory again
SimpleHeap_free( line );
if ( bytesIn != width ) {
fprintf( stderr, "Short or broken image\n" );
return ( -7 );
}
}
SimpleHeap_free( image );
//
// end use of memory
//
LocalFree( (HLOCAL) myHeap );
return 0;
}