1 /* @(#)movecbytes.c	1.2 16/11/05 Copyright 2016 J. Schilling */
2 /*
3  *	move data, stop if character c is copied
4  *
5  *	Copyright (c) 2016 J. Schilling
6  */
7 /*
8  * The contents of this file are subject to the terms of the
9  * Common Development and Distribution License, Version 1.0 only
10  * (the "License").  You may not use this file except in compliance
11  * with the License.
12  *
13  * See the file CDDL.Schily.txt in this distribution for details.
14  * A copy of the CDDL is also available via the Internet at
15  * http://www.opensource.org/licenses/cddl1.txt
16  *
17  * When distributing Covered Code, include this CDDL HEADER in each
18  * file and include the License file CDDL.Schily.txt from this distribution.
19  */
20 
21 #include <schily/standard.h>
22 #include <schily/types.h>
23 #include <schily/schily.h>
24 
25 #define	DO8(a)	a; a; a; a; a; a; a; a;
26 
27 /*
28  * movecbytes(from, to, c, cnt) is the same as memccpy(to, from, c, cnt)
29  */
30 EXPORT char *
movecbytes(fromv,tov,c,cnt)31 movecbytes(fromv, tov, c, cnt)
32 	const void	*fromv;
33 	void		*tov;
34 	register int	c;
35 	size_t		cnt;
36 {
37 	register const char	*from	= fromv;
38 	register char		*to	= tov;
39 	register size_t		n;
40 
41 	if ((n = cnt) == 0)
42 		return (NULL);
43 
44 #define	separate_code
45 #ifdef	separate_code
46 	while (n >= 8) {
47 		/* BEGIN CSTYLED */
48 		DO8(
49 			if ((*to++ = *from++) == (char)c)
50 				return (to);
51 		);
52 		/* END CSTYLED */
53 		n -= 8;
54 	}
55 
56 	switch (n) {
57 
58 	case 7:	if ((*to++ = *from++) == (char)c)
59 			return (to);
60 	case 6:	if ((*to++ = *from++) == (char)c)
61 			return (to);
62 	case 5:	if ((*to++ = *from++) == (char)c)
63 			return (to);
64 	case 4:	if ((*to++ = *from++) == (char)c)
65 			return (to);
66 	case 3:	if ((*to++ = *from++) == (char)c)
67 			return (to);
68 	case 2:	if ((*to++ = *from++) == (char)c)
69 			return (to);
70 	case 1:	if ((*to++ = *from++) == (char)c)
71 			return (to);
72 	}
73 #else
74 	/*
75 	 * This variant should be as fast as the code above but
76 	 * half the size. Unfortunately, most compilers do not optmize
77 	 * it correctly.
78 	 */
79 	int	rest = n % 8;
80 
81 	n -= rest;
82 
83 	switch (rest) {
84 
85 	case 0: while (n != 0) {
86 			n -= 8;
87 			if ((*to++ = *from++) == (char)c)
88 				return (to);
89 	case 7:		if ((*to++ = *from++) == (char)c)
90 				return (to);
91 	case 6:		if ((*to++ = *from++) == (char)c)
92 				return (to);
93 	case 5:		if ((*to++ = *from++) == (char)c)
94 				return (to);
95 	case 4:		if ((*to++ = *from++) == (char)c)
96 				return (to);
97 	case 3:		if ((*to++ = *from++) == (char)c)
98 				return (to);
99 	case 2:		if ((*to++ = *from++) == (char)c)
100 				return (to);
101 	case 1:		if ((*to++ = *from++) == (char)c)
102 				return (to);
103 		}
104 	}
105 #endif
106 	return (NULL);
107 }
108