aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/tsearch.c
blob: af373fc334c15fcccefbe5ea7cab0ab147ad4fda (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 * the AT&T man page says.
 *
 * The node_t structure is for internal use only, lint doesn't grok it.
 *
 * Written by reading the System V Interface Definition, not the code.
 *
 * Totally public domain.
 */

#include "mhd_options.h"
#include "tsearch.h"
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif /* HAVE_STDDEF_H */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */


typedef struct node
{
  const void *key;
  struct node  *llink, *rlink;
} node_t;


/*  $NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $  */
/* find or insert datum into search tree */
void *
tsearch (const void *vkey, void **vrootp,
         int (*compar)(const void *, const void *))
{
  node_t *q;
  node_t **rootp = (node_t **) vrootp;

  if (rootp == NULL)
    return NULL;

  while (*rootp != NULL)        /* Knuth's T1: */
  {
    int r;

    if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
      return *rootp;                               /* we found it! */

    rootp = (r < 0) ?
            &(*rootp)->llink :      /* T3: follow left branch */
            &(*rootp)->rlink;       /* T4: follow right branch */
  }

  q = malloc (sizeof(node_t)); /* T5: key not found */
  if (q != NULL)               /* make new node */
  {
    *rootp = q;                /* link new node to old */
    q->key = vkey; /* initialize new node */
    q->llink = q->rlink = NULL;
  }
  return q;
}


/*  $NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $    */
/* find a node by key "vkey" in tree "vrootp", or return 0 */
void *
tfind (const void *vkey, void * const *vrootp,
       int (*compar)(const void *, const void *))
{
  node_t * const *rootp = (node_t * const *) vrootp;

  if (rootp == NULL)
    return NULL;

  while (*rootp != NULL)            /* T1: */
  {
    int r;

    if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
      return *rootp;                               /* key found */
    rootp = (r < 0) ?
            &(*rootp)->llink :                     /* T3: follow left branch */
            &(*rootp)->rlink;                      /* T4: follow right branch */
  }
  return NULL;
}


/*  $NetBSD: tdelete.c,v 1.8 2016/01/20 20:47:41 christos Exp $ */
/* find a node with key "vkey" in tree "vrootp" */
void *
tdelete (const void *vkey, void **vrootp,
         int (*compar)(const void *, const void *))
{
  node_t **rootp = (node_t **) vrootp;
  node_t *p, *q, *r;
  int cmp;

  if ((rootp == NULL) || ((p = *rootp) == NULL) )
    return NULL;

  while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0)
  {
    p = *rootp;
    rootp = (cmp < 0) ?
            &(*rootp)->llink :       /* follow llink branch */
            &(*rootp)->rlink;        /* follow rlink branch */
    if (*rootp == NULL)
      return NULL;                   /* key not found */
  }
  r = (*rootp)->rlink;               /* D1: */
  if ((q = (*rootp)->llink) == NULL) /* Left NULL? */
    q = r;
  else if (r != NULL)                /* Right link is NULL? */
  {
    if (r->llink == NULL)            /* D2: Find successor */
    {
      r->llink = q;
      q = r;
    }
    else                    /* D3: Find NULL link */
    {
      for (q = r->llink; q->llink != NULL; q = r->llink)
        r = q;
      r->llink = q->rlink;
      q->llink = (*rootp)->llink;
      q->rlink = (*rootp)->rlink;
    }
  }
  free (*rootp);            /* D4: Free node */
  *rootp = q;               /* link parent to new node */
  return p;
}


/* end of tsearch.c */