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