1/* 2 * Copyright (C) 2008-2010 Free Software Foundation, Inc. 3 * Written by Eric Blake and Bruno Haible 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19 20#include <string.h> 21 22#include "signature.h" 23SIGNATURE_CHECK (memchr, void *, (void const *, int, size_t)); 24 25#include <stdlib.h> 26 27#include "zerosize-ptr.h" 28#include "macros.h" 29 30/* Calculating void * + int is not portable, so this wrapper converts 31 to char * to make the tests easier to write. */ 32#define MEMCHR (char *) memchr 33 34int 35main (void) 36{ 37 size_t n = 0x100000; 38 char *input = malloc (n); 39 ASSERT (input); 40 41 input[0] = 'a'; 42 input[1] = 'b'; 43 memset (input + 2, 'c', 1024); 44 memset (input + 1026, 'd', n - 1028); 45 input[n - 2] = 'e'; 46 input[n - 1] = 'a'; 47 48 /* Basic behavior tests. */ 49 ASSERT (MEMCHR (input, 'a', n) == input); 50 51 ASSERT (MEMCHR (input, 'a', 0) == NULL); 52 ASSERT (MEMCHR (zerosize_ptr (), 'a', 0) == NULL); 53 54 ASSERT (MEMCHR (input, 'b', n) == input + 1); 55 ASSERT (MEMCHR (input, 'c', n) == input + 2); 56 ASSERT (MEMCHR (input, 'd', n) == input + 1026); 57 58 ASSERT (MEMCHR (input + 1, 'a', n - 1) == input + n - 1); 59 ASSERT (MEMCHR (input + 1, 'e', n - 1) == input + n - 2); 60 61 ASSERT (MEMCHR (input, 'f', n) == NULL); 62 ASSERT (MEMCHR (input, '\0', n) == NULL); 63 64 /* Check that a very long haystack is handled quickly if the byte is 65 found near the beginning. */ 66 { 67 size_t repeat = 10000; 68 for (; repeat > 0; repeat--) 69 { 70 ASSERT (MEMCHR (input, 'c', n) == input + 2); 71 } 72 } 73 74 /* Alignment tests. */ 75 { 76 int i, j; 77 for (i = 0; i < 32; i++) 78 { 79 for (j = 0; j < 256; j++) 80 input[i + j] = j; 81 for (j = 0; j < 256; j++) 82 { 83 ASSERT (MEMCHR (input + i, j, 256) == input + i + j); 84 } 85 } 86 } 87 88 /* Check that memchr() does not read past the first occurrence of the 89 byte being searched. See the Austin Group's clarification 90 <http://www.opengroup.org/austin/docs/austin_454.txt>. */ 91 { 92 char *page_boundary = (char *) zerosize_ptr (); 93 94 if (page_boundary != NULL) 95 { 96 for (n = 1; n <= 500; n++) 97 { 98 char *mem = page_boundary - n; 99 memset (mem, 'X', n); 100 ASSERT (MEMCHR (mem, 'U', n) == NULL); 101 102 { 103 size_t i; 104 105 for (i = 0; i < n; i++) 106 { 107 mem[i] = 'U'; 108 ASSERT (MEMCHR (mem, 'U', 4000) == mem + i); 109 mem[i] = 'X'; 110 } 111 } 112 } 113 } 114 } 115 116 free (input); 117 118 return 0; 119} 120