mem.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 Martin Decky
00003  * Copyright (c) 2008 Jiri Svoboda
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * - Redistributions of source code must retain the above copyright
00011  *   notice, this list of conditions and the following disclaimer.
00012  * - Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in the
00014  *   documentation and/or other materials provided with the distribution.
00015  * - The name of the author may not be used to endorse or promote products
00016  *   derived from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00019  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00023  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00027  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00036 #include <mem.h>
00037 #include <stdlib.h>
00038 #include <sys/types.h>
00039 
00041 void *memset(void *dest, int b, size_t n)
00042 {
00043         char *pb;
00044         unsigned long *pw;
00045         size_t word_size;
00046         size_t n_words;
00047 
00048         unsigned long pattern;
00049         size_t i;
00050         size_t fill;
00051 
00052         /* Fill initial segment. */
00053         word_size = sizeof(unsigned long);
00054         fill = word_size - ((uintptr_t) dest & (word_size - 1));
00055         if (fill > n) fill = n;
00056 
00057         pb = dest;
00058 
00059         i = fill;
00060         while (i-- != 0)
00061                 *pb++ = b;
00062 
00063         /* Compute remaining size. */
00064         n -= fill;
00065         if (n == 0) return dest;
00066 
00067         n_words = n / word_size;
00068         n = n % word_size;
00069         pw = (unsigned long *) pb;
00070 
00071         /* Create word-sized pattern for aligned segment. */
00072         pattern = 0;
00073         i = word_size;
00074         while (i-- != 0)
00075                 pattern = (pattern << 8) | (uint8_t) b;
00076 
00077         /* Fill aligned segment. */
00078         i = n_words;
00079         while (i-- != 0)
00080                 *pw++ = pattern;
00081 
00082         pb = (char *) pw;
00083 
00084         /* Fill final segment. */
00085         i = n;
00086         while (i-- != 0)
00087                 *pb++ = b;
00088 
00089         return dest;
00090 }
00091 
00092 struct along {
00093         unsigned long n;
00094 } __attribute__ ((packed));
00095 
00096 static void *unaligned_memcpy(void *dst, const void *src, size_t n)
00097 {
00098         size_t i, j;
00099         struct along *adst = dst;
00100         const struct along *asrc = src;
00101 
00102         for (i = 0; i < n / sizeof(unsigned long); i++)
00103                 adst[i].n = asrc[i].n;
00104                 
00105         for (j = 0; j < n % sizeof(unsigned long); j++)
00106                 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
00107                     ((unsigned char *) (((unsigned long *) src) + i))[j];
00108                 
00109         return (char *) dst;
00110 }
00111 
00113 void *memcpy(void *dst, const void *src, size_t n)
00114 {
00115         size_t i;
00116         size_t mod, fill;
00117         size_t word_size;
00118         size_t n_words;
00119 
00120         const unsigned long *srcw;
00121         unsigned long *dstw;
00122         const uint8_t *srcb;
00123         uint8_t *dstb;
00124 
00125         word_size = sizeof(unsigned long);
00126 
00127         /*
00128          * Are source and destination addresses congruent modulo word_size?
00129          * If not, use unaligned_memcpy().
00130          */
00131 
00132         if (((uintptr_t) dst & (word_size - 1)) !=
00133             ((uintptr_t) src & (word_size - 1)))
00134                 return unaligned_memcpy(dst, src, n);
00135 
00136         /*
00137          * mod is the address modulo word size. fill is the length of the
00138          * initial buffer segment before the first word boundary.
00139          * If the buffer is very short, use unaligned_memcpy(), too.
00140          */
00141 
00142         mod = (uintptr_t) dst & (word_size - 1);
00143         fill = word_size - mod;
00144         if (fill > n) fill = n;
00145 
00146         /* Copy the initial segment. */
00147 
00148         srcb = src;
00149         dstb = dst;
00150 
00151         i = fill;
00152         while (i-- != 0)
00153                 *dstb++ = *srcb++;
00154 
00155         /* Compute remaining length. */
00156 
00157         n -= fill;
00158         if (n == 0) return dst;
00159 
00160         /* Pointers to aligned segment. */
00161 
00162         dstw = (unsigned long *) dstb;
00163         srcw = (const unsigned long *) srcb;
00164 
00165         n_words = n / word_size;        /* Number of whole words to copy. */
00166         n -= n_words * word_size;       /* Remaining bytes at the end. */
00167 
00168         /* "Fast" copy. */
00169         i = n_words;
00170         while (i-- != 0)
00171                 *dstw++ = *srcw++;
00172 
00173         /*
00174          * Copy the rest.
00175          */
00176 
00177         srcb = (const uint8_t *) srcw;
00178         dstb = (uint8_t *) dstw;
00179 
00180         i = n;
00181         while (i-- != 0)
00182                 *dstb++ = *srcb++;
00183 
00184         return dst;
00185 }
00186 
00188 void *memmove(void *dst, const void *src, size_t n)
00189 {
00190         const uint8_t *sp;
00191         uint8_t *dp;
00192 
00193         /* Nothing to do? */
00194         if (src == dst)
00195                 return dst;
00196 
00197         /* Non-overlapping? */
00198         if (dst >= src + n || src >= dst + n) { 
00199                 return memcpy(dst, src, n);
00200         }
00201 
00202         /* Which direction? */
00203         if (src > dst) {
00204                 /* Forwards. */
00205                 sp = src;
00206                 dp = dst;
00207 
00208                 while (n-- != 0)
00209                         *dp++ = *sp++;
00210         } else {
00211                 /* Backwards. */
00212                 sp = src + (n - 1);
00213                 dp = dst + (n - 1);
00214 
00215                 while (n-- != 0)
00216                         *dp-- = *sp--;
00217         }
00218 
00219         return dst;
00220 }
00221 
00233 int bcmp(const void *s1, const void *s2, size_t len)
00234 {
00235         uint8_t *u1 = (uint8_t *) s1;
00236         uint8_t *u2 = (uint8_t *) s2;
00237         
00238         for (; (len != 0) && (*u1++ == *u2++); len--);
00239         
00240         return len;
00241 }
00242 

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7