memchr.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* Scan memory for a character. Generic version
  2. Copyright (C) 1991-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <libc-pointer-arith.h>
  16. #include <string-fzb.h>
  17. #include <string-fzc.h>
  18. #include <string-fzi.h>
  19. #include <string-shift.h>
  20. #include <string.h>
  21. #undef memchr
  22. #ifdef MEMCHR
  23. # define __memchr MEMCHR
  24. #endif
  25. static __always_inline const char *
  26. sadd (uintptr_t x, uintptr_t y)
  27. {
  28. return (const char *)(y > UINTPTR_MAX - x ? UINTPTR_MAX : x + y);
  29. }
  30. /* Search no more than N bytes of S for C. */
  31. void *
  32. __memchr (void const *s, int c_in, size_t n)
  33. {
  34. if (__glibc_unlikely (n == 0))
  35. return NULL;
  36. /* Read the first word, but munge it so that bytes before the array
  37. will not match goal. */
  38. const op_t *word_ptr = PTR_ALIGN_DOWN (s, sizeof (op_t));
  39. uintptr_t s_int = (uintptr_t) s;
  40. op_t word = *word_ptr;
  41. op_t repeated_c = repeat_bytes (c_in);
  42. /* Compute the address of the last byte taking in consideration possible
  43. overflow. */
  44. const char *lbyte = sadd (s_int, n - 1);
  45. /* And also the address of the word containing the last byte. */
  46. const op_t *lword = (const op_t *) PTR_ALIGN_DOWN (lbyte, sizeof (op_t));
  47. find_t mask = shift_find (find_eq_all (word, repeated_c), s_int);
  48. if (mask != 0)
  49. {
  50. char *ret = (char *) s + index_first (mask);
  51. return (ret <= lbyte) ? ret : NULL;
  52. }
  53. if (word_ptr == lword)
  54. return NULL;
  55. word = *++word_ptr;
  56. while (word_ptr != lword)
  57. {
  58. if (has_eq (word, repeated_c))
  59. return (char *) word_ptr + index_first_eq (word, repeated_c);
  60. word = *++word_ptr;
  61. }
  62. if (has_eq (word, repeated_c))
  63. {
  64. /* We found a match, but it might be in a byte past the end of the
  65. array. */
  66. char *ret = (char *) word_ptr + index_first_eq (word, repeated_c);
  67. if (ret <= lbyte)
  68. return ret;
  69. }
  70. return NULL;
  71. }
  72. #ifndef MEMCHR
  73. weak_alias (__memchr, memchr)
  74. libc_hidden_builtin_def (memchr)
  75. #endif