Coverage Report

Created: 2026-08-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/dcmdata/libsrc/dcvrus.cc
Line
Count
Source
1
/*
2
 *
3
 *  Copyright (C) 1994-2026, OFFIS e.V.
4
 *  All rights reserved.  See COPYRIGHT file for details.
5
 *
6
 *  This software and supporting documentation were developed by
7
 *
8
 *    OFFIS e.V.
9
 *    R&D Division Health
10
 *    Escherweg 2
11
 *    D-26121 Oldenburg, Germany
12
 *
13
 *
14
 *  Module:  dcmdata
15
 *
16
 *  Author:  Gerd Ehlers, Andreas Barth
17
 *
18
 *  Purpose: Implementation of class DcmUnsignedShort
19
 *
20
 */
21
22
23
#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
24
#include "dcmtk/dcmdata/dcvrus.h"
25
#include "dcmtk/ofstd/ofstd.h"
26
#include "dcmtk/ofstd/ofstream.h"
27
28
// ********************************
29
30
31
DcmUnsignedShort::DcmUnsignedShort(const DcmTag &tag)
32
0
  : DcmElement(tag, 0)
33
0
{
34
0
}
35
36
37
DcmUnsignedShort::DcmUnsignedShort(const DcmTag &tag, const Uint32 len)
38
3.90k
  : DcmElement(tag, len)
39
3.90k
{
40
3.90k
}
41
42
43
DcmUnsignedShort::DcmUnsignedShort(const DcmUnsignedShort &old)
44
0
  : DcmElement(old)
45
0
{
46
0
}
47
48
49
DcmUnsignedShort::~DcmUnsignedShort()
50
3.90k
{
51
3.90k
}
52
53
54
DcmUnsignedShort &DcmUnsignedShort::operator=(const DcmUnsignedShort &obj)
55
0
{
56
0
    DcmElement::operator=(obj);
57
0
    return *this;
58
0
}
59
60
61
int DcmUnsignedShort::compare(const DcmElement& rhs) const
62
0
{
63
0
    int result = DcmElement::compare(rhs);
64
0
    if (result != 0)
65
0
    {
66
0
        return result;
67
0
    }
68
69
    /* cast away constness (dcmdata is not const correct...) */
70
0
    DcmUnsignedShort* myThis = NULL;
71
0
    DcmUnsignedShort* myRhs = NULL;
72
0
    myThis = OFconst_cast(DcmUnsignedShort*, this);
73
0
    myRhs =  OFstatic_cast(DcmUnsignedShort*, OFconst_cast(DcmElement*, &rhs));
74
75
    /* compare number of values */
76
0
    unsigned long thisNumValues = myThis->getNumberOfValues();
77
0
    unsigned long rhsNumValues = myRhs->getNumberOfValues();
78
0
    if (thisNumValues < rhsNumValues)
79
0
    {
80
0
        return -1;
81
0
    }
82
0
    else if (thisNumValues > rhsNumValues)
83
0
    {
84
0
        return 1;
85
0
    }
86
87
    /* iterate over all components and test equality */
88
0
    for (unsigned long count = 0; count < thisNumValues; count++)
89
0
    {
90
0
        Uint16 val = 0;
91
0
        if (myThis->getUint16(val, count).good())
92
0
        {
93
0
            Uint16 rhsVal = 0;
94
0
            if (myRhs->getUint16(rhsVal, count).good())
95
0
            {
96
0
                  if (val > rhsVal)
97
0
                  {
98
0
                      return 1;
99
0
                  }
100
0
                  else if (val < rhsVal)
101
0
                  {
102
0
                      return -1;
103
0
                  }
104
0
            }
105
0
        }
106
0
    }
107
108
    /* all values as well as VM equal: objects are equal */
109
0
    return 0;
110
0
}
111
112
113
OFCondition DcmUnsignedShort::copyFrom(const DcmObject& rhs)
114
0
{
115
0
    if (this != &rhs)
116
0
    {
117
0
        if (rhs.ident() != ident()) return EC_IllegalCall;
118
0
        *this = OFstatic_cast(const DcmUnsignedShort &, rhs);
119
0
    }
120
0
    return EC_Normal;
121
0
}
122
123
124
// ********************************
125
126
127
DcmEVR DcmUnsignedShort::ident() const
128
120
{
129
120
    return EVR_US;
130
120
}
131
132
133
OFCondition DcmUnsignedShort::checkValue(const OFString &vm,
134
                                         const OFBool /*oldFormat*/)
135
0
{
136
    /* check VM only */
137
0
    return DcmElement::checkVM(getVM(), vm);
138
0
}
139
140
141
unsigned long DcmUnsignedShort::getVM()
142
3
{
143
3
    return getNumberOfValues();
144
3
}
145
146
147
unsigned long DcmUnsignedShort::getNumberOfValues()
148
3
{
149
3
    return OFstatic_cast(unsigned long, getLengthField() / sizeof(Uint16));
150
3
}
151
152
153
// ********************************
154
155
156
void DcmUnsignedShort::print(STD_NAMESPACE ostream &out,
157
                             const size_t flags,
158
                             const int level,
159
                             const char * /*pixelFileName*/,
160
                             size_t * /*pixelCounter*/)
161
0
{
162
0
    if (valueLoaded())
163
0
    {
164
        /* get unsigned integer data */
165
0
        Uint16 *uintVals;
166
0
        errorFlag = getUint16Array(uintVals);
167
0
        if (uintVals != NULL)
168
0
        {
169
0
            const unsigned long count = getNumberOfValues();
170
            /* double-check length field for valid value */
171
0
            if (count > 0)
172
0
            {
173
0
                const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ?
174
0
                    DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/;
175
0
                unsigned long printedLength = 0;
176
0
                unsigned long newLength = 0;
177
0
                char buffer[32];
178
                /* print line start with tag and VR */
179
0
                printInfoLineStart(out, flags, level);
180
                /* print multiple values */
181
0
                for (unsigned int i = 0; i < count; i++, uintVals++)
182
0
                {
183
                    /* check whether first value is printed (omit delimiter) */
184
0
                    if (i == 0)
185
0
                        OFStandard::snprintf(buffer, sizeof(buffer), "%hu", *uintVals);
186
0
                    else
187
0
                        OFStandard::snprintf(buffer, sizeof(buffer), "\\%hu", *uintVals);
188
                    /* check whether current value sticks to the length limit */
189
0
                    newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer));
190
0
                    if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength)))
191
0
                    {
192
0
                        out << buffer;
193
0
                        printedLength = newLength;
194
0
                    } else {
195
                        /* check whether output has been truncated */
196
0
                        if (i + 1 < count)
197
0
                        {
198
0
                            out << "...";
199
0
                            printedLength += 3;
200
0
                        }
201
0
                        break;
202
0
                    }
203
0
                }
204
                /* print line end with length, VM and tag name */
205
0
                printInfoLineEnd(out, flags, printedLength);
206
0
            } else {
207
                /* count can be zero if we have an invalid element with less than two bytes length */
208
0
                printInfoLine(out, flags, level, "(invalid value)");
209
0
            }
210
0
        } else
211
0
            printInfoLine(out, flags, level, "(no value available)");
212
0
    } else
213
0
        printInfoLine(out, flags, level, "(not loaded)");
214
0
}
215
216
217
// ********************************
218
219
220
OFCondition DcmUnsignedShort::getUint16(Uint16 &uintVal,
221
                                        const unsigned long pos)
222
10
{
223
    /* get unsigned integer data */
224
10
    Uint16 *uintValues = NULL;
225
10
    errorFlag = getUint16Array(uintValues);
226
    /* check data before returning */
227
10
    if (errorFlag.good())
228
10
    {
229
10
        if (uintValues == NULL)
230
7
            errorFlag = EC_IllegalCall;
231
3
        else if (pos >= getVM())
232
0
            errorFlag = EC_IllegalParameter;
233
3
        else
234
3
            uintVal = uintValues[pos];
235
10
    }
236
    /* clear value in case of error */
237
10
    if (errorFlag.bad())
238
7
        uintVal = 0;
239
10
    return errorFlag;
240
10
}
241
242
243
OFCondition DcmUnsignedShort::getUint16Array(Uint16 *&uintVals)
244
10
{
245
10
    uintVals = OFstatic_cast(Uint16 *, getValue());
246
10
    return errorFlag;
247
10
}
248
249
250
// ********************************
251
252
253
OFCondition DcmUnsignedShort::getOFString(OFString &stringVal,
254
                                          const unsigned long pos,
255
                                          OFBool /*normalize*/)
256
10
{
257
10
    Uint16 uintVal;
258
    /* get the specified numeric value */
259
10
    errorFlag = getUint16(uintVal, pos);
260
10
    if (errorFlag.good())
261
3
    {
262
        /* ... and convert it to a character string */
263
3
        char buffer[32];
264
3
        OFStandard::snprintf(buffer, sizeof(buffer), "%hu", uintVal);
265
        /* assign result */
266
3
        stringVal = buffer;
267
3
    }
268
10
    return errorFlag;
269
10
}
270
271
272
// ********************************
273
274
275
OFCondition DcmUnsignedShort::putUint16(const Uint16 uintVal,
276
                                        const unsigned long pos)
277
0
{
278
0
    Uint16 val = uintVal;
279
0
    errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Uint16) * pos), OFstatic_cast(Uint32, sizeof(Uint16)));
280
0
    return errorFlag;
281
0
}
282
283
284
OFCondition DcmUnsignedShort::putUint16Array(const Uint16 *uintVals,
285
                                             const unsigned long numUints)
286
0
{
287
0
    errorFlag = EC_Normal;
288
0
    if (numUints > 0)
289
0
    {
290
        /* check for valid data */
291
0
        if (uintVals != NULL)
292
0
            errorFlag = putValue(uintVals, OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numUints)));
293
0
        else
294
0
            errorFlag = EC_CorruptedData;
295
0
    } else
296
0
        errorFlag = putValue(NULL, 0);
297
0
    return errorFlag;
298
0
}
299
300
301
// ********************************
302
303
304
OFCondition DcmUnsignedShort::putString(const char *stringVal)
305
0
{
306
    /* determine length of the string value */
307
0
    const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0;
308
    /* call the real function */
309
0
    return putString(stringVal, OFstatic_cast(Uint32, stringLen));
310
0
}
311
312
313
OFCondition DcmUnsignedShort::putString(const char *stringVal,
314
                                        const Uint32 stringLen)
315
0
{
316
0
    errorFlag = EC_Normal;
317
    /* determine VM of the string */
318
0
    const unsigned long vm = DcmElement::determineVM(stringVal, stringLen);
319
0
    if (vm > 0)
320
0
    {
321
        /* reject values whose overall length would exceed the 32-bit DICOM value length
322
         * limit; this also prevents an integer overflow in the allocation size below
323
         */
324
0
        if (vm > DCM_UndefinedLength / sizeof(Uint16))
325
0
        {
326
0
            errorFlag = EC_ElemLengthExceeds32BitField;
327
0
            return errorFlag;
328
0
        }
329
0
        Uint16 *field = new Uint16[vm];
330
0
        OFString value;
331
0
        size_t pos = 0;
332
        /* retrieve unsigned integer data from character string */
333
0
        for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++)
334
0
        {
335
            /* get specified value from multi-valued string */
336
0
            pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value);
337
0
            if (value.empty() || (sscanf(value.c_str(), "%hu", &field[i]) != 1))
338
0
                errorFlag = EC_CorruptedData;
339
0
        }
340
        /* set binary data as the element value */
341
0
        if (errorFlag.good())
342
0
            errorFlag = putUint16Array(field, vm);
343
        /* delete temporary buffer */
344
0
        delete[] field;
345
0
    } else
346
0
        errorFlag = putValue(NULL, 0);
347
0
    return errorFlag;
348
0
}
349
350
351
// ********************************
352
353
354
OFCondition DcmUnsignedShort::verify(const OFBool autocorrect)
355
0
{
356
    /* check for valid value length */
357
0
    if (getLengthField() % (sizeof(Uint16)) != 0)
358
0
    {
359
0
        errorFlag = EC_CorruptedData;
360
0
        if (autocorrect)
361
0
        {
362
            /* strip to valid length */
363
0
            setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Uint16))));
364
0
        }
365
0
    } else
366
0
        errorFlag = EC_Normal;
367
0
    return errorFlag;
368
0
}
369
370
371
OFBool DcmUnsignedShort::matches(const DcmElement& candidate,
372
                                 const OFBool enableWildCardMatching) const
373
0
{
374
0
  OFstatic_cast(void,enableWildCardMatching);
375
0
  if (ident() == candidate.ident())
376
0
  {
377
    // some const casts to call the getter functions, I do not modify the values, I promise!
378
0
    DcmUnsignedShort& key = OFconst_cast(DcmUnsignedShort&,*this);
379
0
    DcmElement& can = OFconst_cast(DcmElement&,candidate);
380
0
    Uint16 a, b;
381
0
    for( unsigned long ui = 0; ui < key.getVM(); ++ui )
382
0
      for( unsigned long uj = 0; uj < can.getVM(); ++uj )
383
0
        if( key.getUint16( a, ui ).good() && can.getUint16( b, uj ).good() && a == b )
384
0
          return OFTrue;
385
0
    return key.getVM() == 0;
386
0
  }
387
0
  return OFFalse;
388
0
}