Main Page | File List | Globals

src/string.c

Go to the documentation of this file.
00001 /*
00002      This file is part of PlibC.
00003      (C) 2005 Nils Durner (and other contributing authors)
00004 
00005            This library is free software; you can redistribute it and/or
00006            modify it under the terms of the GNU Lesser General Public
00007            License as published by the Free Software Foundation; either
00008            version 2.1 of the License, or (at your option) any later version.
00009         
00010            This library is distributed in the hope that it will be useful,
00011            but WITHOUT ANY WARRANTY; without even the implied warranty of
00012            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013            Lesser General Public License for more details.
00014         
00015            You should have received a copy of the GNU Lesser General Public
00016            License along with this library; if not, write to the Free Software
00017            Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00025 #include "plibc_private.h"
00026 
00027 #if !HAVE_STRNDUP
00028 
00033 char *strndup (const char *s, size_t n)
00034 {
00035   size_t len = strnlen (s, n);
00036   char *new = (char *) malloc (len + 1);
00037 
00038   if (new == NULL)
00039     return NULL;
00040 
00041   new[len] = '\0';
00042   return (char *) memcpy (new, s, len);
00043 }
00044 #endif
00045 
00046 #if !HAVE_STRNLEN
00047 
00051 size_t strnlen (const char *str, size_t maxlen)
00052 {
00053   const char *char_ptr, *end_ptr = str + maxlen;
00054   const unsigned long int *longword_ptr;
00055   unsigned long int longword, magic_bits, himagic, lomagic;
00056 
00057   if (maxlen == 0)
00058     return 0;
00059 
00060   if (__builtin_expect (end_ptr < str, 0))
00061     end_ptr = (const char *) ~0UL;
00062 
00063   /* Handle the first few characters by reading one character at a time.
00064      Do this until CHAR_PTR is aligned on a longword boundary.  */
00065   for (char_ptr = str; ((unsigned long int) char_ptr
00066                         & (sizeof (longword) - 1)) != 0;
00067        ++char_ptr)
00068     if (*char_ptr == '\0')
00069       {
00070         if (char_ptr > end_ptr)
00071           char_ptr = end_ptr;
00072         return char_ptr - str;
00073       }
00074 
00075   /* All these elucidatory comments refer to 4-byte longwords,
00076      but the theory applies equally well to 8-byte longwords.  */
00077 
00078   longword_ptr = (unsigned long int *) char_ptr;
00079 
00080   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
00081      the "holes."  Note that there is a hole just to the left of
00082      each byte, with an extra at the end:
00083 
00084      bits:  01111110 11111110 11111110 11111111
00085      bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
00086 
00087      The 1-bits make sure that carries propagate to the next 0-bit.
00088      The 0-bits provide holes for carries to fall into.  */
00089   magic_bits = 0x7efefeffL;
00090   himagic = 0x80808080L;
00091   lomagic = 0x01010101L;
00092   if (sizeof (longword) > 4)
00093     {
00094       /* 64-bit version of the magic.  */
00095       /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
00096       magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
00097       himagic = ((himagic << 16) << 16) | himagic;
00098       lomagic = ((lomagic << 16) << 16) | lomagic;
00099     }
00100   if (sizeof (longword) > 8)
00101     abort ();
00102 
00103   /* Instead of the traditional loop which tests each character,
00104      we will test a longword at a time.  The tricky part is testing
00105      if *any of the four* bytes in the longword in question are zero.  */
00106   while (longword_ptr < (unsigned long int *) end_ptr)
00107     {
00108       /* We tentatively exit the loop if adding MAGIC_BITS to
00109          LONGWORD fails to change any of the hole bits of LONGWORD. */
00110 
00111       longword = *longword_ptr++;
00112 
00113       if ((longword - lomagic) & himagic)
00114         {
00115           /* Which of the bytes was the zero?  If none of them were, it was
00116              a misfire; continue the search.  */
00117 
00118           const char *cp = (const char *) (longword_ptr - 1);
00119 
00120           char_ptr = cp;
00121           if (cp[0] == 0)
00122             break;
00123           char_ptr = cp + 1;
00124           if (cp[1] == 0)
00125             break;
00126           char_ptr = cp + 2;
00127           if (cp[2] == 0)
00128             break;
00129           char_ptr = cp + 3;
00130           if (cp[3] == 0)
00131             break;
00132           if (sizeof (longword) > 4)
00133             {
00134               char_ptr = cp + 4;
00135               if (cp[4] == 0)
00136                 break;
00137               char_ptr = cp + 5;
00138               if (cp[5] == 0)
00139                 break;
00140               char_ptr = cp + 6;
00141               if (cp[6] == 0)
00142                 break;
00143               char_ptr = cp + 7;
00144               if (cp[7] == 0)
00145                 break;
00146             }
00147         }
00148       char_ptr = end_ptr;
00149     }
00150 
00151   if (char_ptr > end_ptr)
00152     char_ptr = end_ptr;
00153   return char_ptr - str;
00154 }
00155 #endif
00156 
00157 /* end of string.c */

Generated on Sun Sep 4 11:16:47 2005 for PlibC by  doxygen 1.4.2