Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/pcidsk/sdk/pcidsk_shape.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Purpose:  PCIDSK Vector Shape interface.  Declaration.
4
 *
5
 ******************************************************************************
6
 * Copyright (c) 2009
7
 * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#ifndef INCLUDE_PCIDSK_SHAPE_H
13
#define INCLUDE_PCIDSK_SHAPE_H
14
15
#include <string>
16
#include <vector>
17
#include <cstdlib>
18
#include <cstring>
19
20
namespace PCIDSK
21
{
22
23
    //! Type used for shape identifier, use constant NullShapeId as a NULL value
24
    typedef int32 ShapeId;
25
26
    static const ShapeId NullShapeId = -1;
27
28
    //! Structure for an x,y,z point.
29
    typedef struct
30
    {
31
        double x;
32
        double y;
33
        double z;
34
    } ShapeVertex;
35
36
/************************************************************************/
37
/*                            ShapeFieldType                            */
38
/************************************************************************/
39
    //! Attribute field types.
40
    typedef enum  // These deliberately match GDBFieldType values.
41
    {
42
        FieldTypeNone = 0,
43
        FieldTypeFloat = 1,
44
        FieldTypeDouble = 2,
45
        FieldTypeString = 3,
46
        FieldTypeInteger = 4,
47
        FieldTypeCountedInt = 5
48
    } ShapeFieldType;
49
50
/************************************************************************/
51
/*                         ShapeFieldTypeName()                         */
52
/************************************************************************/
53
    /**
54
     \brief Translate field type into a textual description.
55
     @param type the type enumeration value to translate.
56
     @return name for field type.
57
    */
58
    inline std::string ShapeFieldTypeName( ShapeFieldType type )
59
0
    {
60
0
        switch( type ) {
61
0
          case FieldTypeNone: return "None";
62
0
          case FieldTypeFloat: return "Float";
63
0
          case FieldTypeDouble: return "Double";
64
0
          case FieldTypeString: return "String";
65
0
          case FieldTypeInteger: return "Integer";
66
0
          case FieldTypeCountedInt: return "CountedInt";
67
0
        }
68
0
        return "";
69
0
    }
70
71
72
/************************************************************************/
73
/*                              ShapeField                              */
74
/************************************************************************/
75
    /**
76
     \brief Attribute field value.
77
78
     This class encapsulates any of the supported vector attribute field
79
     types in a convenient way that avoids memory leaks or ownership confusion.
80
     The object has a field type (initially FieldTypeNone on construction)
81
     and a value of the specified type.  Note that the appropriate value
82
     accessor (i.e. GetValueInteger()) must be used that corresponds to the
83
     fields type. No attempt is made to automatically convert (i.e. float to
84
     double) if the wrong accessor is used.
85
86
    */
87
88
    class ShapeField
89
    {
90
      private:
91
        ShapeFieldType  type; // use FieldTypeNone for NULL fields.
92
93
        union
94
        {
95
            float       float_val;
96
            double      double_val;
97
            char       *string_val;
98
            int32       integer_val;
99
            int32      *integer_list_val;
100
        } v;
101
102
      public:
103
        //! Simple constructor.
104
        ShapeField()
105
4.19M
            { v.string_val = nullptr; type = FieldTypeNone; }
106
107
        //! Copy constructor.
108
        ShapeField( const ShapeField &src )
109
360k
            { v.string_val = nullptr; type = FieldTypeNone; *this = src; }
110
111
        ~ShapeField()
112
4.55M
            { Clear(); }
113
114
        //! Assignment operator.
115
        ShapeField &operator=( const ShapeField &src )
116
360k
            {
117
360k
                switch( src.GetType() )
118
360k
                {
119
0
                  case FieldTypeFloat:
120
0
                    SetValue( src.GetValueFloat() );
121
0
                    break;
122
758
                  case FieldTypeDouble:
123
758
                    SetValue( src.GetValueDouble() );
124
758
                    break;
125
570
                  case FieldTypeInteger:
126
570
                    SetValue( src.GetValueInteger() );
127
570
                    break;
128
0
                  case FieldTypeCountedInt:
129
0
                    SetValue( src.GetValueCountedInt() );
130
0
                    break;
131
358k
                  case FieldTypeString:
132
358k
                    SetValue( src.GetValueString() );
133
358k
                    break;
134
0
                  case FieldTypeNone:
135
0
                    Clear();
136
0
                    break;
137
360k
                }
138
360k
                return *this;
139
360k
            }
140
141
        //! Assignment operator.
142
        bool operator==( const ShapeField &other )
143
0
            {
144
0
                if( GetType() != other.GetType() )
145
0
                    return false;
146
0
147
0
                switch( other.GetType() )
148
0
                {
149
0
                  case FieldTypeFloat:
150
0
                    return GetValueFloat() == other.GetValueFloat();
151
0
                  case FieldTypeDouble:
152
0
                    return GetValueDouble() == other.GetValueDouble();
153
0
                  case FieldTypeInteger:
154
0
                    return GetValueInteger() == other.GetValueInteger();
155
0
                  case FieldTypeString:
156
0
                    return GetValueString() == other.GetValueString();
157
0
                  case FieldTypeCountedInt:
158
0
                    return GetValueCountedInt() == other.GetValueCountedInt();
159
0
                  case FieldTypeNone:
160
0
                    return false;
161
0
                  default:
162
0
                    return false;
163
0
                }
164
0
            }
165
166
        //! Clear field value.
167
        void Clear()
168
9.86M
            {
169
9.86M
                if( (type == FieldTypeString || type == FieldTypeCountedInt)
170
5.08M
                    && v.string_val != nullptr )
171
5.08M
                {
172
5.08M
                    free( v.string_val );
173
5.08M
                    v.string_val = nullptr;
174
5.08M
                }
175
9.86M
                type = FieldTypeNone;
176
9.86M
            }
177
178
        //! Fetch field type
179
        ShapeFieldType  GetType() const
180
9.22M
            { return type; }
181
182
        //! Set integer value on field.
183
        void SetValue( int32 val )
184
186k
            {
185
186k
                Clear();
186
186k
                type = FieldTypeInteger;
187
186k
                v.integer_val = val;
188
186k
            }
189
190
        //! Set integer list value on field.
191
        void SetValue( const std::vector<int32> &val )
192
0
            {
193
0
                Clear();
194
0
                type = FieldTypeCountedInt;
195
0
                v.integer_list_val = (int32*)
196
0
                    malloc(sizeof(int32) * (val.size()+1) );
197
0
                v.integer_list_val[0] = static_cast<int32>(val.size());
198
0
                if( !val.empty() )
199
0
                    memcpy( v.integer_list_val+1, &(val[0]),
200
0
                            sizeof(int32) * val.size() );
201
0
            }
202
203
        //! Set string value on field.
204
        void SetValue( const std::string &val )
205
5.08M
            {
206
5.08M
                Clear();
207
5.08M
                type = FieldTypeString;
208
5.08M
                v.string_val = strdup(val.c_str());
209
5.08M
            }
210
211
        //! Set double precision floating point value on field.
212
        void SetValue( double val )
213
38.6k
            {
214
38.6k
                Clear();
215
38.6k
                type = FieldTypeDouble;
216
38.6k
                v.double_val = val;
217
38.6k
            }
218
219
        //! Set single precision floating point value on field.
220
        void SetValue( float val )
221
0
            {
222
0
                Clear();
223
0
                type = FieldTypeFloat;
224
0
                v.float_val = val;
225
0
            }
226
227
        //! Fetch value as integer or zero if field not of appropriate type.
228
        int32 GetValueInteger() const
229
186k
            { if( type == FieldTypeInteger ) return v.integer_val; else return 0; }
230
        //! Fetch value as integer list or empty list if field not of appropriate type.
231
        std::vector<int32> GetValueCountedInt() const
232
0
            {
233
0
                std::vector<int32> result;
234
0
                if( type == FieldTypeCountedInt )
235
0
                {
236
0
                    result.resize( v.integer_list_val[0] );
237
0
                    if( v.integer_list_val[0] > 0 )
238
0
                        memcpy( &(result[0]), &(v.integer_list_val[1]),
239
0
                                (v.integer_list_val[0]) * sizeof(int32) );
240
0
                }
241
0
                return result;
242
0
            }
243
        //! Fetch value as string or "" if field not of appropriate type.
244
        std::string GetValueString() const
245
9.26M
            { if( type == FieldTypeString ) return v.string_val; else return ""; }
246
        //! Fetch value as float or 0.0 if field not of appropriate type.
247
        float GetValueFloat() const
248
0
            { if( type == FieldTypeFloat ) return v.float_val; else return 0.0; }
249
        //! Fetch value as double or 0.0 if field not of appropriate type.
250
        double GetValueDouble() const
251
38.4k
            { if( type == FieldTypeDouble ) return v.double_val; else return 0.0; }
252
    };
253
254
} // end namespace PCIDSK
255
256
#endif // INCLUDE_PCIDSK_SHAPE_H