Rev 3730 | Rev 4226 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3730 | Rev 3731 | ||
|---|---|---|---|
| Line 32... | Line 32... | ||
| 32 | */ |
32 | */ |
| 33 | /** @file |
33 | /** @file |
| 34 | */ |
34 | */ |
| 35 | 35 | ||
| 36 | #include <string.h> |
36 | #include <string.h> |
| 37 | #include <unistd.h> |
- | |
| 38 | #include <ctype.h> |
37 | #include <stdlib.h> |
| 39 | #include <limits.h> |
38 | #include <limits.h> |
| 40 | #include <align.h> |
- | |
| 41 | #include <sys/types.h> |
39 | #include <ctype.h> |
| 42 | #include <malloc.h> |
40 | #include <malloc.h> |
| 43 | 41 | ||
| 44 | /** Fill memory block with a constant value. */ |
- | |
| 45 | void *memset(void *dest, int b, size_t n) |
- | |
| 46 | { |
- | |
| 47 | char *pb; |
- | |
| 48 | unsigned long *pw; |
- | |
| 49 | size_t word_size; |
- | |
| 50 | size_t n_words; |
- | |
| 51 | - | ||
| 52 | unsigned long pattern; |
- | |
| 53 | size_t i; |
- | |
| 54 | size_t fill; |
- | |
| 55 | - | ||
| 56 | /* Fill initial segment. */ |
- | |
| 57 | word_size = sizeof(unsigned long); |
- | |
| 58 | fill = word_size - ((uintptr_t) dest & (word_size - 1)); |
- | |
| 59 | if (fill > n) fill = n; |
- | |
| 60 | - | ||
| 61 | pb = dest; |
- | |
| 62 | - | ||
| 63 | i = fill; |
- | |
| 64 | while (i-- != 0) |
- | |
| 65 | *pb++ = b; |
- | |
| 66 | - | ||
| 67 | /* Compute remaining size. */ |
- | |
| 68 | n -= fill; |
- | |
| 69 | if (n == 0) return dest; |
- | |
| 70 | - | ||
| 71 | n_words = n / word_size; |
- | |
| 72 | n = n % word_size; |
- | |
| 73 | pw = (unsigned long *) pb; |
- | |
| 74 | - | ||
| 75 | /* Create word-sized pattern for aligned segment. */ |
- | |
| 76 | pattern = 0; |
- | |
| 77 | i = word_size; |
- | |
| 78 | while (i-- != 0) |
- | |
| 79 | pattern = (pattern << 8) | (uint8_t) b; |
- | |
| 80 | - | ||
| 81 | /* Fill aligned segment. */ |
- | |
| 82 | i = n_words; |
- | |
| 83 | while (i-- != 0) |
- | |
| 84 | *pw++ = pattern; |
- | |
| 85 | - | ||
| 86 | pb = (char *) pw; |
- | |
| 87 | - | ||
| 88 | /* Fill final segment. */ |
- | |
| 89 | i = n; |
- | |
| 90 | while (i-- != 0) |
- | |
| 91 | *pb++ = b; |
- | |
| 92 | - | ||
| 93 | return dest; |
- | |
| 94 | } |
- | |
| 95 | - | ||
| 96 | struct along { |
- | |
| 97 | unsigned long n; |
- | |
| 98 | } __attribute__ ((packed)); |
- | |
| 99 | - | ||
| 100 | static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
- | |
| 101 | { |
- | |
| 102 | int i, j; |
- | |
| 103 | struct along *adst = dst; |
- | |
| 104 | const struct along *asrc = src; |
- | |
| 105 | - | ||
| 106 | for (i = 0; i < n / sizeof(unsigned long); i++) |
- | |
| 107 | adst[i].n = asrc[i].n; |
- | |
| 108 | - | ||
| 109 | for (j = 0; j < n % sizeof(unsigned long); j++) |
- | |
| 110 | ((unsigned char *) (((unsigned long *) dst) + i))[j] = |
- | |
| 111 | ((unsigned char *) (((unsigned long *) src) + i))[j]; |
- | |
| 112 | - | ||
| 113 | return (char *) dst; |
- | |
| 114 | } |
- | |
| 115 | - | ||
| 116 | /** Copy memory block. */ |
- | |
| 117 | void *memcpy(void *dst, const void *src, size_t n) |
- | |
| 118 | { |
- | |
| 119 | size_t i; |
- | |
| 120 | size_t mod, fill; |
- | |
| 121 | size_t word_size; |
- | |
| 122 | size_t n_words; |
- | |
| 123 | - | ||
| 124 | const unsigned long *srcw; |
- | |
| 125 | unsigned long *dstw; |
- | |
| 126 | const uint8_t *srcb; |
- | |
| 127 | uint8_t *dstb; |
- | |
| 128 | - | ||
| 129 | word_size = sizeof(unsigned long); |
- | |
| 130 | - | ||
| 131 | /* |
- | |
| 132 | * Are source and destination addresses congruent modulo word_size? |
- | |
| 133 | * If not, use unaligned_memcpy(). |
- | |
| 134 | */ |
- | |
| 135 | - | ||
| 136 | if (((uintptr_t) dst & (word_size - 1)) != |
- | |
| 137 | ((uintptr_t) src & (word_size - 1))) |
- | |
| 138 | return unaligned_memcpy(dst, src, n); |
- | |
| 139 | - | ||
| 140 | /* |
- | |
| 141 | * mod is the address modulo word size. fill is the length of the |
- | |
| 142 | * initial buffer segment before the first word boundary. |
- | |
| 143 | * If the buffer is very short, use unaligned_memcpy(), too. |
- | |
| 144 | */ |
- | |
| 145 | - | ||
| 146 | mod = (uintptr_t) dst & (word_size - 1); |
- | |
| 147 | fill = word_size - mod; |
- | |
| 148 | if (fill > n) fill = n; |
- | |
| 149 | - | ||
| 150 | /* Copy the initial segment. */ |
- | |
| 151 | - | ||
| 152 | srcb = src; |
- | |
| 153 | dstb = dst; |
- | |
| 154 | - | ||
| 155 | i = fill; |
- | |
| 156 | while (i-- != 0) |
- | |
| 157 | *dstb++ = *srcb++; |
- | |
| 158 | - | ||
| 159 | /* Compute remaining length. */ |
- | |
| 160 | - | ||
| 161 | n -= fill; |
- | |
| 162 | if (n == 0) return dst; |
- | |
| 163 | - | ||
| 164 | /* Pointers to aligned segment. */ |
- | |
| 165 | - | ||
| 166 | dstw = (unsigned long *) dstb; |
- | |
| 167 | srcw = (const unsigned long *) srcb; |
- | |
| 168 | - | ||
| 169 | n_words = n / word_size; /* Number of whole words to copy. */ |
- | |
| 170 | n -= n_words * word_size; /* Remaining bytes at the end. */ |
- | |
| 171 | - | ||
| 172 | /* "Fast" copy. */ |
- | |
| 173 | i = n_words; |
- | |
| 174 | while (i-- != 0) |
- | |
| 175 | *dstw++ = *srcw++; |
- | |
| 176 | - | ||
| 177 | /* |
- | |
| 178 | * Copy the rest. |
- | |
| 179 | */ |
- | |
| 180 | - | ||
| 181 | srcb = (const uint8_t *) srcw; |
- | |
| 182 | dstb = (uint8_t *) dstw; |
- | |
| 183 | - | ||
| 184 | i = n; |
- | |
| 185 | while (i-- != 0) |
- | |
| 186 | *dstb++ = *srcb++; |
- | |
| 187 | - | ||
| 188 | return dst; |
- | |
| 189 | } |
- | |
| 190 | - | ||
| 191 | /** Move memory block with possible overlapping. */ |
- | |
| 192 | void *memmove(void *dst, const void *src, size_t n) |
- | |
| 193 | { |
- | |
| 194 | uint8_t *dp, *sp; |
- | |
| 195 | - | ||
| 196 | /* Nothing to do? */ |
- | |
| 197 | if (src == dst) |
- | |
| 198 | return dst; |
- | |
| 199 | - | ||
| 200 | /* Non-overlapping? */ |
- | |
| 201 | if (dst >= src + n || src >= dst + n) { |
- | |
| 202 | return memcpy(dst, src, n); |
- | |
| 203 | } |
- | |
| 204 | - | ||
| 205 | /* Which direction? */ |
- | |
| 206 | if (src > dst) { |
- | |
| 207 | /* Forwards. */ |
- | |
| 208 | sp = src; |
- | |
| 209 | dp = dst; |
- | |
| 210 | - | ||
| 211 | while (n-- != 0) |
- | |
| 212 | *dp++ = *sp++; |
- | |
| 213 | } else { |
- | |
| 214 | /* Backwards. */ |
- | |
| 215 | sp = src + (n - 1); |
- | |
| 216 | dp = dst + (n - 1); |
- | |
| 217 | - | ||
| 218 | while (n-- != 0) |
- | |
| 219 | *dp-- = *sp--; |
- | |
| 220 | } |
- | |
| 221 | - | ||
| 222 | return dst; |
- | |
| 223 | } |
- | |
| 224 | - | ||
| 225 | /** Compare two memory areas. |
- | |
| 226 | * |
- | |
| 227 | * @param s1 Pointer to the first area to compare. |
- | |
| 228 | * @param s2 Pointer to the second area to compare. |
- | |
| 229 | * @param len Size of the first area in bytes. Both areas must have |
- | |
| 230 | * the same length. |
- | |
| 231 | * @return If len is 0, return zero. If the areas match, return |
- | |
| 232 | * zero. Otherwise return non-zero. |
- | |
| 233 | */ |
- | |
| 234 | int bcmp(const char *s1, const char *s2, size_t len) |
- | |
| 235 | { |
- | |
| 236 | for (; len && *s1++ == *s2++; len--) |
- | |
| 237 | ; |
- | |
| 238 | return len; |
- | |
| 239 | } |
- | |
| 240 | - | ||
| 241 | /** Count the number of characters in the string, not including terminating 0. |
42 | /** Count the number of characters in the string, not including terminating 0. |
| 242 | * |
43 | * |
| 243 | * @param str String. |
44 | * @param str String. |
| 244 | * @return Number of characters in string. |
45 | * @return Number of characters in string. |
| 245 | */ |
46 | */ |