Coverage Report

Created: 2026-06-05 06:37

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