Coverage Report

Created: 2026-06-05 06:37

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