Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. FUNCTION
  3.         <<memset>>---set an area of memory
  4.  
  5. INDEX
  6.         memset
  7.  
  8. ANSI_SYNOPSIS
  9.         #include <string.h>
  10.         void *memset(void *<[dst]>, int <[c]>, size_t <[length]>);
  11.  
  12. TRAD_SYNOPSIS
  13.         #include <string.h>
  14.         void *memset(<[dst]>, <[c]>, <[length]>)
  15.         void *<[dst]>;
  16.         int <[c]>;
  17.         size_t <[length]>;
  18.  
  19. DESCRIPTION
  20.         This function converts the argument <[c]> into an unsigned
  21.         char and fills the first <[length]> characters of the array
  22.         pointed to by <[dst]> to the value.
  23.  
  24. RETURNS
  25.         <<memset>> returns the value of <[dst]>.
  26.  
  27. PORTABILITY
  28. <<memset>> is ANSI C.
  29.  
  30.     <<memset>> requires no supporting OS subroutines.
  31.  
  32. QUICKREF
  33.         memset ansi pure
  34. */
  35.  
  36. #include <string.h>
  37.  
  38. #define LBLOCKSIZE (sizeof(long))
  39. #define UNALIGNED(X)   ((long)X & (LBLOCKSIZE - 1))
  40. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  41.  
  42. _PTR
  43. _DEFUN (memset, (m, c, n),
  44.         _PTR m _AND
  45.         int c _AND
  46.         size_t n)
  47. {
  48.   char *s = (char *) m;
  49.  
  50. #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
  51.   int i;
  52.   unsigned long buffer;
  53.   unsigned long *aligned_addr;
  54.   unsigned int d = c & 0xff;    /* To avoid sign extension, copy C to an
  55.                                    unsigned variable.  */
  56.  
  57.   while (UNALIGNED (s))
  58.     {
  59.       if (n--)
  60.         *s++ = (char) c;
  61.       else
  62.         return m;
  63.     }
  64.  
  65.   if (!TOO_SMALL (n))
  66.     {
  67.       /* If we get this far, we know that n is large and s is word-aligned. */
  68.       aligned_addr = (unsigned long *) s;
  69.  
  70.       /* Store D into each char sized location in BUFFER so that
  71.          we can set large blocks quickly.  */
  72.       buffer = (d << 8) | d;
  73.       buffer |= (buffer << 16);
  74.       for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
  75.         buffer = (buffer << i) | buffer;
  76.  
  77.       /* Unroll the loop.  */
  78.       while (n >= LBLOCKSIZE*4)
  79.         {
  80.           *aligned_addr++ = buffer;
  81.           *aligned_addr++ = buffer;
  82.           *aligned_addr++ = buffer;
  83.           *aligned_addr++ = buffer;
  84.           n -= 4*LBLOCKSIZE;
  85.         }
  86.  
  87.       while (n >= LBLOCKSIZE)
  88.         {
  89.           *aligned_addr++ = buffer;
  90.           n -= LBLOCKSIZE;
  91.         }
  92.       /* Pick up the remainder with a bytewise loop.  */
  93.       s = (char*)aligned_addr;
  94.     }
  95.  
  96. #endif /* not PREFER_SIZE_OVER_SPEED */
  97.  
  98.   while (n--)
  99.     *s++ = (char) c;
  100.  
  101.   return m;
  102. }
  103.