1 /* @(#)cmpbytes.c 1.23 10/08/21 Copyright 1988, 1995-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)cmpbytes.c 1.23 10/08/21 Copyright 1988, 1995-2010 J. Schilling";
6 #endif /* lint */
7 /*
8 * compare data
9 * Return the index of the first differing character
10 *
11 * Copyright (c) 1988, 1995-2010 J. Schilling
12 */
13 /*
14 * The contents of this file are subject to the terms of the
15 * Common Development and Distribution License, Version 1.0 only
16 * (the "License"). You may not use this file except in compliance
17 * with the License.
18 *
19 * See the file CDDL.Schily.txt in this distribution for details.
20 * A copy of the CDDL is also available via the Internet at
21 * http://www.opensource.org/licenses/cddl1.txt
22 *
23 * When distributing Covered Code, include this CDDL HEADER in each
24 * file and include the License file CDDL.Schily.txt from this distribution.
25 */
26
27 #include <schily/standard.h>
28 #include <schily/align.h>
29 #include <schily/types.h>
30 #include <schily/schily.h>
31
32 #define DO8(a) a; a; a; a; a; a; a; a;
33
34 /*
35 * Return the index of the first differing character
36 * This interface is not compatible to memcmp()
37 */
38 EXPORT ssize_t
cmpbytes(fromp,top,cnt)39 cmpbytes(fromp, top, cnt)
40 const void *fromp;
41 const void *top;
42 ssize_t cnt;
43 {
44 register const char *from = (char *)fromp;
45 register const char *to = (char *)top;
46 register ssize_t n;
47 register ssize_t i;
48
49 /*
50 * If we change cnt to be unsigned, check for == instead of <=
51 */
52 if ((n = cnt) <= 0)
53 return (cnt);
54
55 /*
56 * Compare byte-wise until properly aligned for a long pointer.
57 */
58 i = sizeof (long) - 1;
59 while (--n >= 0 && --i >= 0 && !l2aligned(from, to)) {
60 if (*to++ != *from++)
61 goto cdiff;
62 }
63 n++;
64
65 if (n >= (ssize_t)(8 * sizeof (long))) {
66 if (l2aligned(from, to)) {
67 register const long *froml = (const long *)from;
68 register const long *tol = (const long *)to;
69 register ssize_t rem = n % (8 * sizeof (long));
70
71 n /= (8 * sizeof (long));
72 do {
73 /* BEGIN CSTYLED */
74 DO8(
75 if (*tol++ != *froml++)
76 break;
77 );
78 /* END CSTYLED */
79 } while (--n > 0);
80
81 if (n > 0) {
82 --froml;
83 --tol;
84 to = (const char *)tol;
85 from = (const char *)froml;
86 goto ldiff;
87 }
88 to = (const char *)tol;
89 from = (const char *)froml;
90 n = rem;
91 }
92
93 if (n >= 8) {
94 n -= 8;
95 do {
96 /* BEGIN CSTYLED */
97 DO8(
98 if (*to++ != *from++)
99 goto cdiff;
100 );
101 /* END CSTYLED */
102 } while ((n -= 8) >= 0);
103 n += 8;
104 }
105 if (n > 0) do {
106 if (*to++ != *from++)
107 goto cdiff;
108 } while (--n > 0);
109 return (cnt);
110 }
111 if (n > 0) do {
112 if (*to++ != *from++)
113 goto cdiff;
114 } while (--n > 0);
115 return (cnt);
116 ldiff:
117 n = sizeof (long);
118 do {
119 if (*to++ != *from++)
120 goto cdiff;
121 } while (--n > 0);
122 cdiff:
123 return ((ssize_t)(--from - (char *)fromp));
124 }
125