about summary refs log tree commit diff
path: root/lib/util
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-06-27 21:05:14 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-06-27 21:05:14 +0000
commit4e5f07abc5cdc1f076eb8713c75823fd2097d911 (patch)
tree1e640322b516eeab31c58aad886edd3932814efe /lib/util
parent3ecf4ceb636585673b6eec27c1e56f85dc6d2dfe (diff)
downloadnetpbm-mirror-4e5f07abc5cdc1f076eb8713c75823fd2097d911.tar.gz
netpbm-mirror-4e5f07abc5cdc1f076eb8713c75823fd2097d911.tar.xz
netpbm-mirror-4e5f07abc5cdc1f076eb8713c75823fd2097d911.zip
Release 10.47.00: rebase to trunk
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@944 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/util')
-rw-r--r--lib/util/intcode.h203
-rw-r--r--lib/util/nstring.h12
-rw-r--r--lib/util/wordaccess.h30
-rw-r--r--lib/util/wordaccess_64_le.h48
-rw-r--r--lib/util/wordaccess_gcc3_be.h17
-rw-r--r--lib/util/wordaccess_gcc3_le.h56
-rw-r--r--lib/util/wordaccess_generic.h74
7 files changed, 217 insertions, 223 deletions
diff --git a/lib/util/intcode.h b/lib/util/intcode.h
index 0ee70932..dd42f669 100644
--- a/lib/util/intcode.h
+++ b/lib/util/intcode.h
@@ -1,10 +1,78 @@
 #ifndef INTCODE_H_INCLUDED
 #define INTCODE_H_INCLUDED
 
-#include "pm_config.h"  /* For uint32_t, BYTE_ORDER */
+#include "pm_config.h"  /* For uint32_t, BYTE_ORDER, HAVE_INT64 */
 
 static unsigned int const pm_byteOrder = BYTE_ORDER;
 
+typedef struct {
+/*----------------------------------------------------------------------------
+   This is a big-endian representation of a 16 bit integer.  I.e.
+   bytes[0] is the most significant 8 bits; bytes[1] is the least
+   significant 8 bits of the number in pure binary.
+
+   On a big-endian machines, this is bit for bit identical to uint16_t.
+   On a little-endian machine, it isn't.
+
+   This is an important data type because decent file formats use
+   big-endian -- they don't care if some CPU happens to use some other
+   code for its own work.
+-----------------------------------------------------------------------------*/
+    unsigned char bytes[2];
+} bigend16;
+
+
+static __inline__ uint16_t
+pm_uintFromBigend16(bigend16 const arg) {
+
+    uint16_t retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            bigend16 bigend;
+            uint16_t native;
+        } converter;
+        converter.bigend = arg;
+        retval = converter.native;
+    } break;
+
+    default: {
+        retval =
+            (arg.bytes[0] << 8) |
+            (arg.bytes[1] << 0);
+    }
+    }
+    return retval;
+}
+
+
+
+static __inline__ bigend16
+pm_bigendFromUint16(uint16_t const arg) {
+
+    bigend16 retval;
+
+    switch (pm_byteOrder) {
+    case BIG_ENDIAN: {
+        union {
+            bigend16 bigend;
+            uint16_t native;
+        } converter;
+        converter.native = arg;
+        retval = converter.bigend;
+    } break;
+
+    default: {
+        uint16_t shift;
+        shift = arg;
+        retval.bytes[1] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[0] = shift;  /* Takes lower 8 bits */
+    }
+    }
+    return retval;
+}
 
 typedef struct {
 /*----------------------------------------------------------------------------
@@ -34,19 +102,30 @@ pm_uintFromBigend32(bigend32 const arg) {
             bigend32 bigend;
             uint32_t native;
         } converter;
-        
         converter.bigend = arg;
-        
         retval = converter.native;
-    }; break;
+    } break;
+
+#if HAVE_GCC_BSWAP
     case LITTLE_ENDIAN: {
+        /* Use GCC built-in */  
+        union {
+            bigend32 bigend;
+            uint32_t native;
+        } converter;
+        converter.bigend = arg;
+        retval = __builtin_bswap32(converter.native);
+    } break;
+#endif
+    
+    default:
         retval =
             (arg.bytes[0] << 24) |
             (arg.bytes[1] << 16) |
             (arg.bytes[2] <<  8) |
             (arg.bytes[3] <<  0);
-    } break;
     }
+
     return retval;
 }
 
@@ -63,12 +142,23 @@ pm_bigendFromUint32(uint32_t const arg) {
             bigend32 bigend;
             uint32_t native;
         } converter;
-        
         converter.native = arg;
-
         retval = converter.bigend;
     } break;
+
+#if HAVE_GCC_BSWAP    
     case LITTLE_ENDIAN: {
+        /* Use GCC built-in */  
+        union {
+            bigend32 bigend;
+            uint32_t native;
+        } converter;
+        converter.native = __builtin_bswap32(arg);
+        retval = converter.bigend;
+    } break;
+#endif    
+
+    default: {
         uint32_t shift;
         shift = arg;
         retval.bytes[3] = shift;  /* Takes lower 8 bits */
@@ -78,80 +168,127 @@ pm_bigendFromUint32(uint32_t const arg) {
         retval.bytes[1] = shift;  /* Takes lower 8 bits */
         shift >>= 8;
         retval.bytes[0] = shift;  /* Takes lower 8 bits */
-    } break;
+    }
     }
     return retval;
 }
 
+
+#if HAVE_INT64
+
 typedef struct {
 /*----------------------------------------------------------------------------
-   This is a big-endian representation of a 16 bit integer.  I.e.
-   bytes[0] is the most significant 8 bits; bytes[1] is the least
+   This is a big-endian representation of a 64 bit integer.  I.e.
+   bytes[0] is the most significant 8 bits; bytes[7] is the least
    significant 8 bits of the number in pure binary.
 
-   On a big-endian machines, this is bit for bit identical to uint16_t.
+   On a big-endian machines, this is bit for bit identical to uint64_t.
    On a little-endian machine, it isn't.
 
    This is an important data type because decent file formats use
    big-endian -- they don't care if some CPU happens to use some other
    code for its own work.
+
+   uint64_t is supported only when available.
 -----------------------------------------------------------------------------*/
-    unsigned char bytes[2];
-} bigend16;
+    unsigned char bytes[8];
+} bigend64;
 
 
-static __inline__ uint16_t
-pm_uintFromBigend16(bigend16 const arg) {
+static __inline__ uint64_t
+pm_uintFromBigend64(bigend64 const arg) {
 
-    uint16_t retval;
+    uint64_t retval;
 
     switch (pm_byteOrder) {
     case BIG_ENDIAN: {
         union {
-            bigend16 bigend;
-            uint16_t native;
+            bigend64 bigend;
+            uint64_t native;
         } converter;
-        
         converter.bigend = arg;
-        
         retval = converter.native;
-    }; break;
+    } break;
+
+#if HAVE_GCC_BSWAP    
     case LITTLE_ENDIAN: {
-        retval =
-            (arg.bytes[0] << 8) |
-            (arg.bytes[1] << 0);
+        /* Use GCC built-in */  
+        union {
+            bigend64 bigend;
+            uint64_t native;
+        } converter;
+        converter.bigend = arg;
+        retval = __builtin_bswap64(converter.native);
     } break;
+#endif
+    default:
+        retval =
+            ((uint64_t)arg.bytes[0] << 56) | ((uint64_t)arg.bytes[1] << 48) |
+            ((uint64_t)arg.bytes[2] << 40) | ((uint64_t)arg.bytes[3] << 32) |
+            ((uint64_t)arg.bytes[4] << 24) | ((uint64_t)arg.bytes[5] << 16) |
+            ((uint64_t)arg.bytes[6] <<  8) | ((uint64_t)arg.bytes[7] <<  0);
     }
     return retval;
 }
 
 
 
-static __inline__ bigend16
-pm_bigendFromUint16(uint16_t const arg) {
+static __inline__ bigend64
+pm_bigendFromUint64(uint64_t const arg) {
 
-    bigend16 retval;
+    bigend64 retval;
 
     switch (pm_byteOrder) {
     case BIG_ENDIAN: {
         union {
-            bigend16 bigend;
-            uint16_t native;
+            bigend64 bigend;
+            uint64_t native;
         } converter;
-        
         converter.native = arg;
-
         retval = converter.bigend;
     } break;
+
+#if HAVE_GCC_BSWAP
     case LITTLE_ENDIAN: {
-        uint16_t shift;
+
+        /* Use GCC built-in */  
+        union {
+            bigend64 bigend;
+            uint64_t native;
+        } converter;
+        converter.native = __builtin_bswap64(arg);
+        retval = converter.bigend;
+    } break;
+#endif
+    
+    default: {
+        uint64_t shift;
         shift = arg;
+        retval.bytes[7] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[6] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[5] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[4] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[3] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
+        retval.bytes[2] = shift;  /* Takes lower 8 bits */
+        shift >>= 8;
         retval.bytes[1] = shift;  /* Takes lower 8 bits */
         shift >>= 8;
         retval.bytes[0] = shift;  /* Takes lower 8 bits */
-    } break;
+    }
     }
     return retval;
 }
 
+#endif /* HAVE_INT64 */
+
 #endif
+
+
+
+
+
diff --git a/lib/util/nstring.h b/lib/util/nstring.h
index 1e5ca4c3..53f1e4c0 100644
--- a/lib/util/nstring.h
+++ b/lib/util/nstring.h
@@ -28,8 +28,16 @@ extern "C" {
     (strncpy(A+strlen(A), B, sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0')
 #define STRSEQ(A, B) \
 	(strneq((A), (B), sizeof(A)))
-#define MEMSZERO(A) \
-    bzero((A), sizeof(A))
+
+#define MEMEQ(a,b,c) (memcmp(a, b, c) == 0)
+
+#define MEMSEQ(a,b) (memeq(a, b, sizeof(*(a))) == 0)
+
+#define MEMSSET(a,b) (memset(a, b, sizeof(*(a))))
+
+#define MEMSCPY(a,b) (memcpy(a, b, sizeof(*(a))))
+
+#define MEMSZERO(a) (MEMSSET(a, 0))
 
 
 static __inline__ int
diff --git a/lib/util/wordaccess.h b/lib/util/wordaccess.h
index 08034361..2eaa2b24 100644
--- a/lib/util/wordaccess.h
+++ b/lib/util/wordaccess.h
@@ -36,31 +36,39 @@
    work with that.
 
    We also assume that a char is 8 bits.
+
+   HAVE_GCC_BITCOUNT and HAVE_GCC_BSWAP are set in pm_config.h
+
+   BITS_PER_LONG is the number of bits in long int.
 */
 
 #include "pm_config.h"
 
-#if (!defined(WORDACCESS_GENERIC) \
-     && defined(__GNUC__) && defined(__GLIBC__) \
-     && (__GNUC__ * 100 + __GNUC_MINOR__ >= 304) )
-
-    #if BYTE_ORDER==BIG_ENDIAN    /* defined by GCC */
+#if (!defined(WORDACCESS_GENERIC) && HAVE_GCC_BITCOUNT )
 
+    #if BYTE_ORDER == BIG_ENDIAN    /* See pm_config.h */
+        /* Sun Sparc 64, etc */ 
         #include "wordaccess_gcc3_be.h"
 
-    #elif defined(__ia64__) || defined(__amd64__) || defined(__x86_64__)
-         /* all these macros are defined by GCC */
-
+    #elif (BITS_PER_LONG == 64)
+        /* AMD Athlon 64, Intel x86_64, Intel Itanium, etc. */
         #include "wordaccess_64_le.h"
 
-    #else
+    #elif (BITS_PER_LONG == 32)
+        /* Intel x86_32 (80386, 80486, Pentium), etc. */
+        #include "wordaccess_generic.h"
 
-        #include "wordaccess_gcc3_le.h"
+    #else
+        /* Extremely rare case.
+           If long is neither 32 nor 64 bits, (say, 128) it comes here.
+        */
+        #define WORDACCESS_GENERIC
+        #include "wordaccess_generic.h"
 
     #endif
 
 #else
-
+    /* Non GCC, GCC prior to v.3.4 or WORDACCESS_GENERIC defined  */
     #include "wordaccess_generic.h"
 
 #endif
diff --git a/lib/util/wordaccess_64_le.h b/lib/util/wordaccess_64_le.h
index ad316df2..4d148ad2 100644
--- a/lib/util/wordaccess_64_le.h
+++ b/lib/util/wordaccess_64_le.h
@@ -2,28 +2,21 @@
   This file is the part of wordaccess.h for use under these
   conditions:
 
-  * GCC (>=3.4), GLIBC
-  * 64 bit Little-Endian machines (IA64, X86-64, AMD64)
-=============================================================================*/
-   
-/*  
-    64 bit hton and ntoh do not exist.  Here we use bswap_64.
-    
-    While bswap_64 works on 64 bit data, __builtin_clzl works on "long" which
-    may or may not be 64 bits.  Code provided to find the right data type and
-    file off any extra when necessary.
-*/
-
-#include <byteswap.h>  /* See note above on bswap_64 */
-
-#include "pm.h"
+  * GCC (>=3.4)  (__builtin_clz appears in GCC 3.4)
+  * Little-Endian machines (IA64, X86-64, AMD64)
+  * 64 bit long
  
+=============================================================================*/
+
+#include "intcode.h"
+
 typedef uint64_t wordint;
 typedef unsigned char wordintBytes[sizeof(wordint)];
 
+
 static __inline__ wordint
-bytesToWordint(wordintBytes bytes) {
-    return ((wordint) bswap_64(*(wordint *)bytes));
+bytesToWordint(wordintBytes const bytes) {
+    return (wordint) pm_uintFromBigend64(*(bigend64*)bytes);
 }
 
 
@@ -31,24 +24,5 @@ bytesToWordint(wordintBytes bytes) {
 static __inline__ void
 wordintToBytes(wordintBytes * const bytesP,
                wordint        const wordInt) {
-    *(wordint *)bytesP = bswap_64(wordInt);
-}
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x){
-
-    unsigned int s;
-
-    if (x == 0)
-        return sizeof(wordint) * 8;
-
-    /* Find the data type closest to 64 bits, and file off any extra. */
-    else if ((s=sizeof(long int)) >= 8)
-        return (__builtin_clzl((long int)x << (s - 8) * 8));
-    else if ((s=sizeof(long long int)) >= 8)
-        return (__builtin_clzll((long long int)x << (s - 8) * 8));
-    else
-        pm_error("Long long int is less than 64 bits on this machine"); 
+     *(bigend64*)bytesP = pm_bigendFromUint64(wordInt);
 }
diff --git a/lib/util/wordaccess_gcc3_be.h b/lib/util/wordaccess_gcc3_be.h
index 6f5d86fc..5aa63521 100644
--- a/lib/util/wordaccess_gcc3_be.h
+++ b/lib/util/wordaccess_gcc3_be.h
@@ -4,16 +4,6 @@
 
   * GCC (>=3.4), GLIBC
   * Big-Endian machines
-  
-  __builtin_clz is available on GCC 3.4 and above
-     
-  Note that the clz scheme does not work and requires adjustment
-  if long type does not make use of all bits for data storage.
-  
-  This is unlikely.  According to GNU MP (http://www.swox.com/gmp/),
-  in rare cases such as Cray, there are smaller data types that take up
-  the same space as long, but leave the higher bits silent.  Currently,
-  there are no known such cases for data type long.
 *===========================================================================*/
 
 typedef unsigned long int wordint;
@@ -31,10 +21,3 @@ wordintToBytes(wordintBytes * const bytesP,
                wordint        const wordInt) {
     *(wordint *)bytesP = wordInt;
 }
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x) {
-    return (x==0 ? sizeof(wordint)*8 : __builtin_clzl(x));
-}
diff --git a/lib/util/wordaccess_gcc3_le.h b/lib/util/wordaccess_gcc3_le.h
deleted file mode 100644
index 798566af..00000000
--- a/lib/util/wordaccess_gcc3_le.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*=============================================================================
-
-  This file is the part of wordaccess.h for use under these
-  conditions:
-
-  * GCC (>=3.4), GLIBC
-  * 32 bit Little-Endian machines (intel MPUs 80386, Pentium, etc.)
-  * Other non-Big-Endian machines (very rare)
-  
-=============================================================================*/
-
-typedef uint32_t wordint;
-typedef unsigned char wordintBytes[sizeof(wordint)];
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include "pm.h"
-
-/*
-  Here we use the more widely used functions htonl and ntohl instead of
-  bswap_32.  This makes possible the handling of weird byte ordering
-  (neither Big-Endian nor Little-Endian) schemes, if any.
-*/
-
-static __inline__ wordint
-bytesToWordint(wordintBytes const bytes) {
-    return (wordint) ntohl(*(wordint *)bytes);
-}
-
-
-
-static __inline__ void
-wordintToBytes(wordintBytes * const bytesP,
-               wordint        const wordInt) {
-
-    *(wordint *)bytesP = htonl(wordInt);
-}
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x) {
-
-    /* Find the data type closest to 32 bits, and file off any extra.  */
-
-    if (x == 0)
-        return sizeof(wordint) * 8;
-    else if (sizeof(int) >= 4)
-        return __builtin_clz((int)x << (sizeof(int) - 4) * 8);
-    else if (sizeof(long int) >= 4)
-        return __builtin_clzl((long int)x << (sizeof(long int) - 4) * 8);
-    else
-        pm_error("Long int is less than 32 bits on this machine"); 
-}
-
diff --git a/lib/util/wordaccess_generic.h b/lib/util/wordaccess_generic.h
index 7f27ef74..94cc8124 100644
--- a/lib/util/wordaccess_generic.h
+++ b/lib/util/wordaccess_generic.h
@@ -5,85 +5,25 @@
 
   * Compilers other than GCC
   * GCC before version 3.4
-  * c libraries other than Glibc
   * Specified by the user with WORDACCESS_GENERIC
 =============================================================================*/
 
+#include "intcode.h"
+
 typedef uint32_t wordint;
 typedef unsigned char wordintBytes[sizeof(wordint)];
+
     
 static __inline__ wordint
-bytesToWordint(wordintBytes const bytes) {
-    wordint retval;
-    unsigned int i;
+bytesToWordint(wordintBytes  const bytes) {
 
-    /* Note that 'bytes' is a pointer, due to C array degeneration.
-       That means sizeof(bytes) isn't what you think it is.
-    */
-    
-    for (i = 1, retval = bytes[0]; i < sizeof(wordint); ++i) {
-        retval = (retval << 8) + bytes[i];
-    }
-    return retval;
+    return (wordint)  pm_uintFromBigend32( * (bigend32*) bytes);
 }
 
 
-
 static __inline__ void
 wordintToBytes(wordintBytes * const bytesP,
-               wordint        const wordInt) {
-
-    wordint buffer;
-    int i;
-
-    for (i = sizeof(*bytesP)-1, buffer = wordInt; i >= 0; --i) {
-        (*bytesP)[i] = buffer & 0xFF;
-        buffer >>= 8;
-    }
-}
-    
-static unsigned char const clz8[256]= {
-    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
-};
-
-
-
-static __inline__ unsigned int
-clz16(wordint const x) {
-    if (x >> 8  != 0)
-        return clz8[x >> 8];
-    else
-        return clz8[x] + 8;
-}
-
-
-
-static __inline__  unsigned int
-clz32(wordint const x) {
-    if (x >> 16  != 0)
-        return clz16(x >> 16);
-    else
-        return clz16(x) +16;
-}
-
-
+               wordint    const wordInt) {
 
-static __inline__  unsigned int
-wordintClz(wordint const x) {
-    return clz32(x);
+    * (bigend32*) bytesP = pm_bigendFromUint32((uint32_t)wordInt);
 }