/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/sgx/core/memory/memory.cpp

*/

#include "sgx/core/core.hpp"
#include <cstring>
/**
This is the SGX abstraction for the memory-handling operations, such as
memcpy. This abstractions helps isolate the platform-specific libraries
from the user, and include automatic checking of the area through the
memory watcher. 

  See @sgxDebugRegister
*/
using namespace std;

/**
Move a block of memory from pSrc to pDst. Overlapping blocks are
considered sympathetically, and will not overwrite.
*/
void *sgxMemmove(void *pDest, const void *pSrc, tMEM_SIZE iSize)
{
    sgxCheckForOverwrites(pDest, iSize);
    return memmove(pDest, pSrc, iSize);
}

/**
Copy a block of memory from pSrc to pDest. It is an error to
copy blocks which overlap, as this may produce inconsistent
behaviour between platforms.
*/
void *sgxMemcpy(void *pDest, const void *pSrc, tMEM_SIZE iSize)
{
    tBYTE *pbDest = (tBYTE *)pDest;
    tBYTE *pbSrc  = (tBYTE *)pSrc;

    if ( ( pbSrc < pbDest &&  pbSrc + iSize > pbDest ) || 
         (pbDest < pbSrc  && pbDest + iSize > pbSrc) ) {
        sgxTrace("sgxMemcpy overlaps! We should use sgxMemmove");
        return sgxMemmove(pDest, pSrc, iSize);
    }

    sgxCheckForOverwrites(pDest, iSize);
    return memcpy(pDest, pSrc, iSize);
}

/**
set every byte of memory from @pSrc to @pSrc+@iNum-1 with the
same byte, as found in the lower bits of @iCharacter.
*/
void *sgxMemset(void *pSrc, int iCharacter, tMEM_SIZE iNum)
{
    sgxCheckForOverwrites(pSrc, iNum);
    return memset(pSrc, iCharacter, iNum); 
}

/**
Perform a bitwise compare on the two blocks @pSrc1 and @pSrc2. The
return of 0 means they are equal.
*/
int sgxMemcmp(const void *pSrc1, const void *pSrc2, tMEM_SIZE iNum) 
{ 
    return memcmp(pSrc1, pSrc2, iNum); 
}

/**
Search for the first instance of @iCharacter within the memory block
of @pSrc to @pSrc+@iNum-1.
*/
const void *sgxMemchr(const void *pSrc,  int iCharacter, tMEM_SIZE iNum) 
{ 
    return memchr(pSrc, iCharacter, iNum); 
}

/**
Swap the contents of the memory blocks pointed to by @pSrc1 and @pSrc2.
*/
void sgxMemSwap(const void *pSrc1, const void *pSrc2, tMEM_SIZE iNum) 
{
   tBYTE *pbSrc1 = (tBYTE *)pSrc1;
   tBYTE *pbSrc2  = (tBYTE *)pSrc2;
	tBYTE t;
	tMEM_SIZE count = iNum;

	while(count--) {
		t = *pbSrc1;
		*pbSrc1 = *pbSrc2;
		*pbSrc2 = t;
		++pbSrc1;
		++pbSrc2;
	}
}
