mcabber/libjabber/hashtable.c
author Mikael Berthe <mikael@lilotux.net>
Sat, 16 Jun 2007 11:48:56 +0200
changeset 1234 2b7a4d003057
parent 25 bf3d6e241714
permissions -rw-r--r--
Update PL help files (Salvador)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     1
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     2
The contents of this file are subject to the Mozilla Public License
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     3
Version 1.1 (the "License"); you may not use this file except in
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     4
csompliance with the License. You may obtain a copy of the License at
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     5
http://www.mozilla.org/MPL/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     6
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     7
Software distributed under the License is distributed on an "AS IS"
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     8
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     9
License for the specific language governing rights and limitations
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    10
under the License.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    11
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    12
The Original Code is expat.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    13
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    14
The Initial Developer of the Original Code is James Clark.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    15
Portions created by James Clark are Copyright (C) 1998, 1999
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    16
James Clark. All Rights Reserved.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    17
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    18
Contributor(s):
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    19
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    20
Alternatively, the contents of this file may be used under the terms
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    21
of the GNU General Public License (the "GPL"), in which case the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    22
provisions of the GPL are applicable instead of those above.  If you
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    23
wish to allow use of your version of this file only under the terms of
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    24
the GPL and not to allow others to use your version of this file under
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    25
the MPL, indicate your decision by deleting the provisions above and
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    26
replace them with the notice and other provisions required by the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    27
GPL. If you do not delete the provisions above, a recipient may use
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    28
your version of this file under either the MPL or the GPL.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    29
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    30
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    31
#include "xmldef.h"
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    32
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    33
#ifdef XML_UNICODE_WCHAR_T
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    34
#ifndef XML_UNICODE
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    35
#define XML_UNICODE
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    36
#endif
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    37
#endif
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    38
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    39
#include "hashtable.h"
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    40
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    41
#define INIT_SIZE 64
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    42
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    43
static
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    44
int keyeq(KEY s1, KEY s2)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    45
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    46
    for (; *s1 == *s2; s1++, s2++)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    47
        if (*s1 == 0)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    48
            return 1;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    49
    return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    50
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    51
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    52
static
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    53
unsigned long hash(KEY s)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    54
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    55
    unsigned long h = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    56
    while (*s)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    57
        h = (h << 5) + h + (unsigned char)*s++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    58
    return h;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    59
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    60
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    61
NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    62
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    63
    size_t i;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    64
    if (table->size == 0) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    65
        if (!createSize)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    66
            return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    67
        table->v = calloc(INIT_SIZE, sizeof(NAMED *));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    68
        if (!table->v)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    69
            return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    70
        table->size = INIT_SIZE;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    71
        table->usedLim = INIT_SIZE / 2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    72
        i = hash(name) & (table->size - 1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    73
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    74
    else {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    75
        unsigned long h = hash(name);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    76
        for (i = h & (table->size - 1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    77
                table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    78
                i == 0 ? i = table->size - 1 : --i) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    79
            if (keyeq(name, table->v[i]->name))
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    80
                return table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    81
        }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    82
        if (!createSize)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    83
            return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    84
        if (table->used == table->usedLim) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    85
            /* check for overflow */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    86
            size_t newSize = table->size * 2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    87
            NAMED **newV = calloc(newSize, sizeof(NAMED *));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    88
            if (!newV)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    89
                return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    90
            for (i = 0; i < table->size; i++)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    91
                if (table->v[i]) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    92
                    size_t j;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    93
                    for (j = hash(table->v[i]->name) & (newSize - 1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    94
                            newV[j];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    95
                            j == 0 ? j = newSize - 1 : --j)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    96
                        ;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    97
                    newV[j] = table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    98
                }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    99
            free(table->v);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   100
            table->v = newV;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   101
            table->size = newSize;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   102
            table->usedLim = newSize/2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   103
            for (i = h & (table->size - 1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   104
                    table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   105
                    i == 0 ? i = table->size - 1 : --i)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   106
                ;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   107
        }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   108
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   109
    table->v[i] = calloc(1, createSize);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   110
    if (!table->v[i])
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   111
        return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   112
    table->v[i]->name = name;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   113
    (table->used)++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   114
    return table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   115
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   116
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   117
void hashTableDestroy(HASH_TABLE *table)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   118
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   119
    size_t i;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   120
    for (i = 0; i < table->size; i++) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   121
        NAMED *p = table->v[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   122
        if (p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   123
            free(p);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   124
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   125
    free(table->v);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   126
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   127
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   128
void hashTableInit(HASH_TABLE *p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   129
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   130
    p->size = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   131
    p->usedLim = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   132
    p->used = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   133
    p->v = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   134
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   135
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   136
void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   137
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   138
    iter->p = table->v;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   139
    iter->end = iter->p + table->size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   140
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   141
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   142
NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   143
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   144
    while (iter->p != iter->end) {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   145
        NAMED *tem = *(iter->p)++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   146
        if (tem)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   147
            return tem;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   148
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   149
    return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   150
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   151