hrev43470 adds 2 changesets to branch 'master' old head: 2a8373704a3a028df23daa12063928ba3383ed25 new head: 04fccd250fe3bb28f5f0010b1a60ad22f1cd64dc ---------------------------------------------------------------------------- 7cd683b: fix typo 04fccd2: added hcreate, hdestroy, hsearch from glibc [ Jérôme Duval <jerome.duval@xxxxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 291 insertions(+), 2 deletions(-) src/bin/addattr/addAttr.cpp | 4 +- src/system/libroot/posix/glibc/misc/Jamfile | 2 + src/system/libroot/posix/glibc/misc/hsearch.c | 57 +++++ src/system/libroot/posix/glibc/misc/hsearch_r.c | 230 +++++++++++++++++++ ############################################################################ Commit: 7cd683ba12f74771eb851c29df10b8e8192039b2 URL: http://cgit.haiku-os.org/haiku/commit/?id=7cd683b Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Sun Dec 11 09:36:16 2011 UTC fix typo ---------------------------------------------------------------------------- diff --git a/src/bin/addattr/addAttr.cpp b/src/bin/addattr/addAttr.cpp index 8af3251..a404413 100644 --- a/src/bin/addattr/addAttr.cpp +++ b/src/bin/addattr/addAttr.cpp @@ -33,9 +33,9 @@ writeAttrValue(int fd, const char *name, type_code type, Type value) /** Writes an attribute to a node, taking the type into account and - * convertig the value accordingly + * converting the value accordingly * - * On success it will return the amount of bytes writen + * On success it will return the amount of bytes written * On failure it returns an error code (negative number) */ ############################################################################ Revision: hrev43470 Commit: 04fccd250fe3bb28f5f0010b1a60ad22f1cd64dc URL: http://cgit.haiku-os.org/haiku/commit/?id=04fccd2 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Sun Dec 11 09:42:38 2011 UTC added hcreate, hdestroy, hsearch from glibc ---------------------------------------------------------------------------- diff --git a/src/system/libroot/posix/glibc/misc/Jamfile b/src/system/libroot/posix/glibc/misc/Jamfile index 52767e5..937e164 100644 --- a/src/system/libroot/posix/glibc/misc/Jamfile +++ b/src/system/libroot/posix/glibc/misc/Jamfile @@ -16,6 +16,8 @@ UsePrivateHeaders libroot ; SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; MergeObject posix_gnu_misc.o : + hsearch.c + hsearch_r.c insremque.c lsearch.c tsearch.c diff --git a/src/system/libroot/posix/glibc/misc/hsearch.c b/src/system/libroot/posix/glibc/misc/hsearch.c new file mode 100644 index 0000000..79d38f5 --- /dev/null +++ b/src/system/libroot/posix/glibc/misc/hsearch.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@xxxxxxxxxxxxxx> + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <search.h> + +/* The non-reentrant version use a global space for storing the table. */ +static struct hsearch_data htab; + + +/* Define the non-reentrant function using the reentrant counterparts. */ +ENTRY * +hsearch (item, action) + ENTRY item; + ACTION action; +{ + ENTRY *result; + + (void) hsearch_r (item, action, &result, &htab); + + return result; +} + + +int +hcreate (nel) + size_t nel; +{ + return hcreate_r (nel, &htab); +} + + +void +__hdestroy () +{ + hdestroy_r (&htab); +} +weak_alias (__hdestroy, hdestroy) + +/* Make sure the table is freed if we want to free everything before + exiting. */ +text_set_element (__libc_subfreeres, __hdestroy); diff --git a/src/system/libroot/posix/glibc/misc/hsearch_r.c b/src/system/libroot/posix/glibc/misc/hsearch_r.c new file mode 100644 index 0000000..0dec896 --- /dev/null +++ b/src/system/libroot/posix/glibc/misc/hsearch_r.c @@ -0,0 +1,230 @@ +/* Copyright (C) 1993,1995-1997,2002,2005,2007,2008,2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@xxxxxxxxxxxxxx>, 1993. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <malloc.h> +#include <string.h> + +#include <search.h> + +/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 + [Knuth] The Art of Computer Programming, part 3 (6.4) */ + + +/* The reentrant version has no static variables to maintain the state. + Instead the interface of all functions is extended to take an argument + which describes the current status. */ +typedef struct _ENTRY +{ + unsigned int used; + ENTRY entry; +} +_ENTRY; + + +/* For the used double hash method the table size has to be a prime. To + correct the user given table size we need a prime test. This trivial + algorithm is adequate because + a) the code is (most probably) called a few times per program run and + b) the number is small because the table must fit in the core */ +static int +isprime (unsigned int number) +{ + /* no even number will be passed */ + unsigned int div = 3; + + while (div * div < number && number % div != 0) + div += 2; + + return number % div != 0; +} + + +/* Before using the hash table we must allocate memory for it. + Test for an existing table are done. We allocate one element + more as the found prime number says. This is done for more effective + indexing as explained in the comment for the hsearch function. + The contents of the table is zeroed, especially the field used + becomes zero. */ +int +hcreate_r (nel, htab) + size_t nel; + struct hsearch_data *htab; +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return 0; + } + + /* There is still another table active. Return with error. */ + if (htab->table != NULL) + return 0; + + /* We need a size of at least 3. Otherwise the hash functions we + use will not work. */ + if (nel < 3) + nel = 3; + /* Change nel to the first prime number not smaller as nel. */ + nel |= 1; /* make odd */ + while (!isprime (nel)) + nel += 2; + + htab->size = nel; + htab->filled = 0; + + /* allocate memory and zero out */ + htab->table = (_ENTRY *) calloc (htab->size + 1, sizeof (_ENTRY)); + if (htab->table == NULL) + return 0; + + /* everything went alright */ + return 1; +} +libc_hidden_def (hcreate_r) + + +/* After using the hash table it has to be destroyed. The used memory can + be freed and the local static variable can be marked as not used. */ +void +hdestroy_r (htab) + struct hsearch_data *htab; +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return; + } + + /* Free used memory. */ + free (htab->table); + + /* the sign for an existing table is an value != NULL in htable */ + htab->table = NULL; +} +libc_hidden_def (hdestroy_r) + + +/* This is the search function. It uses double hashing with open addressing. + The argument item.key has to be a pointer to an zero terminated, most + probably strings of chars. The function for generating a number of the + strings is simple but fast. It can be replaced by a more complex function + like ajw (see [Aho,Sethi,Ullman]) if the needs are shown. + + We use an trick to speed up the lookup. The table is created by hcreate + with one more element available. This enables us to use the index zero + special. This index will never be used because we store the first hash + index in the field used where zero means not used. Every other value + means used. The used field can be used as a first fast comparison for + equality of the stored and the parameter value. This helps to prevent + unnecessary expensive calls of strcmp. */ +int +hsearch_r (item, action, retval, htab) + ENTRY item; + ACTION action; + ENTRY **retval; + struct hsearch_data *htab; +{ + unsigned int hval; + unsigned int count; + unsigned int len = strlen (item.key); + unsigned int idx; + + /* Compute an value for the given string. Perhaps use a better method. */ + hval = len; + count = len; + while (count-- > 0) + { + hval <<= 4; + hval += item.key[count]; + } + if (hval == 0) + ++hval; + + /* First hash function: simply take the modul but prevent zero. */ + idx = hval % htab->size + 1; + + if (htab->table[idx].used) + { + /* Further action might be required according to the action value. */ + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + { + /* Second hash function, as suggested in [Knuth] */ + unsigned int hval2 = 1 + hval % (htab->size - 2); + unsigned int first_idx = idx; + + do + { + /* Because SIZE is prime this guarantees to step through all + available indeces. */ + if (idx <= hval2) + idx = htab->size + idx - hval2; + else + idx -= hval2; + + /* If we visited all entries leave the loop unsuccessfully. */ + if (idx == first_idx) + break; + + /* If entry is found use it. */ + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + } + while (htab->table[idx].used); + } + } + + /* An empty bucket has been found. */ + if (action == ENTER) + { + /* If table is full and another entry should be entered return + with error. */ + if (htab->filled == htab->size) + { + __set_errno (ENOMEM); + *retval = NULL; + return 0; + } + + htab->table[idx].used = hval; + htab->table[idx].entry = item; + + ++htab->filled; + + *retval = &htab->table[idx].entry; + return 1; + } + + __set_errno (ESRCH); + *retval = NULL; + return 0; +} +libc_hidden_def (hsearch_r)