📄 mmstring.c
字号:
mm_strpack32(const char *str, size_t min){ int32_t hash = 0; size_t i; for (i = 0; *str > 32 && i < 5; i++) { hash <<= 8; hash |= toupper_table[(int)*str++]; } if (i < min || i > 4) hash = -1; return (hash);}unsigned longmm_htol(const char *s){ register unsigned long v = 0; while (*s) { if (*s >= '0' && *s <= '9') { if (v <= (unsigned short)-1) v = (unsigned short)v * 16; else v = v * 16; v += *s++ - '0'; } else if (*s >= 'a' && *s <= 'f') { if (v <= (unsigned short)-1) v = (unsigned short)v * 16; else v = v * 16; v += *s++ - 87; } else if (*s >= 'A' && *s <= 'F') { if (v <= (unsigned short)-1) v = (unsigned short)v * 16; else v = v * 16; v += *s++ - 55; } else break; } return (v);}voidmm_strrev(char *str){ char *p1, *p2, t; for (p1 = p2 = str; *p2; p2++) ; if (p2 > p1) p2--; for (;p1 < p2; p1++, p2--) { t = *p1; *p1 = *p2; *p2 = t; }}/* This hash function should be pretty safe as it was tested to not cause * duplicates on: * locate '*' * cat /usr/share/dict/words * XXX Could be unrolled a little */u_int64_tmm_strhash64(char *str){ u_int64_t hash = 0; while (*str) { hash = *str + (2818937311llu * hash); str++; } return (hash);}/* Variant of hash64 on memory buffer */u_int64_tmm_memhash64(void *mem, size_t size){ u_int64_t hash = 0; char *curmem, *tomem; curmem = tomem = mem; tomem += size; while (curmem < tomem) { hash = *curmem + (2818937311llu * hash); curmem++; } return (hash);}/* Some may argue about the usefulness of such a thing. Some C libraries will * provide more efficient architecture-dependant functions using unrolling * when necessary, word copy methods, or even hardware data manipulation * functions. But, some systems may have broken implementations, and others * will provide unefficient C or assembly ones. So I borrow this code from * my Xisop project which is portable and guaranteed to work decently. * These functions are probably as fast as C ones could be. * The ARCH_INTn and ARCH_LOWCACHE definitions are found in mmlib/mmtypes.h * and should be tweaked for maximum performance on a particular architecture. * I previously had ARCH_INDEXPREFERED which used to emphasize code on [] * indexing rather than ptr++ style if defined, but further analyzis of * generally resulting assembly proved that it was not necessary. In fact, GCC * generated less efficient code on i386 even though that architecture * privileges indexed instructions, normally the pointer reference with post * increment would best suit for m68k and similar processors, but then again, * compilers can generate lame instructions. Let's not care anymore about * indexed addressing then. The reason for using "int" as the general word * size for the system is that "long" type may be implemented as 32-bit on a * 16-bit or pseudo-32bit system, and would be less efficient than moving * words of the native size for the CPU. * * Matt */boolmm_memcmp(const void *dest, const void *src, size_t len){ register const char *ptr, *toptr, *dptr; ptr = toptr = src; toptr += len; dptr = dest;#if defined(ARCH_INT8)#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) if (*ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++) return (FALSE);#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) if (*ptr++ != *dptr++) return (FALSE);#else /* defined(ARCH_INT8) */ if (len < 32 || ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) {#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) if (*ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++) return (FALSE);#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) if (*ptr++ != *dptr++) return (FALSE); } else { register const int *lptr, *ltoptr, *ldptr, *ldtoptr; register const char *dtoptr; dtoptr = dptr; dtoptr += len; lptr = (const int *)MMALIGN_CEIL(ptr, int); ltoptr = (const int *)MMALIGN_FLOOR(toptr, int); ldptr = (const int *)MMALIGN_CEIL(dptr, int); ldtoptr = (const int *)MMALIGN_FLOOR(dtoptr, int); if (ldtoptr - ldptr < ltoptr - lptr) ltoptr--; while (ptr < (const char *)lptr) if (*ptr++ != *dptr++) return (FALSE);#if !defined(ARCH_LOWCACHE) while (lptr < ltoptr - (sizeof(int) * 8)) { if (*ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++) return (FALSE); }#endif /* !defined(ARCH_LOWCACHE) */ while (lptr < ltoptr) if (*lptr++ != *ldptr++) return (FALSE); ptr = (const char *)lptr; dptr = (const char *)ldptr; while (ptr < toptr) if (*ptr++ != *dptr++) return (FALSE); }#endif /* !defined(ARCH_INT8) */ return (TRUE);}voidmm_memcpy(void *dest, const void *src, size_t len){ register const char *ptr, *toptr; register char *dptr; ptr = toptr = src; toptr += len; dptr = dest;#if defined(ARCH_INT8)#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) { *dptr++ = *ptr++;#else /* defined(ARCH_INT8) */ if (len < 32 || ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) {#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) *dptr++ = *ptr++; } else { register const int *lptr, *ltoptr; register int *ldptr, *ldtoptr; register char *dtoptr; dtoptr = dptr; dtoptr += len; lptr = (const int *)MMALIGN_CEIL(ptr, int); ltoptr = (const int *)MMALIGN_FLOOR(toptr, int); ldptr = (int *)MMALIGN_CEIL(dptr, int); ldtoptr = (int *)MMALIGN_FLOOR(dtoptr, int); if (ldtoptr - ldptr < ltoptr - lptr) ltoptr--; while (ptr < (const char *)lptr || dptr < (char *)ldptr) *dptr++ = *ptr++;#if !defined(ARCH_LOWCACHE) while (lptr < ltoptr - (sizeof(int) * 8)) { *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (lptr < ltoptr) *ldptr++ = *lptr++; ptr = (const char *)lptr; dptr = (char *)ldptr; while (ptr < toptr) *dptr++ = *ptr++; }#endif /* !defined(ARCH_INT8) */}/* Can work with overlapping areas */voidmm_memmov(void *dest, const void *src, size_t len){ register const char *ptr = NULL, *toptr = NULL; register char *dptr = NULL; size_t d; if (dest < src) d = (const char *)src - (char *)dest; else d = (char *)dest - (const char *)src;#if defined(ARCH_INT8) if (dest < src) { /* Copy in increasing order */ ptr = toptr = (const char *)src; toptr += len; dptr = dest;#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) *dptr++ = *ptr++; } else if (dest > src) { /* Copy in reverse order */ ptr = (const char *)src; ptr += len; dptr = dest; dptr += len; toptr = (const char *)src;#if !defined(ARCH_LOWCACHE) while (ptr > toptr + 8) { *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr > toptr) *dptr-- = *ptr--; }#else /* defined(ARCH_INT8) */ if (len < 32 || d < sizeof(int) || ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) { if (dest < src) { /* Copy in increasing order */ ptr = toptr = (const char *)src; toptr += len; dptr = dest;#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; *dptr++ = *ptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) *dptr++ = *ptr++; } else if (dest > src) { /* Copy in reverse order */ ptr = (const char *)src; ptr += len; dptr = dest; dptr += len; toptr = (const char *)src;#if !defined(ARCH_LOWCACHE) while (ptr > toptr + 8) { *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; *dptr-- = *ptr--; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr > toptr) *dptr-- = *ptr--; } } else { if (dest < src) { /* Increasing order */ register const int *lptr, *ltoptr; register int *ldptr, *ldtoptr; register char *dtoptr; ptr = toptr = (const char *)src; toptr += len; dptr = dest; dtoptr = dptr; dtoptr += len; lptr = (const int *)MMALIGN_CEIL(ptr, int); ltoptr = (const int *)MMALIGN_FLOOR(toptr, int); ldptr = (int *)MMALIGN_CEIL(dptr, int); ldtoptr = (int *)MMALIGN_FLOOR(dtoptr, int); if (ldtoptr - ldptr < ltoptr - lptr) ltoptr--; while (ptr < (const char *)lptr) *dptr++ = *ptr++;#if !defined(ARCH_LOWCACHE) while (lptr < ltoptr - (sizeof(int) * 8)) { *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; *ldptr++ = *lptr++; }#endif /* !defined(ARCH_LOWCACHE) */ while (lptr < ltoptr) *ldptr++ = *lptr++; ptr = (const char *)lptr; dptr = (char *)ldptr; while (ptr < toptr) *dptr++ = *ptr++; } else if (dest > src) { /* Reverse order */ register const int *lptr, *ltoptr; register int *ldptr, *ldtoptr; register char *dtoptr; ptr = toptr = (const char *)src; ptr += len; dptr = dest; dptr += len; dtoptr = dest; lptr = (const int *)MMALIGN_FLOOR(ptr, int); ldptr = (int *)MMALIGN_FLOOR(dptr, int); ltoptr = (const int *)MMALIGN_CEIL(toptr, int); ldtoptr = (int *)MMALIGN_CEIL(dtoptr, int); if (ldptr - ldtoptr < lptr - ltoptr) ltoptr++; while (ptr > (const char *)lptr) *dptr-- = *ptr--;#if !defined(ARCH_LOWCACHE) while (lptr > ltoptr + (sizeof(int) * 8)) { *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; *ldptr-- = *lptr--; }#endif /* !defined(ARCH_LOWCACHE) */ while (lptr > ltoptr) *ldptr-- = *lptr--; ptr = (const char *)lptr; dptr = (char *)ldptr; while (ptr > toptr) *dptr-- = *ptr--; } }#endif /* !defined(ARCH_INT8) */}voidmm_memset(void *mem, char byte, size_t len){ register char *ptr, *toptr; ptr = toptr = mem; toptr += len;#if defined(ARCH_INT8)#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) *ptr++ = byte;#else /* defined(ARCH_INT8) */ if (len < 32) {#if !defined(ARCH_LOWCACHE) while (ptr < toptr - 8) { *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; *ptr++ = byte; }#endif /* !defined(ARCH_LOWCACHE) */ while (ptr < toptr) *ptr++ = byte; } else { register int *lptr, *ltoptr, lword = 0; /* XXX Make sure that this works on various endian architectures; * a SHIFT macro could be defined in mmtypes.h otherwise. */ if (byte) {#if defined(ARCH_INT16) lword |= byte; lword <<= 8; lword |= byte;#elif defined(ARCH_INT32) register short tmp = 0; tmp |= byte; tmp <<= 8; tmp |= byte; lword |= tmp; lword <<= 16; lword |= tmp;#elif defined(ARCH_INT64) register u_int32_t tmp2 = 0; register short tmp = 0; tmp |= byte; tmp <<= 8; tmp |= byte; tmp2 |= tmp; tmp2 <<= 16; tmp2 |= tmp; lword |= tmp2; lword <<= 32; lword |= tmp2;#endif } lptr = (int *)MMALIGN_CEIL(ptr, int); ltoptr = (int *)MMALIGN_FLOOR(toptr, int); while (ptr < (char *)lptr) *ptr++ = byte;#if !defined(ARCH_LOWCACHE) while (lptr < ltoptr - (sizeof(int) * 8)) { *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; *lptr++ = lword; }#endif /* !defined(ARCH_LOWCACHE) */ while (lptr < ltoptr) *lptr++ = lword; ptr = (char *)lptr; while (ptr < toptr) *ptr++ = byte; }#endif /* !defined(ARCH_INT8) */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -