Coverage Report

Created: 2025-06-13 06:29

/src/gdal/frmts/gtiff/libgeotiff/geo_set.c
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
 *
3
 *  geo_set.c  -- Public routines for GEOTIFF GeoKey access.
4
 *
5
 *    Written By: Niles D. Ritter.
6
 *
7
 *  copyright (c) 1995   Niles D. Ritter
8
 *
9
 *  Permission granted to use this software, so long as this copyright
10
 *  notice accompanies any products derived therefrom.
11
 *
12
 **********************************************************************/
13
14
#include <assert.h>
15
#include <stdarg.h>
16
#include <string.h>
17
18
#include "geotiff.h"   /* public interface        */
19
#include "geo_tiffp.h" /* external TIFF interface */
20
#include "geo_keyp.h"  /* private interface       */
21
22
/**
23
This function writes a geokey_t value to a GeoTIFF file.
24
25
@param gtif The geotiff information handle from GTIFNew().
26
27
@param keyID The geokey_t name (such as ProjectedCSTypeGeoKey).
28
This must come from the list of legal geokey_t values
29
(an enumeration) listed below.
30
31
@param type Type of the key.
32
33
@param count Indicates how many values
34
to read.  At this time all keys except for strings have only one value,
35
so <b>index</b> should be zero, and <b>count</b> should be one.<p>
36
37
The <b>keyID</b> indicates the key name to be written to the
38
file and should from the geokey_t enumeration
39
(eg. <tt>ProjectedCSTypeGeoKey</tt>).  The full list of possible geokey_t
40
values can be found in geokeys.inc, or in the online documentation for
41
GTIFKeyGet().<p>
42
43
The <b>type</b> should be one of TYPE_SHORT, TYPE_ASCII, or TYPE_DOUBLE and
44
will indicate the type of value being passed at the end of the argument
45
list (the key value).  The <b>count</b> should be one except for strings
46
when it should be the length of the string (or zero to for this to be
47
computed internally).  As a special case a <b>count</b> of -1 can be
48
used to request an existing key be deleted, in which no value is passed.<p>
49
50
The actual value is passed at the end of the argument list, and should be
51
a short, a double, or a char * value.  Note that short and double values
52
are passed by value rather than as pointers when count is 1, but as pointers
53
if count is larger than 1.<p>
54
55
Note that key values aren't actually flushed to the file until
56
GTIFWriteKeys() is called.  Till then
57
the new values are just kept with the GTIF structure.<p>
58
59
<b>Example:</b><p>
60
61
<pre>
62
    GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1,
63
               RasterPixelIsArea);
64
    GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0,
65
               "UTM 11 North / NAD27" );
66
</pre>
67
68
 */
69
70
int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
71
0
{
72
0
    va_list ap;
73
0
    int nIndex = gtif->gt_keyindex[ keyID ];
74
0
    GeoKey *key;
75
0
    char *data = NULL;
76
0
    char *val = NULL;
77
0
    pinfo_t sval;
78
0
    double dval;
79
80
0
    va_start(ap, count);
81
    /* pass singleton keys by value */
82
0
    if (count>1 && type!=TYPE_ASCII)
83
0
    {
84
0
        val = va_arg(ap, char*);
85
0
    }
86
0
    else if( count == -1 )
87
0
    {
88
        /* delete the indicated tag */
89
0
        va_end(ap);
90
91
0
        if( nIndex < 1 )
92
0
            return 0;
93
94
0
        if (gtif->gt_keys[nIndex].gk_type == TYPE_ASCII)
95
0
        {
96
0
            _GTIFFree (gtif->gt_keys[nIndex].gk_data);
97
0
        }
98
99
0
        while( nIndex < gtif->gt_num_keys )
100
0
        {
101
0
            _GTIFmemcpy( gtif->gt_keys + nIndex,
102
0
                         gtif->gt_keys + nIndex + 1,
103
0
                         sizeof(GeoKey) );
104
0
            gtif->gt_keyindex[gtif->gt_keys[nIndex].gk_key] = nIndex;
105
0
            nIndex++;
106
0
        }
107
108
0
        gtif->gt_num_keys--;
109
0
        gtif->gt_nshorts -= sizeof(KeyEntry)/sizeof(pinfo_t);
110
0
        gtif->gt_keyindex[keyID] = 0;
111
0
        gtif->gt_flags |= FLAG_FILE_MODIFIED;
112
113
0
        return 1;
114
0
    }
115
0
    else switch (type)
116
0
    {
117
0
      case TYPE_SHORT:
118
        /* cppcheck-suppress unreadVariable */
119
0
        sval=(pinfo_t) va_arg(ap, int);
120
0
        val=(char *)&sval;
121
0
        break;
122
0
      case TYPE_DOUBLE:
123
        /* cppcheck-suppress unreadVariable */
124
0
        dval=va_arg(ap, dblparam_t);
125
0
        val=(char *)&dval;
126
0
        break;
127
0
      case TYPE_ASCII:
128
0
        val=va_arg(ap, char*);
129
0
        count = (int)strlen(val) + 1; /* force = string length */
130
0
        break;
131
0
      default:
132
0
        assert( FALSE );
133
0
        break;
134
0
    }
135
0
    va_end(ap);
136
137
    /* We assume here that there are no multi-valued SHORTS ! */
138
0
    if (nIndex)
139
0
    {
140
        /* Key already exists */
141
0
        key = gtif->gt_keys+nIndex;
142
0
        if (type!=key->gk_type || count > key->gk_count)
143
0
        {
144
            /* need to reset data pointer */
145
0
            key->gk_type = type;
146
0
            key->gk_count = count;
147
0
            key->gk_size = _gtiff_size[ type ];
148
149
0
            if( type == TYPE_DOUBLE )
150
0
            {
151
0
                key->gk_data = (char *)(gtif->gt_double + gtif->gt_ndoubles);
152
0
                gtif->gt_ndoubles += count;
153
0
            }
154
0
        }
155
0
    }
156
0
    else
157
0
    {
158
        /* We need to create the key */
159
0
        if (gtif->gt_num_keys == MAX_KEYS) return 0;
160
0
        key = gtif->gt_keys + ++gtif->gt_num_keys;
161
0
        nIndex = gtif->gt_num_keys;
162
0
        gtif->gt_keyindex[ keyID ] = nIndex;
163
0
        key->gk_key = keyID;
164
0
        key->gk_type = type;
165
0
        key->gk_count = count;
166
0
        key->gk_size = _gtiff_size[ type ];
167
0
        if ((geokey_t)gtif->gt_keymin > keyID)  gtif->gt_keymin=keyID;
168
0
        if ((geokey_t)gtif->gt_keymax < keyID)  gtif->gt_keymax=keyID;
169
0
        gtif->gt_nshorts += sizeof(KeyEntry)/sizeof(pinfo_t);
170
0
        if( type == TYPE_DOUBLE )
171
0
        {
172
0
            key->gk_data = (char *)(gtif->gt_double + gtif->gt_ndoubles);
173
0
            gtif->gt_ndoubles += count;
174
0
        }
175
0
    }
176
177
0
    switch (type)
178
0
    {
179
0
        case TYPE_SHORT:
180
0
            if (count > 1) return 0;
181
0
            data = (char *)&key->gk_data; /* store value *in* data */
182
0
            break;
183
0
        case TYPE_DOUBLE:
184
0
            data = key->gk_data;
185
0
            break;
186
0
        case TYPE_ASCII:
187
            /* throw away existing data and allocate room for new data */
188
0
            if (key->gk_data != 0)
189
0
            {
190
0
                _GTIFFree(key->gk_data);
191
0
            }
192
0
            key->gk_data = (char *)_GTIFcalloc(count);
193
0
            key->gk_count = count;
194
0
            data = key->gk_data;
195
0
            break;
196
0
        default:
197
0
            return 0;
198
0
    }
199
200
0
    _GTIFmemcpy(data, val, count*key->gk_size);
201
202
0
    gtif->gt_flags |= FLAG_FILE_MODIFIED;
203
0
    return 1;
204
0
}
205
206
/* Set the version numbers of the GeoTIFF directory */
207
int  GTIFSetVersionNumbers(GTIF* gtif,
208
                           unsigned short version,
209
                           unsigned short key_revision,
210
                           unsigned short minor_revision)
211
0
{
212
0
    gtif->gt_version = version;
213
0
    gtif->gt_rev_major = key_revision;
214
0
    gtif->gt_rev_minor = minor_revision;
215
0
    return 1;
216
0
}