Coverage Report

Created: 2025-07-12 06:32

/src/PROJ/src/initcache.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * Project:  PROJ.4
3
 * Purpose:  init file definition cache.
4
 * Author:   Frank Warmerdam, warmerdam@pobox.com
5
 *
6
 ******************************************************************************
7
 * Copyright (c) 2009, Frank Warmerdam
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
26
 *****************************************************************************/
27
28
#include <assert.h>
29
#include <string.h>
30
31
#include "proj.h"
32
#include "proj_internal.h"
33
34
static int cache_count = 0;
35
static int cache_alloc = 0;
36
static char **cache_key = nullptr;
37
static paralist **cache_paralist = nullptr;
38
39
/************************************************************************/
40
/*                            pj_clone_paralist()                       */
41
/*                                                                      */
42
/*     Allocate a copy of a parameter list.                             */
43
/************************************************************************/
44
45
982
paralist *pj_clone_paralist(const paralist *list) {
46
982
    paralist *list_copy = nullptr, *next_copy = nullptr;
47
48
5.80k
    for (; list != nullptr; list = list->next) {
49
4.82k
        paralist *newitem =
50
4.82k
            (paralist *)malloc(sizeof(paralist) + strlen(list->param));
51
4.82k
        assert(newitem);
52
53
4.82k
        newitem->used = 0;
54
4.82k
        newitem->next = nullptr;
55
4.82k
        strcpy(newitem->param, list->param);
56
57
4.82k
        if (next_copy)
58
3.84k
            next_copy->next = newitem;
59
982
        else
60
982
            list_copy = newitem;
61
62
4.82k
        next_copy = newitem;
63
4.82k
    }
64
65
982
    return list_copy;
66
982
}
67
68
/************************************************************************/
69
/*                            pj_clear_initcache()                      */
70
/*                                                                      */
71
/*      Clear out all memory held in the init file cache.               */
72
/************************************************************************/
73
74
11.3k
void pj_clear_initcache() {
75
11.3k
    if (cache_alloc > 0) {
76
227
        int i;
77
78
227
        pj_acquire_lock();
79
80
521
        for (i = 0; i < cache_count; i++) {
81
294
            paralist *n, *t = cache_paralist[i];
82
83
294
            free(cache_key[i]);
84
85
            /* free parameter list elements */
86
1.93k
            for (; t != nullptr; t = n) {
87
1.63k
                n = t->next;
88
1.63k
                free(t);
89
1.63k
            }
90
294
        }
91
92
227
        free(cache_key);
93
227
        free(cache_paralist);
94
227
        cache_count = 0;
95
227
        cache_alloc = 0;
96
227
        cache_key = nullptr;
97
227
        cache_paralist = nullptr;
98
99
227
        pj_release_lock();
100
227
    }
101
11.3k
}
102
103
/************************************************************************/
104
/*                            pj_search_initcache()                     */
105
/*                                                                      */
106
/*      Search for a matching definition in the init cache.             */
107
/************************************************************************/
108
109
paralist *pj_search_initcache(const char *filekey)
110
111
1.37k
{
112
1.37k
    int i;
113
1.37k
    paralist *result = nullptr;
114
115
1.37k
    pj_acquire_lock();
116
117
2.53k
    for (i = 0; result == nullptr && i < cache_count; i++) {
118
1.16k
        if (strcmp(filekey, cache_key[i]) == 0) {
119
688
            result = pj_clone_paralist(cache_paralist[i]);
120
688
        }
121
1.16k
    }
122
123
1.37k
    pj_release_lock();
124
125
1.37k
    return result;
126
1.37k
}
127
128
/************************************************************************/
129
/*                            pj_insert_initcache()                     */
130
/*                                                                      */
131
/*      Insert a paralist definition in the init file cache.            */
132
/************************************************************************/
133
134
void pj_insert_initcache(const char *filekey, const paralist *list)
135
136
294
{
137
294
    pj_acquire_lock();
138
139
    /*
140
    ** Grow list if required.
141
    */
142
294
    if (cache_count == cache_alloc) {
143
227
        char **cache_key_new;
144
227
        paralist **cache_paralist_new;
145
146
227
        cache_alloc = cache_alloc * 2 + 15;
147
148
227
        cache_key_new = (char **)malloc(sizeof(char *) * cache_alloc);
149
227
        assert(cache_key_new);
150
227
        if (cache_key && cache_count) {
151
0
            memcpy(cache_key_new, cache_key, sizeof(char *) * cache_count);
152
0
        }
153
227
        free(cache_key);
154
227
        cache_key = cache_key_new;
155
156
227
        cache_paralist_new =
157
227
            (paralist **)malloc(sizeof(paralist *) * cache_alloc);
158
227
        assert(cache_paralist_new);
159
227
        if (cache_paralist && cache_count) {
160
0
            memcpy(cache_paralist_new, cache_paralist,
161
0
                   sizeof(paralist *) * cache_count);
162
0
        }
163
227
        free(cache_paralist);
164
227
        cache_paralist = cache_paralist_new;
165
227
    }
166
167
    /*
168
    ** Duplicate the filekey and paralist, and insert in cache.
169
    */
170
294
    cache_key[cache_count] = (char *)malloc(strlen(filekey) + 1);
171
294
    assert(cache_key[cache_count]);
172
294
    strcpy(cache_key[cache_count], filekey);
173
174
294
    cache_paralist[cache_count] = pj_clone_paralist(list);
175
176
294
    cache_count++;
177
178
294
    pj_release_lock();
179
294
}