home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / desklib / Libraries / Mem / c / MidExtend < prev    next >
Encoding:
Text File  |  1994-04-10  |  5.4 KB  |  168 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Mem.MidExtend.c
  12.     Author:  Copyright © 1993 Jason Williams
  13.     Version: 1.00 (12 May 1993)
  14.     Purpose: Dynamic memory manager - reallocation
  15. */
  16.  
  17. #include "MemDefs.h"
  18.  
  19. #include <string.h> 
  20.  
  21.  
  22. extern BOOL Mem_MidExtend(mem_anchor *anchor, int at, int by)
  23. /*  Enlarges or reduces a Mem chunk by moving all data beyond 'at' by
  24.  *  'by' bytes up or down in memory. 'at' is an offset within the chunk.
  25.  *
  26.  *  Goes to rather a lot of effort to avoid moving the base address of
  27.  *  this chunk and others, but if mem_autocompact allows, it will compact
  28.  *  if it is absolutely necessary in order to manage the extension.
  29.  *
  30.  *  Returns TRUE if it succeeds
  31.  */
  32. {
  33.   mem_header *chunk, *next, *prev;
  34.   mem_anchor newchunk;
  35.   int         needed;
  36.   char *database;
  37.  
  38.   if (by == 0) return(TRUE);    /* Zero bytes? Certainly sir! Anything else? */
  39.  
  40.   if (at < 0 || !Mem__FindChunk(anchor, &chunk))  return(FALSE);
  41.   if (at > chunk->datasize) return(FALSE);
  42.  
  43.   database = ((char *) chunk) + sizeof(mem_header);
  44.  
  45.  
  46.   /* ------ Reduce chunk ------ */
  47.   if (by < 0)                            /* Reducing the size of the chunk   */
  48.   {
  49.     if (-by > at) by = -at;              /* Can't delete past start of chunk */
  50.  
  51.     memmove(database + at + by, database + at, chunk->datasize - at);
  52.     chunk->datasize += by;               /* Shrink data area of this block   */
  53.  
  54.     Mem__SplitOffFreeChunk(chunk);      /* Return any free space for use    */
  55.     /* The anchor has not changed */
  56.     return(TRUE);
  57.   }
  58.  
  59.  
  60.   /* ------ Extend chunk ------ */
  61.   if ((int) chunk > (int) mem__heap) /* Step 1: merge with prevchunk if free */
  62.   {
  63.     prev = Mem__PrevChunk(chunk);
  64.     if (ISFREE(prev))
  65.     {
  66.       int newsize = prev->realsize + chunk->realsize;
  67.  
  68.       /*  Merge this chunk into the previous (free) chunk, shifting the data
  69.        *  down into it.
  70.        */
  71.       memmove((void *) prev, (void *) chunk, chunk->realsize);
  72.       prev->realsize = newsize;
  73.  
  74.       if (chunk == mem__lastchunk)
  75.         mem__lastchunk = prev;
  76.       else
  77.       {
  78.         next = Mem__NextChunk(prev);
  79.         next->prevrealsize = newsize;
  80.       }
  81.       chunk = prev;
  82.       *anchor = (mem_anchor) ((int)chunk + sizeof(mem_header));
  83.     }
  84.   }
  85.  
  86.  
  87.   if (chunk != mem__lastchunk)      /* Step 2: merge with next chunk if free */
  88.   {
  89.     next = Mem__NextChunk(chunk);
  90.     if (ISFREE(next))
  91.     {
  92.       /*  Next chunk is free, so we merge it onto the end of this one */
  93.  
  94.       chunk->realsize += next->realsize;
  95.       if (next == mem__lastchunk)
  96.         mem__lastchunk = chunk;
  97.       else
  98.       {
  99.         next = Mem__NextChunk(chunk);
  100.         next->prevrealsize = chunk->realsize;
  101.       }
  102.     }
  103.   }
  104.  
  105.  
  106.                    /* Step 3: Allocate more heap space if this is last chunk */
  107.   needed = chunk->datasize + by + sizeof(mem_header);
  108.   if (chunk == mem__lastchunk && chunk->realsize < needed)
  109.   {
  110.     /*  Still too small? This is the last chunk in the heap, so just
  111.      *  extend the heap to make enough room. Note that normally we won't
  112.      *  have data in the last chunk, but the previous 2 steps may have
  113.      *  merged another chunk into the last (free) chunk to try to get
  114.      *  enough memory.
  115.      */
  116.     mem__heapsize = Mem__HeapSize(mem__heapsize + 16 +
  117.                                   (needed - chunk->realsize));
  118.     mem__lastchunk->realsize = mem__heap + mem__heapsize - (int)mem__lastchunk;
  119.   }
  120.  
  121.  
  122.   /* Now, is the resulting chunk big enough to hold the extended data? */
  123.   if (chunk->realsize >= needed)
  124.   {
  125.     memmove(database + at + by, database + at, chunk->datasize - at);
  126.     chunk->datasize += by;               /* Expand data area of this block   */
  127.  
  128.     Mem__SplitOffFreeChunk(chunk);      /* Return any free space for use    */
  129.  
  130.     /* The anchor has not changed */
  131.     return(TRUE);
  132.   }
  133.  
  134.   Mem__SplitOffFreeChunk(chunk);        /* Return any free space for use    */
  135.  
  136.   /*  Still unable to extend the chunk.
  137.    *  Check if we can relocate this chunk into a larger one, compacting
  138.    *  if necessary (but only if we are allowed to by mem_autocompact)
  139.    */
  140.  
  141.   Mem_Alloc(&newchunk, chunk->datasize + by);
  142.   if (newchunk == NULL)
  143.   {
  144.     /*  **** Exercise for the reader
  145.      *  We can't just grab another chunk of large enough size.
  146.      *  At this point, we really should (if allowed) compact the
  147.      *  heap, extend the heap if necessary, then shift everything
  148.      *  above 'chunk' up enough to extend the chunk as needed.
  149.      *  However, this takes a bit of effort on my part, and also will
  150.      *  add a large bit of code to this function, so I have not yet
  151.      *  implemented it
  152.      */
  153.  
  154.      return(FALSE);
  155.   }
  156.  
  157.   memmove((char *) newchunk, database, at);         /* Copy 1st part of data */
  158.   memmove((char *) ((int) newchunk) + at + by,      /* Copy 2nd part of data */
  159.           database + at, chunk->datasize - at);
  160.  
  161.   Mem_Free(anchor);
  162.   *anchor = newchunk;
  163.   Mem__FindChunk(&newchunk, &chunk);
  164.   chunk->handle = anchor;
  165.  
  166.   return(TRUE);
  167. }
  168.