分类: C 2009-10-08 12:56 288人阅读 评论(0) 收藏 举报
8、特定区域的字符串比较和转换strcoll,strxfrm,wcscoll,wcsxfrm:strcoll使用当前的区域设置来比较字符串,strxfrm使用当前的区域设置来转换字符串。当前区域设置由LL_COLLATE宏指定。它们均调用带有区域设置参数的内部版本strcoll_l和strxfrm_l来完成实际的工作。
view plaincopy to clipboardprint?
1. /* strcoll.c:strcoll函数的实现 */ 2. #include 9. #include \"../locale/localeinfo.h\" 10. int 11. STRCOLL (s1, s2) 12. const STRING_TYPE *s1; 13. const STRING_TYPE *s2; 14. { 15. return STRCOLL_L (s1, s2, _NL_CURRENT_LOCALE); 16. } 17. #ifdef USE_HIDDEN_DEF 18. libc_hidden_def (STRCOLL) 19. #endif /* strcoll.c:strcoll函数的实现 */#include 3. #include 10. STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n) 11. { 12. return STRXFRM_L (dest, src, n, _NL_CURRENT_LOCALE); 13. } /* strxfrm.c:strxfrm函数的实现 */#include 1. /* strerror.c:strerror函数的实现 */ 2. #include 5. #include 6. /* 返回错误码errnum的字符串描述,在下一次调用strerror之前这个字符串存储 7. 空间不能修改,对这个空间进行写操作会导致未定义的行为 */ 8. libc_freeres_ptr (static char *buf); /* 存放字符串描述的全局空间 */ 9. char * 10. strerror (errnum) 11. int errnum; 12. { 13. char *ret = __strerror_r (errnum, NULL, 0); /* 根据错误码获取错误消息 */ 14. int saved_errno; 15. if (__builtin_expect (ret != NULL, 1)) /* 若错误消息获取成功,则返回它 */ 16. return ret; 17. /* 否则获取errno中保存的程序错误码,用缓冲区buf来存储它的字符串描 述 */ 18. saved_errno = errno; 19. if (buf == NULL) 20. buf = malloc (1024); /* buf是一个全局缓冲区 */ 21. __set_errno (saved_errno); /* 设置错误码 */ 22. if (buf == NULL) 23. return _(\"Unknown error\"); 24. return __strerror_r (errnum, buf, 1024); /* 获取错误码对应的错误消息并返 回 */ 25. } /* strerror.c:strerror函数的实现 */#include 3. 1、复制字节,直到目标指针被对齐。 4. 2、在展开的循环中复制字。如果源指针和目标指针不是用 5. 同一种方式对齐,则使用字内存操作,但在写之前要对两个读取的字进行移位 和合并 6. 3、复制剩下的几个字节 7. 在至少有10个寄存器用来给GCC使用的处理器上,这是非常快速的,并且能 在一条指令中使用 8. reg+const来访问内存 */ 9. #include 12. BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) 13. BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) 14. WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_t o_copy) 15. WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_t o_copy) 16. MERGE(old_word, sh_1, new_word, sh_2) 17. */ 18. /* 用于对齐的内存操作类型,正常时它应该是能一次装载和存储的最大类型 */ 19. #define op_t unsigned long int 20. #define OPSIZ (sizeof(op_t)) 21. /* 用于未对齐的操作类型 */ 22. typedef unsigned char byte; 23. /* 用于在寄存器中存储字节的优化类型 */ 24. #define reg_char char 25. /* 对两个字的合并操作 */ 26. #if __BYTE_ORDER == __LITTLE_ENDIAN /* 小端字节序:w0在低端,w1 在高端 */ 27. #define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) 28. #endif 29. #if __BYTE_ORDER == __BIG_ENDIAN /* 大端字节序:w0在高端,w1在低 端 */ 30. #define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) 31. #endif 32. /* 向前复制:从SRC_BP中精确地复制NBTYES个字节到DST_BP中,无需 对指针的对齐作任何假设 */ 33. #define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) / 34. do / 35. { / 36. size_t __nbytes = (nbytes); / 37. while (__nbytes > 0) / 38. { / 39. byte __x = ((byte *) src_bp)[0]; / 40. src_bp += 1; / 41. __nbytes -= 1; / 42. ((byte *) dst_bp)[0] = __x; / 43. dst_bp += 1; / 44. } / 45. } while (0) 46. /* 向后复制:从SRC_END_PTR中精确地复制NBTYTES_TO_COPY个字节 到DST_END_PTR中, 47. 复制从指针前面的字节右端开始,并且向着更小的地址方向前进。无需对指针 的对齐作任何假设 */ 48. #define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) / 49. do / 50. { / 51. size_t __nbytes = (nbytes); / 52. while (__nbytes > 0) / 53. { / 54. byte __x; / 55. src_ep -= 1; / 56. __x = ((byte *) src_ep)[0]; / 57. dst_ep -= 1; / 58. __nbytes -= 1; / 59. ((byte *) dst_ep)[0] = __x; / 60. } / 61. } while (0) 62. /* 向前复制:从SRC_BP中复制最多NBYTES个字节到DST_BP中,假设 DST_BP对齐到OPSIZ的倍数。 63. 如果不是所有的字节都能顺利的复制,剩下的字节数保存到NBYTES_LEFT 中,否则存入0 */ . extern void _wordcopy_fwd_aligned (long int, long int, size_t) __THROW; 65. extern void _wordcopy_fwd_dest_aligned (long int, long int, size_t) __THRO W; 66. #define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) / 67. do / 68. { / 69. if (src_bp % OPSIZ == 0) / 70. _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); / 71. else / 72. _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); / 73. src_bp += (nbytes) & -OPSIZ; / 74. dst_bp += (nbytes) & -OPSIZ; / 75. (nbytes_left) = (nbytes) % OPSIZ; / 76. } while (0) 77. /* 向后复制:从SRC_END_PTR中复制最多NBYTES_TO_COPY个字节到 DST_END_PTR中,复制 78. 从指针前面的字(为op_t类型)的右端开始,并且向着更小的地址方向前进。 可以利用DST_END_PTR 79. 已经对齐到OPSIZ的倍数。如果不是所有的字节都能顺利的复制,剩下的字 节数保存到 80. NBYTES_REMAINING中,否则存入0 */ 81. extern void _wordcopy_bwd_aligned (long int, long int, size_t) __THROW; 82. extern void _wordcopy_bwd_dest_aligned (long int, long int, size_t) __THR OW; 83. #define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) / 84. do / 85. { / 86. if (src_ep % OPSIZ == 0) / 87. _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); / 88. else / . _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); / 90. src_ep -= (nbytes) & -OPSIZ; / 91. dst_ep -= (nbytes) & -OPSIZ; / 92. (nbytes_left) = (nbytes) % OPSIZ; / 93. } while (0) 94. /* 进入展开循环的门槛值 */ 95. #define OP_T_THRES 16 /* memcopy.h -- 在内存复制函数中使用的一些定义 *//* 内存函数的复制策略是: 1、复制字节,直到目标指针被对齐。 2、在展开的循环中复制字。如果源指针和目标指针不是用 同一种方式对齐,则使用字内存操作,但在写之前要对两 3、复制剩下的几个字节 在至少有10个寄存器用来给GCC使用的处理器上,这是非 reg+const来访问内存 */#include 3. PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nbytes) 4. 由WORD_COPY_FWD以及其他的函数来调用,指针至少要是字对齐的。这将 会检查虚页复制是否能 5. 执行、是否应该执行、以及如果能执行的话则执行它 6. 依赖于系统的pagecopy.h文件应该定义以下宏,然后包含本文件: 7. PAGE_COPY_THRESHOLD 8. -- 值得使用按页复制策略的最小字节数 9. PAGE_SIZE 10. -- 页的大小 11. PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes) 12. -- 执行虚页复制操作的宏。指针要对齐到PAGE_SIZE个字节的边界上 13. */ 14. #if PAGE_COPY_THRESHOLD 15. #include 16. #define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) / 17. do / 18. { / 19. if ((nbytes) >= PAGE_COPY_THRESHOLD && / 20. PAGE_OFFSET ((dstp) - (srcp)) == 0) / 21. { / 22. /* 要复制的字节数超过内核用于复制虚拟页的VM操作的门槛值,且源地 址 / 23. 和目标地址有同样的对齐方式 */ / 24. size_t nbytes_before = PAGE_OFFSET (-(dstp)); / 25. if (nbytes_before != 0) / 26. { / 27. /* 首先复制第一页前面的各个字 */ / 28. WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before); / 29. assert (nbytes_left == 0); / 30. nbytes -= nbytes_before; / 31. } / 32. PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes); / 33. } / 34. } while (0) 35. /* 页大小总是2的幂,这样我们就可以避免模除法运算 */ 36. #define PAGE_OFFSET(n) ((n) & (PAGE_SIZE - 1)) 37. #else 38. #define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) 39. #endif /* pagecopy.h -- 按页方式来复制的宏;用在memcpy和memm/* 本文件中定义的宏: PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nb 由WORD_COPY_FWD以及其他的函数来调用,指针至少要是字 执行、是否应该执行、以及如果能执行的话则执行它 依赖于系统的pagecopy.h文件应该定义以下宏,然后包含 PAGE_COPY_THRESHOLD -- 值得使用按页复制策略的最小字节数 PAGE_SIZE -- 页的大小 PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes) -- 执行虚页复制操作的宏。指针要对齐到PAGE_SIZE个字节*/#if PAGE_COPY_THRESHOLD#include 3. #include 数WORD_COPY_FWD */ 4. #include PAGE_COPY_FWD_MAYBE */ 5. #undef memcpy 6. /* 从src中复制len个字节的内容到dst中 */ 7. void * 8. memcpy (dstpp, srcpp, len) 9. void *dstpp; 10. const void *srcpp; 11. size_t len; 12. { 13. unsigned long int dstp = (long int) dstpp; 14. unsigned long int srcp = (long int) srcpp; 15. /* 从开始复制到末尾 */ 16. /* 如果len足够长,使用字复制方式(一个字为long类型,一般占4个字节) */ 17. if (len >= OP_T_THRES) 18. { 19. /* 复制开头的几个字节,以使dstp对齐到字的边界 */ 20. len -= (-dstp) % OPSIZ; 21. BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); /* 字节复制方式 */ 22. /* 通过虚拟地址操作,从srcp中复制尽可能多的页到dstp中 */ 23. PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); /* 页复制方式 */ 24. /* 利用对齐的dstp,采用字复制方式从srcp复制到dstp。剩余的字节数放 在第三个实参中, 25. 例如放在len中。这个数字可能在不同的机器有不同的值 */ 26. WORD_COPY_FWD (dstp, srcp, len, len); 27. /* 复制剩下的尾部几个字节 */ 28. } 29. /* 还有剩下的几个字节,使用字节内存操作 */ 30. BYTE_COPY_FWD (dstp, srcp, len); 31. return dstpp; 32. } 33. libc_hidden_builtin_def (memcpy) /* memcpy.c:memcpy函数的实现 */#include 3. #include 数WORD_COPY_FWD */ 4. #include PAGE_COPY_FWD_MAYBE */ 5. /* 所有这些都是为了在定义了一些东西后bcopy.c能包含本文件 */ 6. #ifndef a1 7. #define a1 dest /* 第一个实参是dest */ 8. #define a1const 9. #define a2 src /* 第二个实参是src */ 10. #define a2const const 11. #undef memmove 12. #endif 13. #if !defined(RETURN) || !defined(rettype) 14. #define RETURN(s) return (s) /* 返回dest */ 15. #define rettype void * 16. #endif 17. /* 从SRC中复制LEN个字节的内容到DEST中,保证对重叠字符串(即SRC 与DEST共用存储空间)有正确的行为 */ 18. rettype 19. memmove (a1, a2, len) 20. a1const void *a1; 21. a2const void *a2; 22. size_t len; 23. { 24. unsigned long int dstp = (long int) dest; 25. unsigned long int srcp = (long int) src; 26. /* 这个测试使得向前复制代码一旦可能就能被使用,减少工作集 */ 27. if (dstp - srcp >= len) /* *Unsigned* compare! */ 28. { 29. /* 从开始复制到末尾 */ 30. /* 如果len足够长,使用字复制方式(一个字为long类型,一般占4个字节) */ 31. if (len >= OP_T_THRES) 32. { 33. /* 复制开头的几个字节,以使dstp对齐到字的边界 */ 34. len -= (-dstp) % OPSIZ; 35. BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); /* 字节复制方式 */ 36. /* 通过虚拟地址操作,从srcp中复制尽可能多的页到dstp中 */ 37. PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); /* 页复制方式 */ 38. /* 利用对齐的dstp,采用字复制方式从srcp复制到dstp。剩余的字节数放 在第三个实参中, 39. 例如放在len中。这个数字可能在不同的机器有不同的值 */ 40. WORD_COPY_FWD (dstp, srcp, len, len); 41. /* 复制剩下的尾部几个字节 */ 42. } 43. /* 还有剩下的几个字节,使用字节内存操作 */ 44. BYTE_COPY_FWD (dstp, srcp, len); 45. } 46. else 47. { 48. /* 从开始复制到末尾 */ 49. srcp += len; 50. dstp += len; 51. /* 如果len足够长,使用字复制方式(一个字为long类型,一般占4个字节) */ 52. if (len >= OP_T_THRES) 53. { 54. /* 复制开头的几个字节,以使dstp对齐到字的边界 */ 55. len -= dstp % OPSIZ; 56. BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); 57. /* 利用对齐的dstp,采用字复制方式从srcp复制到dstp。剩余的字节数放 在第三个实参中, 58. 例如放在len中。这个数字可能在不同的机器有不同的值 */ 59. WORD_COPY_BWD (dstp, srcp, len, len); 60. /* 复制剩下的尾部几个字节 */ 61. } 62. /* 还有剩下的几个字节,使用字节内存操作 */ 63. BYTE_COPY_BWD (dstp, srcp, len); . } 65. RETURN (dest); 66. } 67. #ifndef memmove 68. libc_hidden_builtin_def (memmove) 69. #endif /* memmove.c:memmove函数的实现 */#include 6. /* 标准C++或标准C中通用指针为void*类型 */ 7. #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) 8. # define __ptr_t void * 9. #else /* 传统C中通用指针为char*类型 */ 10. # define __ptr_t char * 11. #endif 12. #if defined _LIBC 13. # include 16. # define reg_char char 17. #endif 18. #if HAVE_STDLIB_H || defined _LIBC 19. # include 21. #if HAVE_LIMITS_H || defined _LIBC 22. # include 24. #define LONG_MAX_32_BITS 21474837 25. #ifndef LONG_MAX 26. #define LONG_MAX LONG_MAX_32_BITS 27. #endif 28. #include 29. #if HAVE_BP_SYM_H || defined _LIBC 30. #include 32. # define BP_SYM(sym) sym 33. #endif 34. #undef memchr 35. #undef __memchr 36. /* 在S的前N个字节中搜索C的第一次出现 */ 37. __ptr_t 38. __memchr (s, c_in, n) 39. const __ptr_t s; 40. int c_in; 41. size_t n; 42. { 43. const unsigned char *char_ptr; 44. const unsigned long int *longword_ptr; 45. unsigned long int longword, magic_bits, charmask; 46. unsigned reg_char c; 47. c = (unsigned char) c_in; 48. /* 通过一次读取一个字符来处理开头的几个字符,直到char_ptr中的值对齐到 一个long型字的边界, 49. 即直到char_ptr中的值是long的字节数(通常为4)的倍数 */ 50. for (char_ptr = (const unsigned char *) s; 51. n > 0 && ((unsigned long int) char_ptr 52. & (sizeof (longword) - 1)) != 0; 53. --n, ++char_ptr) 54. if (*char_ptr == c) /* 若到达字符c处,则直接返回其指针 */ 55. return (__ptr_t) char_ptr; 56. /* 所有这些说明性的注释使用4字节的long型字,但本算法同样也可以应用于 8字节的long型字 */ 57. longword_ptr = (unsigned long int *) char_ptr; 58. /* magic_bits的第8,16,24,31位为0,称这些位为“洞”。注意每个字节的左边 有一个洞, 59. 在最后的位置上也有一个洞。 60. bits: 01111110 11111110 11111110 11111111 61. 比特1确保进位能传播到后面的比特0上,比特0则提供洞,以便让进位陷 进去 */ 62. if (sizeof (longword) != 4 && sizeof (longword) != 8) 63. abort (); . #if LONG_MAX <= LONG_MAX_32_BITS 65. magic_bits = 0x7efefeff; 66. #else 67. magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; 68. #endif 69. /* 设置一个长整型字,其每个字节都是字符c */ 70. charmask = c | (c << 8); 71. charmask |= charmask << 16; 72. #if LONG_MAX > LONG_MAX_32_BITS 73. charmask |= charmask << 32; 74. #endif 75. /* 这里我们不使用传统的对每个字符都进行测试的循环,而是一次测试一个 long型字。技巧性的部分 76. 是测试当前long型字的各个字节是否为0 */ 77. while (n >= sizeof (longword)) 78. { 79. /* longword中有一个字节为C,恰好等价于longword ^ charmask中有一个 字节为0 */ 80. longword = *longword_ptr++ ^ charmask; 81. /* 让longword加上魔数magic_bits */ 82. if ((((longword + magic_bits) 83. /* 设置那些通过加法而未改变的位 */ 84. ^ ~longword) 85. /* 只需看这些洞。如果任何的洞位都没有改变,最有可能的是有一个字节值 为C或者到达终止符处(没找到C) */ 86. & ~magic_bits) != 0) 87. { 88. /* 长整型字的哪个字节为C或0?如果都不是,则是一个非预期情况,继续 搜索 */ . const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); 90. if (cp[0] == c) 91. return (__ptr_t) cp; 92. if (cp[1] == c) 93. return (__ptr_t) &cp[1]; 94. if (cp[2] == c) 95. return (__ptr_t) &cp[2]; 96. if (cp[3] == c) 97. return (__ptr_t) &cp[3]; 98. #if LONG_MAX > 21474837 /* 如果long类型是8个字节,则还有4个字 节需要判断 */ 99. if (cp[4] == c) 100. return (__ptr_t) &cp[4]; 101. if (cp[5] == c) 102. return (__ptr_t) &cp[5]; 103. if (cp[6] == c) 104. return (__ptr_t) &cp[6]; 105. if (cp[7] == c) 106. return (__ptr_t) &cp[7]; 107. #endif 108. } 109. n -= sizeof (longword); 110. } 111. /* 循环完如果还剩下几个字节,则继承搜索这剩下的几个字节 */ 112. char_ptr = (const unsigned char *) longword_ptr; 113. while (n-- > 0) 114. { 115. if (*char_ptr == c) 116. return (__ptr_t) char_ptr; 117. else 118. ++char_ptr; 119. } 120. return 0; 121. } 122. #ifdef weak_alias 123. weak_alias (__memchr, BP_SYM (memchr)) 124. #endif 125. libc_hidden_builtin_def (memchr) /* memchr.c:memchr函数的实现 */#ifdef HAVE_CONFIG_H#include 13、内存块设置memset,wmemset:将内存块的前LEN个字节设置为字符C。也是采用字的方式来进行快速地写入。先设置了一个字cccc,其每个字节都是字符C。为了加快写入速度,每循环一次就写入8个cccc,最后对剩下的几个字节写入C。 view plaincopy to clipboardprint? 1. /* memset.c:memset函数的实现 */ 2. #include 5. /* 将内存块DST的前LEN个字节设置为字符C */ 6. void * 7. memset (dstpp, c, len) 8. void *dstpp; 9. int c; 10. size_t len; 11. { 12. long int dstp = (long int) dstpp; 13. if (len >= 8) 14. { 15. size_t xlen; 16. op_t cccc; 17. 18. /* 设置一个长整型字,其每个字节都是字符c */ 19. cccc = (unsigned char) c; 20. cccc |= cccc << 8; 21. cccc |= cccc << 16; 22. if (OPSIZ > 4) 23. /* 移位操作分两步,以避免当long为32位时出现警告 */ 24. cccc |= (cccc << 16) << 16; 25. /* 把dstp对齐到字的边界,开头的几个字节要设置为C,在这个对齐循环中 无需 26. 测试LEN是否等于0 */ 27. while (dstp % OPSIZ != 0) 28. { 29. ((byte *) dstp)[0] = c; 30. dstp += 1; 31. len -= 1; 32. } 33. /* 每次迭代中写8个op_t型的字,直到剩下不到8个字为止 */ 34. xlen = len / (OPSIZ * 8); /* 计算迭代次数 */ 35. while (xlen > 0) 36. { 37. ((op_t *) dstp)[0] = cccc; 38. ((op_t *) dstp)[1] = cccc; 39. ((op_t *) dstp)[2] = cccc; 40. ((op_t *) dstp)[3] = cccc; 41. ((op_t *) dstp)[4] = cccc; 42. ((op_t *) dstp)[5] = cccc; 43. ((op_t *) dstp)[6] = cccc; 44. ((op_t *) dstp)[7] = cccc; 45. dstp += 8 * OPSIZ; 46. xlen -= 1; 47. } 48. len %= OPSIZ * 8; /* 计算剩下的字节数 */ 49. /* 每次迭代写1个字,直到剩下不到OPSIZ个字节为止 */ 50. xlen = len / OPSIZ; /* 计算迭代次数 */ 51. while (xlen > 0) 52. { 53. ((op_t *) dstp)[0] = cccc; 54. dstp += OPSIZ; 55. xlen -= 1; 56. } 57. len %= OPSIZ; 58. } 59. /* 写入最后剩下的几个字节 */ 60. while (len > 0) 61. { 62. ((byte *) dstp)[0] = c; 63. dstp += 1; . len -= 1; 65. } 66. return dstpp; 67. } 68. libc_hidden_builtin_def (memset)
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务