Zero  0.1.0
umemcmp.h
Go to the documentation of this file.
1 /*<std-header orig-src='shore' incl-file-exclusion='UMEMCMP_H'>
2 
3  $Id: umemcmp.h,v 1.22 2010/12/08 17:37:34 nhall Exp $
4 
5 SHORE -- Scalable Heterogeneous Object REpository
6 
7 Copyright (c) 1994-99 Computer Sciences Department, University of
8  Wisconsin -- Madison
9 All Rights Reserved.
10 
11 Permission to use, copy, modify and distribute this software and its
12 documentation is hereby granted, provided that both the copyright
13 notice and this permission notice appear in all copies of the
14 software, derivative works or modified versions, and any portions
15 thereof, and that both notices appear in supporting documentation.
16 
17 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
18 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
19 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
20 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
21 
22 This software was developed with support by the Advanced Research
23 Project Agency, ARPA order number 018 (formerly 8230), monitored by
24 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
25 Further funding for this work was provided by DARPA through
26 Rome Research Laboratory Contract No. F30602-97-2-0247.
27 
28 */
29 
30 #ifndef __UMEMCMP_H
31 #define __UMEMCMP_H
32 
33 #include "w_defines.h"
34 
35 /* -- do not edit anything above this line -- </std-header>*/
36 
37 /*
38  * This file provides an version of memcmp() called umemcmp that
39  * compared unsigned characters instead of signed.
40  * For correct operation of the btree code umemcmp() must be used.
41  * In fact we recommend you using memcmp only to test for
42  * == or != as it can give different results for > and < depending
43  * on the compiler.
44  */
45 
46 #include <cassert>
47 
48 #ifndef __W_WORKAROUND_H
49 #include "w_workaround.h"
50 #endif // __W_WORKAROUND_H
51 
52 // Simple byte-by-byte comparisions
53 inline int __umemcmp(const unsigned char* p, const unsigned char* q, int n) {
54  int i;
55  for (i = 0; (i < n) && (*p == *q); i++, p++, q++) {}
56  return (i < n) ? *p - *q : 0;
57 }
58 
59 /*
60  * XXX this is a dangerous assumption; correct operation for umemcpy()
61  * should be verified!
62  *
63  * So far only sparcs (sunos) have been found to need a special umemcmp.
64  */
65 #if defined(Sparc)
66 
67 inline uint int_alignment_check(const void *i)
68 {
69  uint tmp = (ptrdiff_t) i & (sizeof(int)-1);
70  w_assert9(tmp == (ptrdiff_t) i % sizeof(int));
71  return tmp;
72 }
73 inline bool is_int_aligned(const void *i)
74 {
75  return int_alignment_check(i) == 0;
76 }
77 
78 // Smarter way if things are aligned. Basically this does the
79 // comparison an int at a time.
80 inline int umemcmp_smart(const void* p_, const void* q_, int n)
81 {
82  const unsigned char* p = (const unsigned char*)p_;
83  const unsigned char* q = (const unsigned char*)q_;
84 
85  // If short, just use simple method
86  if (n < (int)(2*sizeof(int)))
87  return __umemcmp(p, q, n);
88 
89  // See if both are aligned to the same value
90  if (int_alignment_check(p) == int_alignment_check(q)) {
91  if (!is_int_aligned(p)) {
92  // can't handle misaliged, use simple method
93  return __umemcmp(p, q, n);
94  }
95 
96  // Compare an int at a time
97  uint i;
98  for (i = 0; i < n/sizeof(int); i++) {
99  if (((unsigned*)p)[i] != ((unsigned*)q)[i]) {
100  return (((unsigned*)p)[i] > ((unsigned*)q)[i]) ? 1 : -1;
101  }
102  }
103  // take care of the leftover bytes
104  int j = i*sizeof(int);
105  if (j) return __umemcmp(p+j, q+j, n-j);
106  } else {
107  // misaligned with respect to eachother
108  return __umemcmp(p, q, n);
109  }
110  return 0; // must be equal
111 }
112 
113 inline int umemcmp_old(const void* p, const void* q, int n)
114 {
115  return __umemcmp((unsigned char*)p, (unsigned char*)q, n);
116 }
117 
118 inline int umemcmp(const void* p, const void* q, int n)
119 {
120 #if W_DEBUG_LEVEL > 2
121  // check for any bugs in umemcmp_smart
122  int t1 = umemcmp_smart(p, q, n);
123  int t2 = __umemcmp((unsigned char*)p, (unsigned char*)q, n);
124  assert(t1 == t2 || (t1 < 0 && t2 < 0) || (t1 > 0 && t2 > 0));
125  return t1;
126 #else
127  return umemcmp_smart(p, q, n);
128 #endif
129 }
130 
131 #else /* defined(Sparc) */
132 
133 inline int umemcmp(const void* p, const void* q, int n) {
134 #if W_DEBUG_LEVEL > 2
135  // verify that memcmp is equivalent to umemcmp
136  int t1 = memcmp(p, q, n);
137  int t2 = __umemcmp((unsigned char*)p, (unsigned char*)q, n);
138  w_assert3(t1 == t2 || (t1 < 0 && t2 < 0) || (t1 > 0 && t2 > 0));
139  return t1;
140 #else
141  return memcmp(p, q, n);
142 #endif
143 }
144 
145 #endif /* defined(Sparc) */
146 
147 /*<std-footer incl-file-exclusion='UMEMCMP_H'> -- do not edit anything below this line -- */
148 
149 #endif // __UMEMCMP_H /*</std-footer>*/
#define w_assert3(x)
Level 3 definitely adds significant time.
Definition: w_base.h:214
int __umemcmp(const unsigned char *p, const unsigned char *q, int n)
Definition: umemcmp.h:53
int umemcmp(const void *p, const void *q, int n)
Definition: umemcmp.h:133
#define w_assert9(x)
changing an assert to an assert9 turns it off.
Definition: w_base.h:243