1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Stupid implementation of pointer -> pointer map.
   4  *
   5  * Copyright (c) 2017 Luc Van Oostenryck.
   6  *
   7  * Permission is hereby granted, free of charge, to any person obtaining a copy
   8  * of this software and associated documentation files (the "Software"), to deal
   9  * in the Software without restriction, including without limitation the rights
  10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11  * copies of the Software, and to permit persons to whom the Software is
  12  * furnished to do so, subject to the following conditions:
  13  *
  14  * The above copyright notice and this permission notice shall be included in
  15  * all copies or substantial portions of the Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23  * THE SOFTWARE.
  24  */
  25 
  26 #include "ptrmap.h"
  27 #include "allocate.h"
  28 #include <stddef.h>
  29 
  30 #define MAP_NR  7
  31 
  32 struct ptrpair {
  33         void *key;
  34         void *val;
  35 };
  36 struct ptrmap {
  37         struct ptrmap *next;
  38         int nr;
  39         struct ptrpair pairs[MAP_NR];
  40 };
  41 
  42 DECLARE_ALLOCATOR(ptrmap);
  43 ALLOCATOR(ptrmap, "ptrmap");
  44 
  45 void __ptrmap_add(struct ptrmap **mapp, void *key, void *val)
  46 {
  47         struct ptrmap *head = *mapp;
  48         struct ptrmap *newmap;
  49         struct ptrmap *map;
  50         struct ptrpair *pair;
  51         int nr;
  52 
  53         if ((map = head)) {
  54                 struct ptrmap *next = map->next;
  55                 if (next)               // head is full
  56                         map = next;
  57                 if ((nr = map->nr) < MAP_NR)
  58                         goto oldmap;
  59         }
  60 
  61         // need a new block
  62         newmap = __alloc_ptrmap(0);
  63         if (!head) {
  64                 *mapp = newmap;
  65         } else {
  66                 newmap->next = head->next;
  67                 head->next = newmap;
  68         }
  69         map = newmap;
  70         nr = 0;
  71 
  72 oldmap:
  73         pair = &map->pairs[nr];
  74         pair->key = key;
  75         pair->val = val;
  76         map->nr = ++nr;
  77 }
  78 
  79 void *__ptrmap_lookup(struct ptrmap *map, void *key)
  80 {
  81         for (; map; map = map->next) {
  82                 int i, n = map->nr;
  83                 for (i = 0; i < n; i++) {
  84                         struct ptrpair *pair = &map->pairs[i];
  85                         if (pair->key == key)
  86                                 return pair->val;
  87                 }
  88         }
  89         return NULL;
  90 }
  91 
  92 void __ptrmap_update(struct ptrmap **mapp, void *key, void *val)
  93 {
  94         struct ptrmap *map = *mapp;
  95 
  96         for (; map; map = map->next) {
  97                 int i, n = map->nr;
  98                 for (i = 0; i < n; i++) {
  99                         struct ptrpair *pair = &map->pairs[i];
 100                         if (pair->key == key) {
 101                                 if (pair->val != val)
 102                                         pair->val = val;
 103                                 return;
 104                         }
 105                 }
 106         }
 107 
 108         __ptrmap_add(mapp, key, val);
 109 }