LCOV - code coverage report
Current view: top level - src - intern.c (source / functions) Hit Total Coverage
Test: cov_nosys.info Lines: 29 29 100.0 %
Date: 2024-06-16 08:54:54 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  intern.c
       3             :  *  Patater GUI Kit
       4             :  *
       5             :  *  Created by Jaeden Amero on 2019-05-06.
       6             :  *  Copyright 2019. SPDX-License-Identifier: AGPL-3.0-or-later
       7             :  */
       8             : 
       9             : #include "guikit/intern.h"
      10             : #include "guikit/array.h"
      11             : #include "guikit/hash.h"
      12             : #include "guikit/hashmap.h"
      13             : #include "guikit/pmemory.h"
      14             : #include "guikit/ptypes.h"
      15             : #include <stddef.h>
      16             : #include <string.h>
      17             : 
      18             : static struct hashmap *intern_map = NULL;
      19             : static int num_hits = 0;
      20             : static char **intern_array;
      21             : 
      22           5 : void intern_free(void)
      23             : {
      24             :     size_t len;
      25             :     size_t i;
      26             : 
      27           5 :     hashmap_free(intern_map);
      28           5 :     intern_map = NULL;
      29             : 
      30           5 :     len = array_len(intern_array);
      31          11 :     for (i = 0; i < len; i++)
      32             :     {
      33           6 :         pfree(intern_array[i]);
      34             :     }
      35           5 :     array_free(intern_array);
      36             : 
      37           5 :     num_hits = 0;
      38           5 : }
      39             : 
      40           8 : const char *intern(const char *s)
      41             : {
      42             :     size_t len;
      43             :     const char *interned;
      44             :     char *copy;
      45           8 :     u32 key[2];
      46             : 
      47             :     /* Lazy load the intern map */
      48           8 :     if (!intern_map)
      49             :     {
      50           5 :         intern_map = hashmap_alloc();
      51             :     }
      52             : 
      53           8 :     len = strlen(s);
      54           8 :     hash64(key, s, len);
      55           8 :     interned = (const char *)hashmap_get(intern_map, key);
      56           8 :     if (interned != 0)
      57             :     {
      58             :         /* Found previous copy */
      59           2 :         num_hits += 1;
      60           2 :         return interned;
      61             :     }
      62             : 
      63             :     /* Didn't find previous copy, so add it to the intern map. */
      64             :     /* Note that we own the memory for the string we are interning. We do this
      65             :      * so that one can intern strings they've made up on the fly (temporary
      66             :      * strings) without the intern storage disappearing out from under us.
      67             :      *
      68             :      * We track pointers to allocated memory in the intern array. This allows
      69             :      * us to free all the memory we've allocated without using the hash map.
      70             :      *
      71             :      * We don't provide a way to avoid string copying at the moment, although
      72             :      * this would be straightforward to implement given we are tracking
      73             :      * allocated memory. If we did not have a separate intern_array, we would
      74             :      * find it very hard to track such things as the pointers in the hash map's
      75             :      * values array may or may not be strings we've allocated. TODO add a
      76             :      * function to not copy-intern to enable callers to make more efficient use
      77             :      * of string storage. */
      78           6 :     copy = pmalloc(len + 1);
      79           6 :     strcpy(copy, s);
      80           6 :     array_push(intern_array, copy); /* Track allocated memory */
      81           6 :     hashmap_put(intern_map, key, (ptrdiff_t)copy);
      82           6 :     interned = copy;
      83             : 
      84           6 :     return interned;
      85             : }
      86             : 
      87           4 : int intern_num_hits(void)
      88             : {
      89           4 :     return num_hits;
      90             : }
      91             : 
      92           4 : int intern_num_interned(void)
      93             : {
      94           4 :     return array_len(intern_array);
      95             : }

Generated by: LCOV version 1.14