Coverage Report

Created: 2026-06-30 07:05

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