LCOV - code coverage report
Current view: top level - src - napr_heap.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.0 % 81 64
Test Date: 2025-10-15 21:43:52 Functions: 85.7 % 7 6

            Line data    Source code
       1              : /**
       2              :  * @file napr_heap.c
       3              :  * @brief Implementation of the generic binary heap.
       4              :  * @ingroup DataStructures
       5              :  */
       6              : /*
       7              :  * Copyright (C) 2007 François Pesce : francois.pesce (at) gmail (dot) com
       8              :  *
       9              :  * Licensed under the Apache License, Version 2.0 (the "License");
      10              :  * you may not use this file except in compliance with the License.
      11              :  * You may obtain a copy of the License at
      12              :  *
      13              :  *      http://www.apache.org/licenses/LICENSE-2.0
      14              :  *
      15              :  * Unless required by applicable law or agreed to in writing, software
      16              :  * distributed under the License is distributed on an "AS IS" BASIS,
      17              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      18              :  * See the License for the specific language governing permissions and
      19              :  * limitations under the License.
      20              :  */
      21              : 
      22              : #include <apr_thread_mutex.h>
      23              : #include <string.h>
      24              : 
      25              : #include "debug.h"
      26              : #include "napr_heap.h"
      27              : 
      28              : #define INITIAL_MAX 256
      29              : #define NAPR_HEAP_PARENT(position) (((position) - 1) >> 1)
      30              : #define NAPR_HEAP_LEFT(position)   (((position) << 1) + 1)
      31              : #define NAPR_HEAP_RIGHT(position)  (((position) + 1) << 1)
      32              : 
      33              : struct napr_heap_t
      34              : {
      35              :     apr_pool_t *pool;
      36              :     apr_thread_mutex_t *mutex;
      37              :     void **tree;
      38              :     napr_heap_cmp_callback_fn_t *cmp;
      39              :     unsigned int count, max;
      40              :     int mutex_set;              /* true (i.e. 1) if napr_heap_make_r has been
      41              :                                    called instead of non-reentrant function */
      42              : };
      43              : 
      44              : #ifdef HAVE_APR
      45              : /* APR_POOL_IMPLEMENT_ACCESSOR(heap); */
      46              : #endif
      47              : 
      48           35 : napr_heap_t *napr_heap_make(apr_pool_t *pool, napr_heap_cmp_callback_fn_t *cmp)
      49              : {
      50           35 :     napr_heap_t *heap = NULL;
      51              :     apr_pool_t *local_pool;
      52              : 
      53           35 :     if (APR_SUCCESS == (apr_pool_create(&local_pool, pool))) {
      54           35 :         heap = apr_palloc(local_pool, sizeof(napr_heap_t));
      55           35 :         heap->pool = local_pool;
      56           35 :         heap->tree = (void **) apr_pcalloc(local_pool, sizeof(void *) * INITIAL_MAX);
      57              :     }
      58              : 
      59           35 :     if (NULL != heap) {
      60           35 :         heap->max = INITIAL_MAX;
      61           35 :         heap->count = 0;
      62           35 :         heap->cmp = cmp;
      63           35 :         heap->mutex_set = 0;
      64           35 :         heap->mutex = NULL;
      65              :     }
      66              : 
      67           35 :     return heap;
      68              : }
      69              : 
      70          221 : int napr_heap_insert(napr_heap_t *heap, void *datum)
      71              : {
      72              :     void **tmp;
      73              :     unsigned int ipos, ppos;
      74              : 
      75          221 :     if (heap->max <= heap->count) {
      76              :         /*
      77              :          * reallocation by power of 2:
      78              :          */
      79              :         unsigned int new_max;
      80              : 
      81            0 :         for (new_max = 1; new_max <= heap->max; new_max *= 2);
      82              : 
      83            0 :         tmp = apr_palloc(heap->pool, new_max * sizeof(void *));
      84            0 :         if (NULL != tmp) {
      85            0 :             memcpy(tmp, (heap->tree), (heap->count) * sizeof(void *));
      86            0 :             memset((tmp + (heap->count)), 0, (new_max - (heap->count + 1)) * sizeof(void *));
      87            0 :             heap->tree = tmp;
      88            0 :             heap->max = new_max;
      89              :         }
      90              :         else {
      91            0 :             heap->tree = NULL;
      92            0 :             DEBUG_ERR("allocation failed");
      93            0 :             return -1;
      94              :         }
      95              :     }
      96              : 
      97              :     /*
      98              :      * insertion of the datum after the last one of the tree...
      99              :      */
     100          221 :     heap->tree[heap->count] = datum;
     101              : 
     102          221 :     ipos = heap->count;
     103          221 :     ppos = NAPR_HEAP_PARENT(ipos);
     104              : 
     105          356 :     while (ipos > 0 && (heap->cmp(heap->tree[ppos], heap->tree[ipos]) < 0)) {
     106              :         /*
     107              :          * Swap the value ...
     108              :          */
     109          135 :         tmp = heap->tree[ppos];
     110          135 :         heap->tree[ppos] = heap->tree[ipos];
     111          135 :         heap->tree[ipos] = tmp;
     112              : 
     113          135 :         ipos = ppos;
     114          135 :         ppos = NAPR_HEAP_PARENT(ipos);
     115              :     }
     116              : 
     117          221 :     heap->count++;
     118              : 
     119          221 :     return 0;
     120              : }
     121              : 
     122          256 : void *napr_heap_extract(napr_heap_t *heap)
     123              : {
     124          256 :     void *ret = NULL, *tmp;
     125              :     unsigned int ipos, rpos, lpos, mpos;
     126              : 
     127          256 :     if ((0 != heap->count) && (NULL != heap->tree)) {
     128              :         /* keep the value to return */
     129          221 :         ret = heap->tree[0];
     130              :         /* It works for count == 1 too (just think about it) */
     131          221 :         heap->tree[0] = heap->tree[heap->count - 1];
     132          221 :         heap->tree[heap->count - 1] = NULL;
     133          221 :         heap->count--;
     134          221 :         ipos = 0;
     135              : 
     136              :         while (1) {
     137          620 :             lpos = NAPR_HEAP_LEFT(ipos);
     138          620 :             rpos = NAPR_HEAP_RIGHT(ipos);
     139              : 
     140          620 :             if (lpos < heap->count) {
     141          462 :                 if (heap->cmp(heap->tree[lpos], heap->tree[ipos]) > 0) {
     142          368 :                     mpos = lpos;
     143              :                 }
     144              :                 else {
     145           94 :                     mpos = ipos;
     146              :                 }
     147          462 :                 if ((rpos < heap->count) && (heap->cmp(heap->tree[rpos], heap->tree[mpos])) > 0) {
     148          182 :                     mpos = rpos;
     149              :                 }
     150              :             }
     151              :             else {
     152          158 :                 mpos = ipos;
     153              :             }
     154              : 
     155          620 :             if (mpos != ipos) {
     156              :                 /*
     157              :                  * Swap the choosen children with the current node
     158              :                  */
     159          399 :                 tmp = heap->tree[mpos];
     160          399 :                 heap->tree[mpos] = heap->tree[ipos];
     161          399 :                 heap->tree[ipos] = tmp;
     162          399 :                 ipos = mpos;
     163              :             }
     164              :             else {
     165          221 :                 break;
     166              :             }
     167              :         }
     168              :     }
     169              : 
     170          256 :     return ret;
     171              : }
     172              : 
     173            0 : void *napr_heap_get_nth(const napr_heap_t *heap, unsigned int n)
     174              : {
     175            0 :     if ((n < heap->count) && (NULL != heap->tree))
     176            0 :         return heap->tree[n];
     177              :     else
     178            0 :         return NULL;
     179              : }
     180              : 
     181           17 : unsigned int napr_heap_size(const napr_heap_t *heap)
     182              : {
     183           17 :     return heap->count;
     184              : }
     185              : 
     186              : /*
     187              :  * Reentrant versions of previous functions.
     188              :  */
     189            1 : napr_heap_t *napr_heap_make_r(apr_pool_t *pool, napr_heap_cmp_callback_fn_t *cmp)
     190              : {
     191              :     napr_heap_t *heap;
     192              : 
     193            1 :     if (NULL != (heap = napr_heap_make(pool, cmp))) {
     194            1 :         if (APR_SUCCESS != apr_thread_mutex_create(&(heap->mutex), APR_THREAD_MUTEX_DEFAULT, pool))
     195            0 :             heap = NULL;
     196              :     }
     197              : 
     198            1 :     if (NULL != heap)
     199            1 :         heap->mutex_set = 1;
     200              : 
     201            1 :     return heap;
     202              : }
     203              : 
     204            5 : int napr_heap_insert_r(napr_heap_t *heap, void *datum)
     205              : {
     206              :     int rc;
     207              : 
     208            5 :     if (1 == heap->mutex_set) {
     209            5 :         if (APR_SUCCESS == (rc = apr_thread_mutex_lock(heap->mutex))) {
     210            5 :             if (0 == (rc = napr_heap_insert(heap, datum)))
     211            5 :                 rc = apr_thread_mutex_unlock(heap->mutex);
     212              :         }
     213              :         else {
     214            0 :             DEBUG_ERR("locking failed");
     215              :         }
     216              :     }
     217              :     else
     218            0 :         rc = -1;
     219              : 
     220            5 :     return rc;
     221              : }
        

Generated by: LCOV version 2.0-1