1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/*
* Copyright 2013 University Corporation for Atmospheric Research
*
* This file is part of the UDUNITS-2 package. See the file COPYRIGHT
* in the top-level source-directory of the package for copying and
* redistribution conditions.
*/
/*
* Module for system-to-pointer maps.
*
* This module is thread-compatible but not thread-safe.
*/
/*LINTLIBRARY*/
#ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500
#endif
#ifdef _MSC_VER
#include "tsearch.h"
#else
#include <search.h>
#endif
#include <stdlib.h>
#include "systemMap.h"
#include "udunits2.h"
struct SystemMap {
void* tree;
};
typedef struct {
const ut_system* system;
void* ptr;
} Entry;
/*
* Compares two entries according to their unit-system pointers.
*
* Arguments:
* entry1 Pointer to the first entry.
* entry2 Pointer to the second entry.
* Returns:
* -1 The first entry's key is less than the second's.
* 0 The first entry's key is equal to the second's.
* 1 The first entry's key is greater than the second's.
*/
static int
compareEntries(
const void* entry1,
const void* entry2)
{
const ut_system* const system1 = ((Entry*)entry1)->system;
const ut_system* const system2 = ((Entry*)entry2)->system;
return system1 < system2 ? -1 : system1 == system2 ? 0 : 1;
}
/*
* Returns a new instance of a system-map.
*
* Arguments:
* compare Function for comparing keys.
* Returns:
* NULL Operating-system failure. See "errno".
* else Pointer to the new map.
*/
SystemMap*
smNew()
{
SystemMap* map = (SystemMap*)malloc(sizeof(SystemMap));
if (map != NULL)
map->tree = NULL;
return map;
}
/*
* Returns the address of the pointer to which a unit-system maps.
*
* Arguments:
* map Pointer to the system-map.
* system Pointer to the unit-system.
* Returns:
* NULL There is no pointer associated with "system".
* else Address of the pointer to which "system" maps.
*/
void**
smFind(
const SystemMap* const map,
const void* const system)
{
Entry targetEntry;
Entry** treeEntry;
targetEntry.system = system;
treeEntry = tfind(&targetEntry, &map->tree, compareEntries);
return
treeEntry == NULL
? NULL
: &(*treeEntry)->ptr;
}
/*
* Returns the address of the pointer to which a unit-system maps -- creating a
* new entry if necessary. If a new entry is created, then the pointer whose
* address is returned will be NULL.
*
* Arguments:
* map Pointer to the system-map.
* system Pointer to the unit-system.
* Returns:
* NULL Operating system failure. See "errno".
* else Address of the pointer to which "system" maps.
*/
void**
smSearch(
SystemMap* const map,
const void* system)
{
void** addr = NULL; /* failure */
Entry* targetEntry = (Entry*)malloc(sizeof(Entry));
if (targetEntry != NULL) {
Entry** treeEntry;
targetEntry->system = system;
targetEntry->ptr = NULL;
treeEntry = tsearch(targetEntry, &map->tree, compareEntries);
if (treeEntry == NULL) {
free(targetEntry);
}
else {
addr = &(*treeEntry)->ptr;
if (targetEntry != *treeEntry)
free(targetEntry);
}
}
return addr;
}
/*
* Removes the system-map entry that corresponds to a unit-system.
*
* Arguments:
* map Pointer to the map.
* system Pointer to the unit-system.
*/
void
smRemove(
SystemMap* const map,
const void* const system)
{
Entry targetEntry;
Entry** treeEntry;
targetEntry.system = system;
treeEntry = tfind(&targetEntry, &map->tree, compareEntries);
if (treeEntry != NULL) {
Entry* entry = *treeEntry;
(void)tdelete(entry, &map->tree, compareEntries);
free(entry);
}
}
/*
* Frees a system-map. This function should be called when a system-map is no
* longer needed.
*
* Arguments:
* map Pointer to the system-map to be freed or NULL. Use of "map"
* upon return results in undefined behavior.
*/
void
smFree(
SystemMap* const map)
{
if (map != NULL) {
while (map->tree != NULL) {
Entry* entry = *(Entry**)map->tree;
tdelete(entry, &map->tree, compareEntries);
free(entry);
}
free(map);
}
}
|