Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/lib/splay.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*************************************************************************** | |
| 2 * _ _ ____ _ | |
| 3 * Project ___| | | | _ \| | | |
| 4 * / __| | | | |_) | | | |
| 5 * | (__| |_| | _ <| |___ | |
| 6 * \___|\___/|_| \_\_____| | |
| 7 * | |
| 8 * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | |
| 9 * | |
| 10 * This software is licensed as described in the file COPYING, which | |
| 11 * you should have received as part of this distribution. The terms | |
| 12 * are also available at https://curl.haxx.se/docs/copyright.html. | |
| 13 * | |
| 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell | |
| 15 * copies of the Software, and permit persons to whom the Software is | |
| 16 * furnished to do so, under the terms of the COPYING file. | |
| 17 * | |
| 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | |
| 19 * KIND, either express or implied. | |
| 20 * | |
| 21 ***************************************************************************/ | |
| 22 | |
| 23 #include "curl_setup.h" | |
| 24 | |
| 25 #include "splay.h" | |
| 26 | |
| 27 /* | |
| 28 * This macro compares two node keys i and j and returns: | |
| 29 * | |
| 30 * negative value: when i is smaller than j | |
| 31 * zero : when i is equal to j | |
| 32 * positive when : when i is larger than j | |
| 33 */ | |
| 34 #define compare(i,j) Curl_splaycomparekeys((i),(j)) | |
| 35 | |
| 36 /* | |
| 37 * Splay using the key i (which may or may not be in the tree.) The starting | |
| 38 * root is t. | |
| 39 */ | |
| 40 struct Curl_tree *Curl_splay(struct curltime i, | |
| 41 struct Curl_tree *t) | |
| 42 { | |
| 43 struct Curl_tree N, *l, *r, *y; | |
| 44 | |
| 45 if(t == NULL) | |
| 46 return t; | |
| 47 N.smaller = N.larger = NULL; | |
| 48 l = r = &N; | |
| 49 | |
| 50 for(;;) { | |
| 51 long comp = compare(i, t->key); | |
| 52 if(comp < 0) { | |
| 53 if(t->smaller == NULL) | |
| 54 break; | |
| 55 if(compare(i, t->smaller->key) < 0) { | |
| 56 y = t->smaller; /* rotate smaller */ | |
| 57 t->smaller = y->larger; | |
| 58 y->larger = t; | |
| 59 t = y; | |
| 60 if(t->smaller == NULL) | |
| 61 break; | |
| 62 } | |
| 63 r->smaller = t; /* link smaller */ | |
| 64 r = t; | |
| 65 t = t->smaller; | |
| 66 } | |
| 67 else if(comp > 0) { | |
| 68 if(t->larger == NULL) | |
| 69 break; | |
| 70 if(compare(i, t->larger->key) > 0) { | |
| 71 y = t->larger; /* rotate larger */ | |
| 72 t->larger = y->smaller; | |
| 73 y->smaller = t; | |
| 74 t = y; | |
| 75 if(t->larger == NULL) | |
| 76 break; | |
| 77 } | |
| 78 l->larger = t; /* link larger */ | |
| 79 l = t; | |
| 80 t = t->larger; | |
| 81 } | |
| 82 else | |
| 83 break; | |
| 84 } | |
| 85 | |
| 86 l->larger = t->smaller; /* assemble */ | |
| 87 r->smaller = t->larger; | |
| 88 t->smaller = N.larger; | |
| 89 t->larger = N.smaller; | |
| 90 | |
| 91 return t; | |
| 92 } | |
| 93 | |
| 94 /* Insert key i into the tree t. Return a pointer to the resulting tree or | |
| 95 * NULL if something went wrong. | |
| 96 * | |
| 97 * @unittest: 1309 | |
| 98 */ | |
| 99 struct Curl_tree *Curl_splayinsert(struct curltime i, | |
| 100 struct Curl_tree *t, | |
| 101 struct Curl_tree *node) | |
| 102 { | |
| 103 static const struct curltime KEY_NOTUSED = { | |
| 104 (time_t)-1, (unsigned int)-1 | |
| 105 }; /* will *NEVER* appear */ | |
| 106 | |
| 107 if(node == NULL) | |
| 108 return t; | |
| 109 | |
| 110 if(t != NULL) { | |
| 111 t = Curl_splay(i, t); | |
| 112 if(compare(i, t->key) == 0) { | |
| 113 /* There already exists a node in the tree with the very same key. Build | |
| 114 a doubly-linked circular list of nodes. We add the new 'node' struct | |
| 115 to the end of this list. */ | |
| 116 | |
| 117 node->key = KEY_NOTUSED; /* we set the key in the sub node to NOTUSED | |
| 118 to quickly identify this node as a subnode */ | |
| 119 node->samen = t; | |
| 120 node->samep = t->samep; | |
| 121 t->samep->samen = node; | |
| 122 t->samep = node; | |
| 123 | |
| 124 return t; /* the root node always stays the same */ | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 if(t == NULL) { | |
| 129 node->smaller = node->larger = NULL; | |
| 130 } | |
| 131 else if(compare(i, t->key) < 0) { | |
| 132 node->smaller = t->smaller; | |
| 133 node->larger = t; | |
| 134 t->smaller = NULL; | |
| 135 | |
| 136 } | |
| 137 else { | |
| 138 node->larger = t->larger; | |
| 139 node->smaller = t; | |
| 140 t->larger = NULL; | |
| 141 } | |
| 142 node->key = i; | |
| 143 | |
| 144 /* no identical nodes (yet), we are the only one in the list of nodes */ | |
| 145 node->samen = node; | |
| 146 node->samep = node; | |
| 147 return node; | |
| 148 } | |
| 149 | |
| 150 /* Finds and deletes the best-fit node from the tree. Return a pointer to the | |
| 151 resulting tree. best-fit means the smallest node if it is not larger than | |
| 152 the key */ | |
| 153 struct Curl_tree *Curl_splaygetbest(struct curltime i, | |
| 154 struct Curl_tree *t, | |
| 155 struct Curl_tree **removed) | |
| 156 { | |
| 157 static struct curltime tv_zero = {0, 0}; | |
| 158 struct Curl_tree *x; | |
| 159 | |
| 160 if(!t) { | |
| 161 *removed = NULL; /* none removed since there was no root */ | |
| 162 return NULL; | |
| 163 } | |
| 164 | |
| 165 /* find smallest */ | |
| 166 t = Curl_splay(tv_zero, t); | |
| 167 if(compare(i, t->key) < 0) { | |
| 168 /* even the smallest is too big */ | |
| 169 *removed = NULL; | |
| 170 return t; | |
| 171 } | |
| 172 | |
| 173 /* FIRST! Check if there is a list with identical keys */ | |
| 174 x = t->samen; | |
| 175 if(x != t) { | |
| 176 /* there is, pick one from the list */ | |
| 177 | |
| 178 /* 'x' is the new root node */ | |
| 179 | |
| 180 x->key = t->key; | |
| 181 x->larger = t->larger; | |
| 182 x->smaller = t->smaller; | |
| 183 x->samep = t->samep; | |
| 184 t->samep->samen = x; | |
| 185 | |
| 186 *removed = t; | |
| 187 return x; /* new root */ | |
| 188 } | |
| 189 | |
| 190 /* we splayed the tree to the smallest element, there is no smaller */ | |
| 191 x = t->larger; | |
| 192 *removed = t; | |
| 193 | |
| 194 return x; | |
| 195 } | |
| 196 | |
| 197 | |
| 198 /* Deletes the very node we point out from the tree if it's there. Stores a | |
| 199 * pointer to the new resulting tree in 'newroot'. | |
| 200 * | |
| 201 * Returns zero on success and non-zero on errors! | |
| 202 * When returning error, it does not touch the 'newroot' pointer. | |
| 203 * | |
| 204 * NOTE: when the last node of the tree is removed, there's no tree left so | |
| 205 * 'newroot' will be made to point to NULL. | |
| 206 * | |
| 207 * @unittest: 1309 | |
| 208 */ | |
| 209 int Curl_splayremovebyaddr(struct Curl_tree *t, | |
| 210 struct Curl_tree *removenode, | |
| 211 struct Curl_tree **newroot) | |
| 212 { | |
| 213 static const struct curltime KEY_NOTUSED = { | |
| 214 (time_t)-1, (unsigned int)-1 | |
| 215 }; /* will *NEVER* appear */ | |
| 216 struct Curl_tree *x; | |
| 217 | |
| 218 if(!t || !removenode) | |
| 219 return 1; | |
| 220 | |
| 221 if(compare(KEY_NOTUSED, removenode->key) == 0) { | |
| 222 /* Key set to NOTUSED means it is a subnode within a 'same' linked list | |
| 223 and thus we can unlink it easily. */ | |
| 224 if(removenode->samen == removenode) | |
| 225 /* A non-subnode should never be set to KEY_NOTUSED */ | |
| 226 return 3; | |
| 227 | |
| 228 removenode->samep->samen = removenode->samen; | |
| 229 removenode->samen->samep = removenode->samep; | |
| 230 | |
| 231 /* Ensures that double-remove gets caught. */ | |
| 232 removenode->samen = removenode; | |
| 233 | |
| 234 *newroot = t; /* return the same root */ | |
| 235 return 0; | |
| 236 } | |
| 237 | |
| 238 t = Curl_splay(removenode->key, t); | |
| 239 | |
| 240 /* First make sure that we got the same root node as the one we want | |
| 241 to remove, as otherwise we might be trying to remove a node that | |
| 242 isn't actually in the tree. | |
| 243 | |
| 244 We cannot just compare the keys here as a double remove in quick | |
| 245 succession of a node with key != KEY_NOTUSED && same != NULL | |
| 246 could return the same key but a different node. */ | |
| 247 if(t != removenode) | |
| 248 return 2; | |
| 249 | |
| 250 /* Check if there is a list with identical sizes, as then we're trying to | |
| 251 remove the root node of a list of nodes with identical keys. */ | |
| 252 x = t->samen; | |
| 253 if(x != t) { | |
| 254 /* 'x' is the new root node, we just make it use the root node's | |
| 255 smaller/larger links */ | |
| 256 | |
| 257 x->key = t->key; | |
| 258 x->larger = t->larger; | |
| 259 x->smaller = t->smaller; | |
| 260 x->samep = t->samep; | |
| 261 t->samep->samen = x; | |
| 262 } | |
| 263 else { | |
| 264 /* Remove the root node */ | |
| 265 if(t->smaller == NULL) | |
| 266 x = t->larger; | |
| 267 else { | |
| 268 x = Curl_splay(removenode->key, t->smaller); | |
| 269 x->larger = t->larger; | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 *newroot = x; /* store new root pointer */ | |
| 274 | |
| 275 return 0; | |
| 276 } |
