/src/common/db.c

https://gitlab.com/wushin/evol-server-code-old · C · 627 lines · 571 code · 52 blank · 4 comment · 179 complexity · 9e883261631d8242dbdd373219350792 MD5 · raw file

  1. // $Id: db.c,v 1.2 2004/09/23 14:43:06 MouseJstr Exp $
  2. // #define MALLOC_DBN
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "db.h"
  7. #include "utils.h"
  8. #ifdef MEMWATCH
  9. #include "memwatch.h"
  10. #endif
  11. #define ROOT_SIZE 4096
  12. #ifdef MALLOC_DBN
  13. static struct dbn *dbn_root[512], *dbn_free;
  14. static int dbn_root_rest = 0, dbn_root_num = 0;
  15. static void *malloc_dbn (void)
  16. {
  17. struct dbn *ret;
  18. if (dbn_free == NULL)
  19. {
  20. if (dbn_root_rest <= 0)
  21. {
  22. CREATE (dbn_root[dbn_root_num], struct dbn, ROOT_SIZE);
  23. dbn_root_rest = ROOT_SIZE;
  24. dbn_root_num++;
  25. }
  26. return &(dbn_root[dbn_root_num - 1][--dbn_root_rest]);
  27. }
  28. ret = dbn_free;
  29. dbn_free = dbn_free->parent;
  30. return ret;
  31. }
  32. static void free_dbn (struct dbn *add_dbn)
  33. {
  34. if (!add_dbn)
  35. return;
  36. add_dbn->parent = dbn_free;
  37. dbn_free = add_dbn;
  38. }
  39. #endif
  40. static int strdb_cmp (struct dbt *table, void *a, void *b)
  41. {
  42. if (!table || !a || !b)
  43. return 0;
  44. if (table->maxlen)
  45. return strncmp (a, b, table->maxlen);
  46. return strcmp (a, b);
  47. }
  48. static unsigned int strdb_hash (struct dbt *table, void *a)
  49. {
  50. if (!table || !a)
  51. return 0;
  52. int i;
  53. unsigned int h;
  54. unsigned char *p = a;
  55. i = table->maxlen;
  56. if (i == 0)
  57. i = 0x7fffffff;
  58. for (h = 0; *p && --i >= 0;)
  59. {
  60. h = (h * 33 + *p++) ^ (h >> 24);
  61. }
  62. return h;
  63. }
  64. struct dbt *strdb_init (int maxlen)
  65. {
  66. int i;
  67. struct dbt *table;
  68. CREATE (table, struct dbt, 1);
  69. table->cmp = strdb_cmp;
  70. table->hash = strdb_hash;
  71. table->maxlen = maxlen;
  72. for (i = 0; i < HASH_SIZE; i++)
  73. table->ht[i] = NULL;
  74. return table;
  75. }
  76. static int numdb_cmp (struct dbt *table __attribute__ ((unused)),
  77. void *a, void *b)
  78. {
  79. int ia, ib;
  80. ia = (int) a;
  81. ib = (int) b;
  82. if ((ia ^ ib) & 0x80000000)
  83. return ia < 0 ? -1 : 1;
  84. return ia - ib;
  85. }
  86. static unsigned int numdb_hash (struct dbt *table __attribute__ ((unused)),
  87. void *a)
  88. {
  89. return (unsigned int) a;
  90. }
  91. struct dbt *numdb_init (void)
  92. {
  93. int i;
  94. struct dbt *table;
  95. CREATE (table, struct dbt, 1);
  96. table->cmp = numdb_cmp;
  97. table->hash = numdb_hash;
  98. table->maxlen = sizeof (int);
  99. for (i = 0; i < HASH_SIZE; i++)
  100. table->ht[i] = NULL;
  101. return table;
  102. }
  103. void *db_search (struct dbt *table, void *key)
  104. {
  105. if (!table || !key)
  106. return 0;
  107. struct dbn *p;
  108. for (p = table->ht[table->hash (table, key) % HASH_SIZE]; p;)
  109. {
  110. int c = table->cmp (table, key, p->key);
  111. if (c == 0)
  112. return p->data;
  113. if (c < 0)
  114. p = p->left;
  115. else
  116. p = p->right;
  117. }
  118. return NULL;
  119. }
  120. void *db_search2 (struct dbt *table, const char *key)
  121. {
  122. if (!table || !key)
  123. return 0;
  124. int i, sp;
  125. struct dbn *p, *pn, *stack[64];
  126. int slen = strlen (key);
  127. for (i = 0; i < HASH_SIZE; i++)
  128. {
  129. if ((p = table->ht[i]) == NULL)
  130. continue;
  131. sp = 0;
  132. while (1)
  133. {
  134. if (strncasecmp (key, p->key, slen) == 0)
  135. return p->data;
  136. if ((pn = p->left) != NULL)
  137. {
  138. if (p->right)
  139. {
  140. stack[sp++] = p->right;
  141. }
  142. p = pn;
  143. }
  144. else
  145. {
  146. if (p->right)
  147. {
  148. p = p->right;
  149. }
  150. else
  151. {
  152. if (sp == 0)
  153. break;
  154. p = stack[--sp];
  155. }
  156. }
  157. }
  158. }
  159. return 0;
  160. }
  161. static void db_rotate_left (struct dbn *p, struct dbn **root)
  162. {
  163. if (!p || !root)
  164. return;
  165. struct dbn *y = p->right;
  166. p->right = y->left;
  167. if (y->left != 0)
  168. y->left->parent = p;
  169. y->parent = p->parent;
  170. if (p == *root)
  171. *root = y;
  172. else if (p == p->parent->left)
  173. p->parent->left = y;
  174. else
  175. p->parent->right = y;
  176. y->left = p;
  177. p->parent = y;
  178. }
  179. static void db_rotate_right (struct dbn *p, struct dbn **root)
  180. {
  181. if (!p || !root)
  182. return;
  183. struct dbn *y = p->left;
  184. p->left = y->right;
  185. if (y->right != 0)
  186. y->right->parent = p;
  187. y->parent = p->parent;
  188. if (p == *root)
  189. *root = y;
  190. else if (p == p->parent->right)
  191. p->parent->right = y;
  192. else
  193. p->parent->left = y;
  194. y->right = p;
  195. p->parent = y;
  196. }
  197. static void db_rebalance (struct dbn *p, struct dbn **root)
  198. {
  199. if (!p || !root)
  200. return;
  201. p->color = RED;
  202. while (p != *root && p->parent->color == RED)
  203. { // rootは必ず黒で親は赤いので親の親は必ず存在する
  204. if (p->parent == p->parent->parent->left)
  205. {
  206. struct dbn *y = p->parent->parent->right;
  207. if (y && y->color == RED)
  208. {
  209. p->parent->color = BLACK;
  210. y->color = BLACK;
  211. p->parent->parent->color = RED;
  212. p = p->parent->parent;
  213. }
  214. else
  215. {
  216. if (p == p->parent->right)
  217. {
  218. p = p->parent;
  219. db_rotate_left (p, root);
  220. }
  221. p->parent->color = BLACK;
  222. p->parent->parent->color = RED;
  223. db_rotate_right (p->parent->parent, root);
  224. }
  225. }
  226. else
  227. {
  228. struct dbn *y = p->parent->parent->left;
  229. if (y && y->color == RED)
  230. {
  231. p->parent->color = BLACK;
  232. y->color = BLACK;
  233. p->parent->parent->color = RED;
  234. p = p->parent->parent;
  235. }
  236. else
  237. {
  238. if (p == p->parent->left)
  239. {
  240. p = p->parent;
  241. db_rotate_right (p, root);
  242. }
  243. p->parent->color = BLACK;
  244. p->parent->parent->color = RED;
  245. db_rotate_left (p->parent->parent, root);
  246. }
  247. }
  248. }
  249. (*root)->color = BLACK;
  250. }
  251. static void db_rebalance_erase (struct dbn *z, struct dbn **root)
  252. {
  253. if (!z || !root)
  254. return;
  255. struct dbn *y = z, *x = NULL, *x_parent = NULL;
  256. if (y->left == NULL)
  257. x = y->right;
  258. else if (y->right == NULL)
  259. x = y->left;
  260. else
  261. {
  262. y = y->right;
  263. while (y->left != NULL)
  264. y = y->left;
  265. x = y->right;
  266. }
  267. if (y != z)
  268. { // 左右が両方埋まっていた時 yをzの位置に持ってきてzを浮かせる
  269. z->left->parent = y;
  270. y->left = z->left;
  271. if (y != z->right)
  272. {
  273. x_parent = y->parent;
  274. if (x)
  275. x->parent = y->parent;
  276. y->parent->left = x;
  277. y->right = z->right;
  278. z->right->parent = y;
  279. }
  280. else
  281. x_parent = y;
  282. if (*root == z)
  283. *root = y;
  284. else if (z->parent->left == z)
  285. z->parent->left = y;
  286. else
  287. z->parent->right = y;
  288. y->parent = z->parent;
  289. {
  290. int tmp = y->color;
  291. y->color = z->color;
  292. z->color = tmp;
  293. }
  294. y = z;
  295. }
  296. else
  297. { // どちらか空いていた場合 xをzの位置に持ってきてzを浮かせる
  298. x_parent = y->parent;
  299. if (x)
  300. x->parent = y->parent;
  301. if (*root == z)
  302. *root = x;
  303. else if (z->parent->left == z)
  304. z->parent->left = x;
  305. else
  306. z->parent->right = x;
  307. }
  308. // ここまで色の移動の除いて通常の2分木と同じ
  309. if (y->color != RED)
  310. { // 赤が消える分には影響無し
  311. while (x != *root && (x == NULL || x->color == BLACK))
  312. if (x == x_parent->left)
  313. {
  314. struct dbn *w = x_parent->right;
  315. if (w->color == RED)
  316. {
  317. w->color = BLACK;
  318. x_parent->color = RED;
  319. db_rotate_left (x_parent, root);
  320. w = x_parent->right;
  321. }
  322. if ((w->left == NULL ||
  323. w->left->color == BLACK) &&
  324. (w->right == NULL || w->right->color == BLACK))
  325. {
  326. w->color = RED;
  327. x = x_parent;
  328. x_parent = x_parent->parent;
  329. }
  330. else
  331. {
  332. if (w->right == NULL || w->right->color == BLACK)
  333. {
  334. if (w->left)
  335. w->left->color = BLACK;
  336. w->color = RED;
  337. db_rotate_right (w, root);
  338. w = x_parent->right;
  339. }
  340. w->color = x_parent->color;
  341. x_parent->color = BLACK;
  342. if (w->right)
  343. w->right->color = BLACK;
  344. db_rotate_left (x_parent, root);
  345. break;
  346. }
  347. }
  348. else
  349. { // same as above, with right <-> left.
  350. struct dbn *w = x_parent->left;
  351. if (w->color == RED)
  352. {
  353. w->color = BLACK;
  354. x_parent->color = RED;
  355. db_rotate_right (x_parent, root);
  356. w = x_parent->left;
  357. }
  358. if ((w->right == NULL ||
  359. w->right->color == BLACK) &&
  360. (w->left == NULL || w->left->color == BLACK))
  361. {
  362. w->color = RED;
  363. x = x_parent;
  364. x_parent = x_parent->parent;
  365. }
  366. else
  367. {
  368. if (w->left == NULL || w->left->color == BLACK)
  369. {
  370. if (w->right)
  371. w->right->color = BLACK;
  372. w->color = RED;
  373. db_rotate_left (w, root);
  374. w = x_parent->left;
  375. }
  376. w->color = x_parent->color;
  377. x_parent->color = BLACK;
  378. if (w->left)
  379. w->left->color = BLACK;
  380. db_rotate_right (x_parent, root);
  381. break;
  382. }
  383. }
  384. if (x)
  385. x->color = BLACK;
  386. }
  387. }
  388. struct dbn *db_insert (struct dbt *table, void *key, void *data)
  389. {
  390. struct dbn *p, *priv;
  391. int c, hash;
  392. if (!table)
  393. return 0;
  394. hash = table->hash (table, key) % HASH_SIZE;
  395. for (c = 0, priv = NULL, p = table->ht[hash]; p;)
  396. {
  397. c = table->cmp (table, key, p->key);
  398. if (c == 0)
  399. { // replace
  400. if (table->release)
  401. table->release (p, 3);
  402. p->data = data;
  403. p->key = key;
  404. return p;
  405. }
  406. priv = p;
  407. if (c < 0)
  408. {
  409. p = p->left;
  410. }
  411. else
  412. {
  413. p = p->right;
  414. }
  415. }
  416. #ifdef MALLOC_DBN
  417. p = malloc_dbn ();
  418. #else
  419. CREATE (p, struct dbn, 1);
  420. #endif
  421. if (p == NULL)
  422. {
  423. printf ("out of memory : db_insert\n");
  424. return NULL;
  425. }
  426. p->parent = NULL;
  427. p->left = NULL;
  428. p->right = NULL;
  429. p->key = key;
  430. p->data = data;
  431. p->color = RED;
  432. if (c == 0)
  433. { // hash entry is empty
  434. table->ht[hash] = p;
  435. p->color = BLACK;
  436. }
  437. else
  438. {
  439. if (c < 0)
  440. { // left node
  441. priv->left = p;
  442. p->parent = priv;
  443. }
  444. else
  445. { // right node
  446. priv->right = p;
  447. p->parent = priv;
  448. }
  449. if (priv->color == RED)
  450. { // must rebalance
  451. db_rebalance (p, &table->ht[hash]);
  452. }
  453. }
  454. return p;
  455. }
  456. void *db_erase (struct dbt *table, void *key)
  457. {
  458. if (!table)
  459. return 0;
  460. void *data;
  461. struct dbn *p;
  462. int c, hash;
  463. hash = table->hash (table, key) % HASH_SIZE;
  464. for (c = 0, p = table->ht[hash]; p;)
  465. {
  466. c = table->cmp (table, key, p->key);
  467. if (c == 0)
  468. break;
  469. if (c < 0)
  470. p = p->left;
  471. else
  472. p = p->right;
  473. }
  474. if (!p)
  475. return NULL;
  476. data = p->data;
  477. db_rebalance_erase (p, &table->ht[hash]);
  478. #ifdef MALLOC_DBN
  479. free_dbn (p);
  480. #else
  481. free (p);
  482. #endif
  483. return data;
  484. }
  485. void db_foreach (struct dbt *table, int (*func) (void *, void *, va_list),
  486. ...)
  487. {
  488. if (!table)
  489. return;
  490. int i, sp;
  491. // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫
  492. struct dbn *p, *pn, *stack[64];
  493. va_list ap;
  494. va_start (ap, func);
  495. for (i = 0; i < HASH_SIZE; i++)
  496. {
  497. if ((p = table->ht[i]) == NULL)
  498. continue;
  499. sp = 0;
  500. while (1)
  501. {
  502. func (p->key, p->data, ap);
  503. if ((pn = p->left) != NULL)
  504. {
  505. if (p->right)
  506. {
  507. stack[sp++] = p->right;
  508. }
  509. p = pn;
  510. }
  511. else
  512. {
  513. if (p->right)
  514. {
  515. p = p->right;
  516. }
  517. else
  518. {
  519. if (sp == 0)
  520. break;
  521. p = stack[--sp];
  522. }
  523. }
  524. }
  525. }
  526. va_end (ap);
  527. }
  528. void db_final (struct dbt *table, int (*func) (void *, void *, va_list), ...)
  529. {
  530. if (!table)
  531. return;
  532. int i, sp;
  533. struct dbn *p, *pn, *stack[64];
  534. va_list ap;
  535. va_start (ap, func);
  536. for (i = 0; i < HASH_SIZE; i++)
  537. {
  538. if ((p = table->ht[i]) == NULL)
  539. continue;
  540. sp = 0;
  541. while (1)
  542. {
  543. if (func)
  544. func (p->key, p->data, ap);
  545. if ((pn = p->left) != NULL)
  546. {
  547. if (p->right)
  548. {
  549. stack[sp++] = p->right;
  550. }
  551. }
  552. else
  553. {
  554. if (p->right)
  555. {
  556. pn = p->right;
  557. }
  558. else
  559. {
  560. if (sp == 0)
  561. break;
  562. pn = stack[--sp];
  563. }
  564. }
  565. #ifdef MALLOC_DBN
  566. free_dbn (p);
  567. #else
  568. free (p);
  569. #endif
  570. p = pn;
  571. }
  572. }
  573. free (table);
  574. va_end (ap);
  575. }