Coverage Report

Created: 2026-11-12 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/dcmdata/libsrc/dcitem.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
17
 *
18
 *  Purpose: class DcmItem
19
 *
20
 */
21
22
23
#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
24
25
#include "dcmtk/dcmdata/dcitem.h"
26
#include "dcmtk/dcmdata/dcdeftag.h"   /* for name constants */
27
#include "dcmtk/dcmdata/dcistrma.h"   /* for class DcmInputStream */
28
#include "dcmtk/dcmdata/dcobject.h"
29
#include "dcmtk/dcmdata/dcostrma.h"   /* for class DcmOutputStream */
30
#include "dcmtk/dcmdata/dcovlay.h"
31
#include "dcmtk/dcmdata/dcpixel.h"
32
#include "dcmtk/dcmdata/dcsequen.h"
33
#include "dcmtk/dcmdata/dcswap.h"
34
#include "dcmtk/dcmdata/dcvr.h"
35
#include "dcmtk/dcmdata/dcvrae.h"
36
#include "dcmtk/dcmdata/dcvras.h"
37
#include "dcmtk/dcmdata/dcvrat.h"
38
#include "dcmtk/dcmdata/dcvrcs.h"
39
#include "dcmtk/dcmdata/dcvrda.h"
40
#include "dcmtk/dcmdata/dcvrds.h"
41
#include "dcmtk/dcmdata/dcvrdt.h"
42
#include "dcmtk/dcmdata/dcvrfd.h"
43
#include "dcmtk/dcmdata/dcvrfl.h"
44
#include "dcmtk/dcmdata/dcvris.h"
45
#include "dcmtk/dcmdata/dcvrlo.h"
46
#include "dcmtk/dcmdata/dcvrlt.h"
47
#include "dcmtk/dcmdata/dcvrobow.h"
48
#include "dcmtk/dcmdata/dcvrod.h"
49
#include "dcmtk/dcmdata/dcvrof.h"
50
#include "dcmtk/dcmdata/dcvrol.h"
51
#include "dcmtk/dcmdata/dcvrov.h"
52
#include "dcmtk/dcmdata/dcvrpn.h"
53
#include "dcmtk/dcmdata/dcvrsh.h"
54
#include "dcmtk/dcmdata/dcvrsl.h"
55
#include "dcmtk/dcmdata/dcvrss.h"
56
#include "dcmtk/dcmdata/dcvrst.h"
57
#include "dcmtk/dcmdata/dcvrsv.h"
58
#include "dcmtk/dcmdata/dcvrtm.h"
59
#include "dcmtk/dcmdata/dcvruc.h"
60
#include "dcmtk/dcmdata/dcvrui.h"
61
#include "dcmtk/dcmdata/dcvrul.h"
62
#include "dcmtk/dcmdata/dcvrulup.h"
63
#include "dcmtk/dcmdata/dcvrur.h"
64
#include "dcmtk/dcmdata/dcvrus.h"
65
#include "dcmtk/dcmdata/dcvrut.h"
66
#include "dcmtk/dcmdata/dcvruv.h"
67
#include "dcmtk/dcmdata/dcxfer.h"
68
#include "dcmtk/dcmdata/dcspchrs.h"   /* for class DcmSpecificCharacterSet */
69
#include "dcmtk/dcmdata/dcjson.h"
70
71
#include "dcmtk/ofstd/ofstream.h"
72
#include "dcmtk/ofstd/ofstring.h"
73
#include "dcmtk/ofstd/ofcast.h"
74
#include "dcmtk/ofstd/ofstd.h"
75
76
#include <cstring>                    /* for memset() */
77
78
// ********************************
79
80
81
DcmItem::DcmItem()
82
0
  : DcmObject(DCM_ItemTag),
83
0
    elementList(NULL),
84
0
    lastElementComplete(OFTrue),
85
0
    fStartPosition(0),
86
0
    privateCreatorCache(),
87
0
    maxNestingDepth(0),
88
0
    maxElementLength(0),
89
0
    incrementalLoadThreshold(0)
90
0
{
91
0
    elementList = new DcmList;
92
0
}
93
94
95
DcmItem::DcmItem(const DcmTag &tag,
96
                 const Uint32 len)
97
139k
  : DcmObject(tag, len),
98
139k
    elementList(NULL),
99
139k
    lastElementComplete(OFTrue),
100
139k
    fStartPosition(0),
101
139k
    privateCreatorCache(),
102
139k
    maxNestingDepth(0),
103
139k
    maxElementLength(0),
104
139k
    incrementalLoadThreshold(0)
105
139k
{
106
139k
    elementList = new DcmList;
107
139k
}
108
109
110
DcmItem::DcmItem(const DcmItem &old)
111
0
  : DcmObject(old),
112
0
    elementList(new DcmList),
113
0
    lastElementComplete(old.lastElementComplete),
114
0
    fStartPosition(old.fStartPosition),
115
0
    privateCreatorCache(),
116
0
    maxNestingDepth(old.maxNestingDepth),
117
0
    maxElementLength(old.maxElementLength),
118
0
    incrementalLoadThreshold(old.incrementalLoadThreshold)
119
0
{
120
0
    if (!old.elementList->empty())
121
0
    {
122
0
        elementList->seek(ELP_first);
123
0
        old.elementList->seek(ELP_first);
124
0
        do
125
0
        {
126
0
            DcmObject *dO = old.elementList->get()->clone();
127
0
            if (elementList->insert(dO, ELP_next))
128
0
            {
129
                // remember the parent
130
0
                dO->setParent(this);
131
0
            }
132
0
        } while (old.elementList->seek(ELP_next));
133
0
    }
134
0
}
135
136
137
DcmItem& DcmItem::operator=(const DcmItem& obj)
138
0
{
139
0
    if (this != &obj)
140
0
    {
141
        // copy parent's member variables
142
0
        DcmObject::operator=(obj);
143
144
        // delete any existing elements
145
0
        elementList->deleteAllElements();
146
147
        // copy DcmItem's member variables
148
0
        lastElementComplete = obj.lastElementComplete;
149
0
        fStartPosition = obj.fStartPosition;
150
0
        maxNestingDepth = obj.maxNestingDepth;
151
0
        maxElementLength = obj.maxElementLength;
152
0
        incrementalLoadThreshold = obj.incrementalLoadThreshold;
153
0
        if (!obj.elementList->empty())
154
0
        {
155
0
            elementList->seek(ELP_first);
156
0
            obj.elementList->seek(ELP_first);
157
0
            do
158
0
            {
159
0
                DcmObject *dO = obj.elementList->get()->clone();
160
0
                if (elementList->insert(dO, ELP_next))
161
0
                {
162
                    // remember the parent
163
0
                    dO->setParent(this);
164
0
                }
165
0
            } while (obj.elementList->seek(ELP_next));
166
0
        }
167
0
    }
168
0
    return *this;
169
0
}
170
171
172
int DcmItem::compare(const DcmItem& rhs) const
173
0
{
174
0
    if (this == &rhs)
175
0
        return 0;
176
177
    // cast away constness (dcmdata is not const correct...)
178
0
    DcmItem* myThis = NULL;
179
0
    DcmItem* myRhs = NULL;
180
0
    myThis = OFconst_cast(DcmItem*, this);
181
0
    myRhs =  OFconst_cast(DcmItem*, &rhs);
182
183
    // check length, i.e. number of elements in item
184
0
    unsigned long thisNumValues = myThis->card();
185
0
    unsigned long rhsNumValues = myRhs->card();
186
0
    if (thisNumValues < rhsNumValues)
187
0
    {
188
0
        return -1;
189
0
    }
190
0
    else if (thisNumValues > rhsNumValues)
191
0
    {
192
0
        return 1;
193
0
    }
194
    // iterate over all items and test equality
195
0
    for (unsigned long count = 0; count < thisNumValues; count++)
196
0
    {
197
0
        DcmElement* val = myThis->getElement(count);
198
0
        if (val)
199
0
        {
200
0
            DcmElement* rhsVal = myRhs->getElement(count);
201
0
            if (rhsVal)
202
0
            {
203
0
                int result = val->compare(*rhsVal);
204
0
                if (result != 0)
205
0
                {
206
0
                    return result;
207
0
                }
208
                // otherwise they are equal, continue comparison
209
0
            }
210
0
        }
211
0
    }
212
213
    // all values as well as VM equal: objects are equal
214
0
    return 0;
215
0
}
216
217
218
OFCondition DcmItem::copyFrom(const DcmObject& rhs)
219
0
{
220
0
    if (this != &rhs)
221
0
    {
222
0
        if (rhs.ident() != ident()) return EC_IllegalCall;
223
0
        *this = OFstatic_cast(const DcmItem &, rhs);
224
0
    }
225
0
    return EC_Normal;
226
0
}
227
228
229
DcmItem::~DcmItem()
230
139k
{
231
139k
    elementList->deleteAllElements();
232
139k
    delete elementList;
233
139k
}
234
235
236
// ********************************
237
238
239
OFBool DcmItem::foundVR(const Uint8* atposition)
240
18.3k
{
241
18.3k
    const Uint8 c1 = atposition[0];
242
18.3k
    const Uint8 c2 = atposition[1];
243
18.3k
    OFBool valid = OFFalse;
244
245
18.3k
    if (isalpha(c1) && isalpha(c2))
246
12.8k
    {
247
12.8k
        Uint8 vrName[3];
248
12.8k
        vrName[0] = c1;
249
12.8k
        vrName[1] = c2;
250
12.8k
        vrName[2] = '\0';
251
252
        /* is this VR name a standard VR descriptor */
253
12.8k
        DcmVR vr( OFreinterpret_cast(const char*, &vrName[0] ) );
254
12.8k
        valid = vr.isStandard();
255
12.8k
    } else {
256
        /* cannot be a valid VR name since non-characters */
257
5.53k
        valid = OFFalse;
258
5.53k
    }
259
18.3k
    return valid;
260
18.3k
}
261
262
263
// ********************************
264
265
266
E_TransferSyntax DcmItem::checkTransferSyntax(DcmInputStream &inStream)
267
18.6k
{
268
18.6k
    E_TransferSyntax transferSyntax;
269
18.6k
    Uint8 tagAndVR[6];
270
271
    /* we need 6 bytes, if there is less available we can't do much */
272
18.6k
    if (inStream.avail() < 6)
273
238
        return EXS_LittleEndianExplicit;
274
275
    /* read 6 bytes from the input stream (try to read tag and VR (data type)) */
276
18.3k
    inStream.mark();
277
18.3k
    inStream.read(tagAndVR, 6);               // check tag & VR
278
18.3k
    inStream.putback();
279
280
    /* create two tag variables (one for little, one for big */
281
    /* endian) in order to figure out, if there is a valid tag */
282
18.3k
    const Uint8 c1 = tagAndVR[0];
283
18.3k
    const Uint8 c2 = tagAndVR[1];
284
18.3k
    const Uint8 c3 = tagAndVR[2];
285
18.3k
    const Uint8 c4 = tagAndVR[3];
286
18.3k
    const Uint16 t1 = OFstatic_cast(unsigned short, (c1 & 0xff) + ((c2 & 0xff) << 8));  // explicit little endian
287
18.3k
    const Uint16 t2 = OFstatic_cast(unsigned short, (c3 & 0xff) + ((c4 & 0xff) << 8));  // conversion
288
18.3k
    DcmTag taglittle(t1, t2);
289
18.3k
    DcmTag tagbig(swapShort(t1), swapShort(t2));
290
291
    /* now we want to determine the transfer syntax which was used to code the information in the stream. */
292
    /* The decision is based on two questions: a) Did we encounter a valid tag? and b) Do the last 2 bytes */
293
    /* which were read from the stream represent a valid VR? In certain special cases, where the transfer */
294
    /* cannot be determined without doubt, we want to guess the most probable transfer syntax. */
295
296
    /* if both tag variables show an error, we encountered an invalid tag */
297
18.3k
    if ((taglittle.error().bad()) && (tagbig.error().bad()))
298
16.5k
    {
299
        /* in case we encountered an invalid tag, we want to assume that the used transfer syntax */
300
        /* is a little endian transfer syntax. Now we have to figure out, if it is an implicit or */
301
        /* explicit transfer syntax. Hence, check if the last 2 bytes represent a valid VR. */
302
16.5k
        if (foundVR(&tagAndVR[4]))
303
11.6k
        {
304
            /* if the last 2 bytes represent a valid VR, we assume that the used */
305
            /* transfer syntax is the little endian explicit transfer syntax. */
306
11.6k
            transferSyntax = EXS_LittleEndianExplicit;
307
11.6k
        } else {
308
            /* if the last 2 bytes did not represent a valid VR, we assume that the */
309
            /* used transfer syntax is the little endian implicit transfer syntax. */
310
4.86k
            transferSyntax = EXS_LittleEndianImplicit;
311
4.86k
        }
312
16.5k
    }
313
    /* if at least one tag variable did not show an error, we encountered a valid tag */
314
1.87k
    else
315
1.87k
    {
316
        /* in case we encountered a valid tag, we want to figure out, if it is an implicit or */
317
        /* explicit transfer syntax. Hence, check if the last 2 bytes represent a valid VR. */
318
1.87k
        if (foundVR(&tagAndVR[4]))
319
1.00k
        {
320
            /* having figured out that the last 2 bytes represent a valid */
321
            /* VR, we need to find out which of the two tags was valid */
322
1.00k
            if (taglittle.error().bad())
323
6
            {
324
                /* if the little endian tag was invalid, the transfer syntax is big endian explicit */
325
6
                transferSyntax = EXS_BigEndianExplicit;
326
6
            }
327
997
            else if (tagbig.error().bad())
328
8
            {
329
                /* if the big endian tag was invalid, the transfer syntax is little endian explicit */
330
8
                transferSyntax = EXS_LittleEndianExplicit;
331
989
            } else {
332
                /* if both tags were valid, we take a look at the group numbers. Since */
333
                /* group 0008 is much more probable than group 0800 for the first tag */
334
                /* we specify the following: */
335
989
                if ((taglittle.getGTag() > 0xff)&&(tagbig.getGTag() <= 0xff)) transferSyntax = EXS_BigEndianExplicit;
336
716
                else transferSyntax = EXS_LittleEndianExplicit;
337
989
            }
338
1.00k
        } else {
339
            /* having figured out that the last 2 bytes do not represent a */
340
            /* valid VR, we need to find out which of the two tags was valid */
341
868
            if (taglittle.error().bad())
342
10
            {
343
                /* if the little endian tag was invalid, the transfer syntax is big endian implicit */
344
10
                transferSyntax = EXS_BigEndianImplicit;
345
10
            }
346
858
            else if (tagbig.error().bad())
347
44
            {
348
                /* if the big endian tag was invalid, the transfer syntax is little endian implicit */
349
44
                transferSyntax = EXS_LittleEndianImplicit;
350
814
            } else {
351
                /* if both tags were valid, we take a look at the group numbers. Since */
352
                /* group 0008 is much more probable than group 0800 for the first tag */
353
                /* we specify the following: */
354
814
                if ((taglittle.getGTag() > 0xff)&&(tagbig.getGTag() <= 0xff)) transferSyntax = EXS_BigEndianImplicit;
355
437
                else transferSyntax = EXS_LittleEndianImplicit;
356
814
            }
357
868
        }
358
1.87k
    }
359
360
    /* return determined transfer syntax */
361
18.3k
    return transferSyntax;
362
18.6k
}
363
364
365
// ********************************
366
367
368
OFBool DcmItem::checkAndUpdateVR(DcmItem &item,
369
                                 DcmTag &tag)
370
63.7k
{
371
63.7k
    OFBool result = OFFalse;
372
    /* handle special cases where the VR can be determined by some other element values */
373
63.7k
    if (((tag == DCM_WaveformData) || (tag == DCM_WaveformPaddingValue) ||
374
63.0k
        (tag == DCM_ChannelMinimumValue) || (tag == DCM_ChannelMaximumValue)) &&
375
1.69k
        (tag.getEVR() == EVR_ox))
376
0
    {
377
        /* case 1 (WaveformData and others): see section 8.3 in PS 3.5 */
378
0
        Uint16 bitsAlloc;
379
0
        if (item.findAndGetUint16(DCM_WaveformBitsAllocated, bitsAlloc).good())
380
0
        {
381
0
            if (bitsAlloc == 8)
382
0
            {
383
0
                DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of "
384
0
                    << tag.getTagName() << " " << tag << " to 'OB' because WaveformBitsAllocated "
385
0
                    << DCM_WaveformBitsAllocated << " has a value of 8");
386
0
                tag.setVR(EVR_OB);
387
0
                result = OFTrue;
388
0
            } else {
389
0
                DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of "
390
0
                    << tag.getTagName() << " " << tag << " to 'OW' because WaveformBitsAllocated "
391
0
                    << DCM_WaveformBitsAllocated << " has a value that is different from 8");
392
0
                tag.setVR(EVR_OW);
393
0
                result = OFTrue;
394
0
            }
395
0
        }
396
0
    }
397
63.7k
    else if (((tag == DCM_PixelPaddingValue) || (tag == DCM_PixelPaddingRangeLimit) ||
398
63.1k
        (tag == DCM_HistogramFirstBinValue) || (tag == DCM_HistogramLastBinValue) ||
399
60.6k
        (tag == DCM_ZeroVelocityPixelValue) || (tag == DCM_SmallestImagePixelValue) ||
400
59.8k
        (tag == DCM_LargestImagePixelValue) || (tag == DCM_SmallestPixelValueInSeries) ||
401
58.9k
        (tag == DCM_LargestPixelValueInSeries) || (tag == DCM_LUTDescriptor) ||
402
58.2k
        (tag == DCM_RealWorldValueLastValueMapped) || (tag == DCM_RealWorldValueFirstValueMapped)) &&
403
6.24k
        (tag.getEVR() == EVR_xs))
404
0
    {
405
        /* case 2 (PixelPaddingValue and others): see section C.7.5.1, C.7.6.16.x and C.11.5 in PS 3.3 */
406
0
        Uint16 pixelRep;
407
0
        if (item.findAndGetUint16(DCM_PixelRepresentation, pixelRep).good())
408
0
        {
409
0
            if (pixelRep == 0x0001)
410
0
            {
411
0
                DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " << tag.getTagName()
412
0
                    << " " << tag << " to 'SS' because PixelRepresentation "
413
0
                    << DCM_PixelRepresentation << " has a value of 1");
414
0
                tag.setVR(EVR_SS);
415
0
                result = OFTrue;
416
0
            } else {
417
0
                DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " << tag.getTagName()
418
0
                    << " " << tag << " to 'US' because PixelRepresentation "
419
0
                    << DCM_PixelRepresentation << " has a value that is different from 1");
420
0
                tag.setVR(EVR_US);
421
0
                result = OFTrue;
422
0
            }
423
0
        }
424
0
    }
425
63.7k
    else if (((tag.getBaseTag() == DCM_OverlayData) && (tag.getEVR() == EVR_ox)) ||
426
63.7k
        ((tag == DCM_PixelData) && (tag.getEVR() == EVR_px)))
427
0
    {
428
        /* case 3 (OverlayData and PixelData): see section 8.1.2 and 8.2 in PS 3.5 */
429
0
        DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of "
430
0
            << tag.getTagName() << " " << tag << " to 'OW'");
431
0
        tag.setVR(EVR_OW);
432
0
        result = OFTrue;
433
0
    }
434
63.7k
    else if ((tag.getBaseTag() == DCM_RETIRED_CurveData) && (tag.getEVR() == EVR_ox))
435
0
    {
436
        /* case 4 (CurveData): see section A.1 in PS 3.5-2004 */
437
0
        DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of "
438
0
            << tag.getTagName() << " " << tag << " to 'OB'");
439
0
        tag.setVR(EVR_OB);
440
0
        result = OFTrue;
441
0
    }
442
    /* currently unhandled:
443
     * - LUTData (0028,3006), US or OW
444
     * - MappedPixelValue (0022,1452), US or SS
445
     * - RedPaletteColorLookupTableDescriptor (0028,1101), US or SS
446
     * - GreenPaletteColorLookupTableDescriptor (0028,1102), US or SS
447
     * - BluePaletteColorLookupTableDescriptor (0028,1103), US or SS
448
     * and some retired DICOM attributes as well as some DICONDE attributes
449
     */
450
63.7k
    return result;
451
63.7k
}
452
453
454
// ********************************
455
456
457
DcmEVR DcmItem::ident() const
458
55.9k
{
459
55.9k
    return EVR_item;
460
55.9k
}
461
462
463
unsigned long DcmItem::getVM()
464
0
{
465
0
    return 1;
466
0
}
467
468
469
unsigned long DcmItem::getNumberOfValues()
470
0
{
471
0
    return elementList->card();
472
0
}
473
474
475
unsigned long DcmItem::card() const
476
0
{
477
0
    return elementList->card();
478
0
}
479
480
481
// ********************************
482
483
484
void DcmItem::print(STD_NAMESPACE ostream &out,
485
                    const size_t flags,
486
                    const int level,
487
                    const char *pixelFileName,
488
                    size_t *pixelCounter)
489
0
{
490
0
    if (flags & DCMTypes::PF_showTreeStructure)
491
0
    {
492
        /* print item line with empty text */
493
0
        printInfoLine(out, flags, level);
494
        /* print item content */
495
0
        if (!elementList->empty())
496
0
        {
497
0
            DcmObject *dO;
498
0
            elementList->seek(ELP_first);
499
0
            do {
500
0
                dO = elementList->get();
501
0
                dO->print(out, flags, level + 1, pixelFileName, pixelCounter);
502
0
            } while (elementList->seek(ELP_next));
503
0
        }
504
0
    } else {
505
        /* print item start line */
506
0
        OFOStringStream oss;
507
0
        oss << "(Item with ";
508
0
        if (getLengthField() == DCM_UndefinedLength)
509
0
            oss << "undefined";
510
0
        else
511
0
            oss << "explicit";
512
0
        oss << " length #=" << card() << ")" << OFStringStream_ends;
513
0
        OFSTRINGSTREAM_GETSTR(oss, tmpString)
514
0
        printInfoLine(out, flags, level, tmpString);
515
0
        OFSTRINGSTREAM_FREESTR(tmpString)
516
        /* print item content */
517
0
        if (!elementList->empty())
518
0
        {
519
0
            DcmObject *dO;
520
0
            elementList->seek(ELP_first);
521
0
            do {
522
0
                dO = elementList->get();
523
0
                dO->print(out, flags, level + 1, pixelFileName, pixelCounter);
524
0
            } while (elementList->seek(ELP_next));
525
0
        }
526
        /* print item end line */
527
0
        DcmTag delimItemTag(DCM_ItemDelimitationItemTag);
528
0
        if (getLengthField() == DCM_UndefinedLength)
529
0
            printInfoLine(out, flags, level, "(ItemDelimitationItem)", &delimItemTag);
530
0
        else
531
0
            printInfoLine(out, flags, level, "(ItemDelimitationItem for re-encoding)", &delimItemTag);
532
0
    }
533
0
}
534
535
536
// ********************************
537
538
539
OFCondition DcmItem::writeXML(STD_NAMESPACE ostream &out,
540
                              const size_t flags)
541
0
{
542
0
    OFCondition l_error = EC_Normal;
543
0
    if (!(flags & DCMTypes::XF_useNativeModel))
544
0
    {
545
        /* XML start tag for "item" */
546
0
        out << "<item";
547
        /* cardinality (number of attributes) = 1..n */
548
0
        out << " card=\"" << card() << "\"";
549
        /* value length in bytes = 0..max (if not undefined) */
550
0
        if (getLengthField() != DCM_UndefinedLength)
551
0
            out << " len=\"" << getLengthField() << "\"";
552
0
        out << ">" << OFendl;
553
0
    }
554
    /* write item content */
555
0
    if (!elementList->empty())
556
0
    {
557
        /* write content of all children */
558
0
        DcmObject *dO;
559
0
        elementList->seek(ELP_first);
560
0
        do {
561
0
            dO = elementList->get();
562
0
            l_error = dO->writeXML(out, flags);
563
0
        } while (l_error.good() && elementList->seek(ELP_next));
564
0
    }
565
0
    if (l_error.good())
566
0
    {
567
0
        if (!(flags & DCMTypes::XF_useNativeModel))
568
0
        {
569
            /* XML end tag for "item" */
570
0
            out << "</item>" << OFendl;
571
0
        }
572
0
    }
573
0
    return l_error;
574
0
}
575
576
577
// ********************************
578
579
OFCondition DcmItem::writeJson(STD_NAMESPACE ostream &out,
580
                               DcmJsonFormat &format)
581
0
{
582
0
    return writeJsonExt(out, format, OFTrue, OFFalse);
583
0
}
584
585
586
OFCondition DcmItem::writeJsonExt(STD_NAMESPACE ostream &out,
587
                               DcmJsonFormat &format,
588
                                OFBool printBraces,
589
                                OFBool printNewline)
590
0
{
591
0
    size_t num_printed = 0;
592
0
    OFBool first = OFTrue;
593
0
    DcmObject *elem = NULL;
594
0
    OFCondition status = EC_Normal;
595
596
0
    if (!elementList->empty())
597
0
    {
598
        // iterate through all elements in this item
599
0
        elementList->seek(ELP_first);
600
0
        do
601
0
        {
602
            // get next item
603
0
            elem = elementList->get();
604
605
            // check if this is a group length, and if so, ignore
606
0
            if (elem->getTag().getElement() != 0)
607
0
            {
608
              // if this is the first element to be printed, print opening braces if needed
609
0
              if (first && printBraces) out << "{" << format.newline();
610
611
              // if this is not the first element to be printed, start with a comma
612
0
              if (!first) out << "," << format.newline();
613
614
              // print element
615
0
              status = elem->writeJson(out, format);
616
0
              first = OFFalse;
617
0
              num_printed++;
618
0
            }
619
0
        }
620
0
        while (status.good() && elementList->seek(ELP_next));
621
622
        // print closing braces if and only if there were opening braces
623
0
        if (num_printed > 0 && printBraces)
624
0
        {
625
0
            out << format.newline() << format.indent() << "}";
626
0
            if (printNewline) out << format.newline();
627
0
        }
628
0
    }
629
630
    // if no element was printed (item empty or only group list elements)
631
0
    if (num_printed == 0)
632
0
    {
633
0
        if (printBraces)
634
0
        {
635
            // print empty braces if requested
636
0
            out << "{}";
637
0
            if (printNewline) out << format.newline();
638
0
        }
639
0
    }
640
641
0
    return status;
642
643
0
}
644
645
646
// ********************************
647
648
649
OFBool DcmItem::canWriteXfer(const E_TransferSyntax newXfer,
650
                             const E_TransferSyntax oldXfer)
651
0
{
652
0
    OFBool canWrite = OFTrue;
653
0
    if (newXfer == EXS_Unknown)
654
0
        canWrite = OFFalse;
655
0
    else if (!elementList->empty())
656
0
    {
657
0
        DcmObject *dO;
658
0
        elementList->seek(ELP_first);
659
0
        do {
660
0
            dO = elementList->get();
661
0
            canWrite = dO->canWriteXfer(newXfer, oldXfer);
662
0
        } while (elementList->seek(ELP_next) && canWrite);
663
0
    }
664
0
    return canWrite;
665
0
}
666
667
668
// ********************************
669
670
671
Uint32 DcmItem::calcElementLength(const E_TransferSyntax xfer,
672
                                  const E_EncodingType enctype)
673
4.36k
{
674
4.36k
    Uint32 itemlen = 0;
675
4.36k
    DcmXfer xferSyn(xfer);
676
    /* Length of item's start header */
677
4.36k
    const Uint32 headersize = xferSyn.sizeofTagHeader(getVR());
678
    /* Length of item's content, i.e. contained elements */
679
4.36k
    itemlen = getLength(xfer, enctype);
680
    /* Since the item's total length can exceed the maximum length of 32 bit, it is
681
     * always necessary to check for overflows. The approach taken is not elegant
682
     * but should work...
683
     */
684
4.36k
    if ( (itemlen == DCM_UndefinedLength) || OFStandard::check32BitAddOverflow(itemlen, headersize) )
685
0
      return DCM_UndefinedLength;
686
4.36k
    itemlen += headersize;
687
4.36k
    if (enctype == EET_UndefinedLength) // add bytes for closing item tag marker if necessary
688
0
    {
689
0
      if (OFStandard::check32BitAddOverflow(itemlen, 8))
690
0
        return DCM_UndefinedLength;
691
0
      else
692
0
        itemlen += 8;
693
0
    }
694
4.36k
    return itemlen;
695
4.36k
}
696
697
698
// ********************************
699
700
701
Uint32 DcmItem::getLength(const E_TransferSyntax xfer,
702
                          const E_EncodingType enctype)
703
6.38k
{
704
6.38k
    Uint32 itemlen = 0;
705
6.38k
    Uint32 sublen = 0;
706
6.38k
    if (!elementList->empty())
707
5.10k
    {
708
5.10k
        DcmObject *dO;
709
5.10k
        elementList->seek(ELP_first);
710
24.5k
        do {
711
24.5k
            dO = elementList->get();
712
24.5k
            sublen = dO->calcElementLength(xfer, enctype);
713
            /* explicit length: be sure that total size of contained elements fits into item's
714
               32 Bit length field. If not, switch encoding automatically to undefined
715
               length for this item. Nevertheless, any contained elements will be
716
               written with explicit length if possible.
717
             */
718
24.5k
            if ( (enctype == EET_ExplicitLength) && OFStandard::check32BitAddOverflow(sublen, itemlen) )
719
0
            {
720
0
                if (dcmWriteOversizedSeqsAndItemsUndefined.get())
721
0
                {
722
0
                    DCMDATA_WARN("DcmItem: Explicit length of item exceeds 32-Bit length field, "
723
0
                        << "trying to encode with undefined length");
724
0
                }
725
0
                else
726
0
                {
727
0
                    DCMDATA_WARN("DcmItem: Explicit length of item exceeds 32-Bit length field, "
728
0
                        << "aborting write");
729
0
                    errorFlag = EC_SeqOrItemContentOverflow;
730
0
                }
731
0
                return DCM_UndefinedLength;
732
0
            }
733
24.5k
            else
734
24.5k
              itemlen += sublen;
735
24.5k
        } while (elementList->seek(ELP_next));
736
5.10k
    }
737
6.38k
    return itemlen;
738
6.38k
}
739
740
741
// ********************************
742
743
744
OFCondition DcmItem::computeGroupLengthAndPadding(const E_GrpLenEncoding glenc,
745
                                                  const E_PaddingEncoding padenc,
746
                                                  const E_TransferSyntax xfer,
747
                                                  const E_EncodingType enctype,
748
                                                  const Uint32 padlen,
749
                                                  const Uint32 subPadlen,
750
                                                  Uint32 instanceLength)
751
3.13k
{
752
    /* if certain conditions are met, this is considered to be an illegal call. */
753
3.13k
    if ((padenc == EPD_withPadding && (padlen % 2 || subPadlen % 2)) ||
754
3.13k
        ((glenc == EGL_recalcGL || glenc == EGL_withGL ||
755
3.13k
          padenc == EPD_withPadding) && xfer == EXS_Unknown))
756
0
        return EC_IllegalCall;
757
758
    /* if the caller specified that group length tags and padding */
759
    /* tags are not supposed to be changed, there is nothing to do. */
760
3.13k
    if (glenc == EGL_noChange && padenc == EPD_noChange)
761
3.13k
        return EC_Normal;
762
763
    /* if we get to this point, we need to do something. First of all, set the error indicator to normal. */
764
0
    OFCondition l_error = EC_Normal;
765
    /* collects group length elements that cannot be calculated due to length field overflows */
766
0
    OFList<DcmObject*> exceededGroupLengthElems;
767
768
    /* if there are elements in this item... */
769
0
    if (!elementList->empty())
770
0
    {
771
        /* initialize some variables */
772
0
        DcmObject *dO;
773
0
        OFBool beginning = OFTrue;
774
0
        Uint16 lastGrp = 0x0000;
775
0
        Uint16 actGrp;
776
0
        DcmUnsignedLong * actGLElem = NULL;
777
0
        DcmUnsignedLong * paddingGL = NULL;
778
0
        Uint32 grplen = 0;
779
0
        DcmXfer xferSyn(xfer);
780
0
        Uint32 sublen = 0;
781
0
        OFBool groupLengthExceeded = OFFalse;
782
783
        /* determine the current seek mode and set the list pointer to the first element */
784
0
        E_ListPos seekmode = ELP_next;
785
0
        elementList->seek(ELP_first);
786
787
        /* start a loop: we want to go through all elements as long as everything is okay */
788
0
        do
789
0
        {
790
            /* set the seek mode to "next" again, in case it has been modified in the last iteration */
791
0
            seekmode = ELP_next;
792
793
            /* get the current element and assign it to a local variable */
794
0
            dO = elementList->get();
795
796
            /* if the current element is a sequence, compute group length and padding for the sub sequence */
797
0
            if (dO->getVR() == EVR_SQ)
798
0
            {
799
                // add size of sequence header
800
0
                Uint32 templen = instanceLength + xferSyn.sizeofTagHeader(EVR_SQ);
801
                // call computeGroupLengthAndPadding for all contained items
802
0
                l_error = OFstatic_cast(DcmSequenceOfItems *, dO)->computeGroupLengthAndPadding
803
0
                    (glenc, padenc, xfer, enctype, subPadlen, subPadlen, templen);
804
0
            }
805
806
            /* if everything is ok so far */
807
0
            if (l_error.good())
808
0
            {
809
                /* in case one of the following two conditions is met */
810
                /*  (i) the caller specified that we want to add or remove group length elements and the current */
811
                /*      element's tag shows that it is a group length element (tag's element number equals 0x0000) */
812
                /*  (ii) the caller specified that we want to add or remove padding elements and the current */
813
                /*      element's tag shows that it is a padding element (tag is (0xfffc,0xfffc) */
814
                /* then we want to delete the current (group length or padding) element */
815
0
                if (((glenc ==  EGL_withGL || glenc == EGL_withoutGL) && dO->getETag() == 0x0000) ||
816
0
                    (padenc != EPD_noChange && dO->getTag() == DCM_DataSetTrailingPadding))
817
0
                {
818
0
                    delete elementList->remove();
819
0
                    seekmode = ELP_atpos; // remove advances 1 element forward -> make next seek() work
820
0
                    dO = NULL;
821
0
                }
822
                /* if the above mentioned conditions are not met but the caller specified that we want to add group */
823
                /* length tags for every group or that we want to recalculate values for existing group length tags */
824
0
                else  if (glenc == EGL_withGL || glenc == EGL_recalcGL)
825
0
                {
826
                    /* we need to determine the current element's group number */
827
0
                    actGrp = dO->getGTag();
828
829
                    /* and if the group number is different from the last remembered group number or */
830
                    /* if this id the very first element that is treated then we've found a new group */
831
0
                    if (actGrp != lastGrp || beginning) // new Group found
832
0
                    {
833
                        /* set beginning to false in order to specify that the */
834
                        /* very first element has already been treated */
835
0
                        beginning = OFFalse;
836
837
                        /* if the current element is a group length element and its data type */
838
                        /* is not UL replace this element with one that has a UL data type since */
839
                        /* group length elements are supposed to have this data type */
840
0
                        if (dO->getETag() == 0x0000 && dO->ident() != EVR_UL)
841
0
                        {
842
0
                            delete elementList->remove();
843
0
                            dO = new DcmUnsignedLong(DcmTag(actGrp, 0x0000, EVR_UL));
844
0
                            if (elementList->insert(dO, ELP_prev))
845
0
                            {
846
                                // remember the parent
847
0
                                dO->setParent(this);
848
0
                            }
849
0
                            DCMDATA_WARN("DcmItem: Group Length with VR other than UL found, corrected");
850
0
                        }
851
                        /* if the above mentioned condition is not met but the caller specified */
852
                        /* that we want to add group length elements, we need to add such an element */
853
0
                        else if (glenc == EGL_withGL)
854
0
                        {
855
                            // create GroupLength element
856
0
                            dO = new DcmUnsignedLong(DcmTag(actGrp, 0x0000, EVR_UL));
857
                            // insert new GroupLength element
858
0
                            if (elementList->insert(dO, ELP_prev))
859
0
                            {
860
                                // remember the parent
861
0
                                dO->setParent(this);
862
0
                            }
863
0
                        }
864
865
                        /* in case we want to add padding elements and the current element is a */
866
                        /* padding element we want to remember the padding element so that the */
867
                        /* group length of this element can be stored later */
868
0
                        if (padenc == EPD_withPadding && actGrp == 0xfffc)
869
0
                            paddingGL = OFstatic_cast(DcmUnsignedLong *, dO);
870
871
                        /* if actGLElem contains a valid pointer it was set in one of the last iterations */
872
                        /* to the group length element of the last group. We need to write the current computed */
873
                        /* group length value to this element. Exception: If group length exceeds maximum possible */
874
                        /* value, than remove group length element instead of setting it */
875
0
                        if (actGLElem != NULL)
876
0
                        {
877
0
                            if (!groupLengthExceeded)
878
0
                            {
879
                                // do not use putUint32() in order to make sure that the resulting VM is really 1
880
0
                                actGLElem->putUint32Array(&grplen, 1);
881
0
                                DCMDATA_DEBUG("DcmItem::computeGroupLengthAndPadding() Length of Group 0x"
882
0
                                    << STD_NAMESPACE hex << STD_NAMESPACE setfill('0')
883
0
                                    << STD_NAMESPACE setw(4) << actGLElem->getGTag()
884
0
                                    << STD_NAMESPACE dec << STD_NAMESPACE setfill(' ')
885
0
                                    << " len=" << grplen);
886
0
                            }
887
0
                            else
888
0
                            {
889
0
                                DCMDATA_WARN("DcmItem: Group length of group 0x"
890
0
                                    << STD_NAMESPACE hex << STD_NAMESPACE setfill('0')
891
0
                                    << STD_NAMESPACE setw(4) << actGLElem->getGTag()
892
0
                                    << " exceeds 32-Bit length field. "
893
0
                                    << "Cannot calculate/write group length for this group.");
894
0
                                exceededGroupLengthElems.push_back(actGLElem);
895
0
                                groupLengthExceeded = OFFalse;
896
0
                            }
897
0
                        }
898
899
                        /* set the group length value to 0 since it is the beginning of the new group */
900
0
                        grplen = 0;
901
902
                        /* if the current element is a group length element, remember its address for later */
903
                        /* (we need to assign the group length value to this element in a subsequent iteration) */
904
                        /* in case the current element (at the beginning of the group) is not a group length */
905
                        /* element, set the actGLElem pointer to NULL. */
906
0
                        if (dO->getETag() == 0x0000)
907
0
                            actGLElem = OFstatic_cast(DcmUnsignedLong *, dO);
908
0
                        else
909
0
                            actGLElem = NULL;
910
0
                    }
911
                    /* if this is not a new group, calculate the element's length and add it */
912
                    /* to the currently computed group length value. If group length is larger */
913
                    /* than group length field permits, set flag to not add group length for this group */
914
0
                    else
915
0
                    {
916
0
                        sublen = dO->calcElementLength(xfer, enctype);
917
                        // test for 32-bit overflow return value
918
0
                        if ((sublen == DCM_UndefinedLength) || OFStandard::check32BitAddOverflow(sublen, grplen))
919
0
                        {
920
0
                            groupLengthExceeded = OFTrue;
921
0
                        }
922
0
                        else
923
0
                        {
924
0
                            grplen += sublen;
925
0
                        }
926
0
                    }
927
928
                    /* remember the current element's group number so that it is possible to */
929
                    /* figure out if a new group is treated in the following iteration */
930
0
                    lastGrp = actGrp;
931
0
                }
932
0
            }
933
0
        } while (l_error.good() && elementList->seek(seekmode));
934
935
        /* if there was no error and the caller specified that we want to add or recalculate */
936
        /* group length tags and if actGLElem has a valid value, we need to add the above */
937
        /* computed group length value to the last group's group length element. Exception: */
938
        /* If group length exceeds maximum possible value, remove group length element and */
939
        /* i.e. do not write it for this group. */
940
0
        if (l_error.good() && (glenc == EGL_withGL || glenc == EGL_recalcGL) && actGLElem)
941
0
        {
942
0
            if (groupLengthExceeded)
943
0
            {
944
0
                exceededGroupLengthElems.push_back(actGLElem);
945
0
            }
946
0
            else
947
0
            {
948
0
                actGLElem->putUint32(grplen);
949
0
            }
950
0
        }
951
952
        /* if the caller specified that we want to add padding elements and */
953
        /* if the length up to which shall be padded does not equal 0 we might */
954
        /* have to add a padding element */
955
0
        if (padenc == EPD_withPadding && padlen)
956
0
        {
957
            /* calculate how much space the entire padding element is supposed to occupy */
958
0
            Uint32 padding;
959
0
            if (ident() == EVR_dataset)
960
0
            {
961
0
                instanceLength += calcElementLength(xfer, enctype);
962
0
                padding = padlen - (instanceLength % padlen);
963
0
            } else
964
0
                padding = padlen - (getLength(xfer, enctype) % padlen);
965
966
            /* if now padding does not equal padlen we need to create a padding element. (if both values are equal */
967
            /* the element does have the exact required padlen length and does not need a padding element.) */
968
0
            if (padding != padlen)
969
0
            {
970
                /* Create new padding element */
971
0
                DcmOtherByteOtherWord * paddingEl = new DcmOtherByteOtherWord(DCM_DataSetTrailingPadding);
972
973
                /* calculate the length of the new element */
974
0
                Uint32 tmplen = paddingEl->calcElementLength(xfer, enctype);
975
976
                /* in case padding is smaller than the header of the padding element, we */
977
                /* need to increase padding (the value which specifies how much space the */
978
                /* entire padding element is supposed to occupy) until it is no longer smaller */
979
0
                while (tmplen > padding)
980
0
                    padding += padlen;
981
982
                /* determine the amount of bytes that have to be added to the */
983
                /* padding element so that it has the correct size */
984
0
                padding -= tmplen;
985
986
                /* create an array of a corresponding size and set the array fields */
987
0
                Uint8 * padBytes = new Uint8[padding];
988
0
                memset(padBytes, 0, size_t(padding));
989
990
                /* set information in the above created padding element (size and actual value) */
991
0
                paddingEl->putUint8Array(padBytes, padding);
992
993
                /* delete the above created array */
994
0
                delete[] padBytes;
995
996
                /* insert the padding element into this */
997
0
                insert(paddingEl);
998
999
                /* finally we need to update the group length for the padding element if it exists */
1000
0
                if (paddingGL)
1001
0
                {
1002
0
                    Uint32 len;
1003
0
                    paddingGL->getUint32(len);
1004
0
                    len += paddingEl->calcElementLength(xfer, enctype);
1005
0
                    paddingGL->putUint32(len);
1006
0
                }
1007
0
            }
1008
0
        }
1009
0
    }
1010
    /* delete invalid group length elements from item. Cannot be done in */
1011
    /* above while loop because then elementList iterator is invalidated */
1012
0
    const size_t numElems = exceededGroupLengthElems.size();
1013
0
    for (size_t i = 0; i < numElems; i++)
1014
0
    {
1015
0
        delete remove(exceededGroupLengthElems.front());
1016
0
        exceededGroupLengthElems.pop_front();
1017
0
    }
1018
1019
0
    return l_error;
1020
3.13k
}
1021
1022
1023
// ********************************
1024
1025
1026
OFCondition DcmItem::readTagAndLength(DcmInputStream &inStream,
1027
                                      const E_TransferSyntax xfer,
1028
                                      DcmTag &tag,
1029
                                      Uint32 &length,
1030
                                      Uint32 &bytesRead)
1031
310k
{
1032
310k
    OFCondition l_error = EC_Normal;
1033
310k
    Uint32 valueLength = 0;
1034
310k
    Uint16 groupTag = 0xffff;
1035
310k
    Uint16 elementTag = 0xffff;
1036
1037
    /* create a DcmXfer object based on the transfer syntax which was passed */
1038
310k
    DcmXfer xferSyn(xfer);
1039
1040
#ifdef DEBUG
1041
    /* dump some information if required */
1042
    DCMDATA_TRACE("DcmItem::readTagAndLength() TransferSyntax=\"" << xferSyn.getXferName() << "\"");
1043
#endif
1044
1045
    /* bail out if at end of stream */
1046
310k
    if (inStream.eos())
1047
3.54k
        return EC_EndOfStream;
1048
1049
    /* check if either 4 (for implicit transfer syntaxes) or 6 (for explicit transfer */
1050
    /* syntaxes) bytes are available in (i.e. can be read from) inStream. if an error */
1051
    /* occurred while performing this check return this error */
1052
306k
    if (inStream.avail() < OFstatic_cast(offile_off_t, xferSyn.isExplicitVR() ? 6 : 4))
1053
914
        return EC_StreamNotifyClient;
1054
1055
    /* determine the byte ordering of the transfer syntax which was passed; */
1056
    /* if the byte ordering is unknown, this is an illegal call. */
1057
305k
    const E_ByteOrder byteOrder = xferSyn.getByteOrder();
1058
305k
    if (byteOrder == EBO_unknown)
1059
0
        return EC_IllegalCall;
1060
1061
    /* read tag information (4 bytes) from inStream and create a corresponding DcmTag object */
1062
305k
    inStream.mark();
1063
305k
    inStream.read(&groupTag, 2);
1064
305k
    inStream.read(&elementTag, 2);
1065
305k
    swapIfNecessary(gLocalByteOrder, byteOrder, &groupTag, 2, 2);
1066
305k
    swapIfNecessary(gLocalByteOrder, byteOrder, &elementTag, 2, 2);
1067
    // tag has been read
1068
305k
    bytesRead = 4;
1069
305k
    OFString readVR;
1070
305k
    DcmTag newTag(groupTag, elementTag);
1071
305k
    DcmEVR newEVR = newTag.getEVR();
1072
    // check whether tag is private
1073
305k
    const OFBool isPrivate = groupTag & 1;
1074
1075
    /* if the transfer syntax which was passed is an explicit VR syntax and if the current */
1076
    /* item is not a delimitation item (note that delimitation items do not have a VR), go */
1077
    /* ahead and read 2 bytes from inStream. These 2 bytes contain this item's VR value. */
1078
305k
    if (xferSyn.isExplicitVR() && (newEVR != EVR_na))
1079
237k
    {
1080
237k
        char vrstr[3];
1081
237k
        vrstr[2] = '\0';
1082
1083
        /* read 2 bytes */
1084
237k
        inStream.read(vrstr, 2);
1085
237k
        readVR = vrstr;
1086
1087
        /* create a corresponding DcmVR object */
1088
237k
        DcmVR vr(vrstr);
1089
1090
        /* if the VR which was read is not a standard VR (e.g. invalid), print a warning */
1091
237k
        if (!vr.isStandard())
1092
75.5k
        {
1093
75.5k
            OFOStringStream oss;
1094
75.5k
            oss << "DcmItem: " << (vr.isInvalid() ? "Invalid" : "Non-standard") << " VR '"
1095
75.5k
                << ((OFstatic_cast(unsigned char, vrstr[0]) < 32 || OFstatic_cast(unsigned char, vrstr[0]) > 127) ? ' ' : vrstr[0])
1096
75.5k
                << ((OFstatic_cast(unsigned char, vrstr[1]) < 32 || OFstatic_cast(unsigned char, vrstr[1]) > 127) ? ' ' : vrstr[1]) << "' ("
1097
75.5k
                << STD_NAMESPACE hex << STD_NAMESPACE setfill('0')
1098
75.5k
                << STD_NAMESPACE setw(2) << OFstatic_cast(unsigned int, vrstr[0] & 0xff) << "\\"
1099
75.5k
                << STD_NAMESPACE setw(2) << OFstatic_cast(unsigned int, vrstr[1] & 0xff)
1100
75.5k
                << ") encountered while parsing element " << newTag << OFStringStream_ends;
1101
75.5k
            OFSTRINGSTREAM_GETSTR(oss, tmpString)
1102
            /* encoding of this data element might be wrong, try to correct it */
1103
75.5k
            if (dcmAcceptUnexpectedImplicitEncoding.get())
1104
0
            {
1105
0
                DCMDATA_WARN(tmpString << ", trying again with Implicit VR Little Endian");
1106
                /* put back read bytes to input stream ... */
1107
0
                inStream.putback();
1108
0
                bytesRead = 0;
1109
                /* ... and retry with Implicit VR Little Endian transfer syntax */
1110
0
                return readTagAndLength(inStream, EXS_LittleEndianImplicit, tag, length, bytesRead);
1111
75.5k
            } else {
1112
75.5k
                DCMDATA_WARN(tmpString << ", assuming " << (vr.usesExtendedLengthEncoding() ? "4" : "2")
1113
75.5k
                    << " byte length field");
1114
75.5k
            }
1115
75.5k
            OFSTRINGSTREAM_FREESTR(tmpString)
1116
1117
            /* workaround: handle known issue with non-standard VR "OX" for PixelData element */
1118
75.5k
            if ((newTag == DCM_PixelData) && (strncmp(vrstr, "OX", 2) == 0))
1119
1.94k
            {
1120
1.94k
                DCMDATA_WARN("DcmItem: Non-standard VR 'OX' is known to be wrongly used for PixelData " << newTag
1121
1.94k
                    << ", setting VR to 'OW'");
1122
1.94k
                vr.setVR(EVR_OW);
1123
1.94k
            }
1124
75.5k
        }
1125
1126
        /* the VR in the dataset might be wrong, so the user can decide to ignore it */
1127
237k
        if (dcmPreferVRFromDataDictionary.get() && (newEVR != EVR_UNKNOWN) && (newEVR != EVR_UNKNOWN2B))
1128
0
        {
1129
            /* resolve ambiguous VRs, e.g. map the internal "ox" to either "OB" or "OW" */
1130
0
            if (checkAndUpdateVR(*this, newTag))
1131
0
                newEVR = newTag.getEVR();
1132
1133
0
            if (newEVR != vr.getEVR())
1134
0
            {
1135
                /* ignore explicit VR in dataset if tag is defined in data dictionary */
1136
0
                DCMDATA_DEBUG("DcmItem::readTagAndLength() ignoring explicit VR in data set ("
1137
0
                    << vr.getVRName() << ") for element " << newTag
1138
0
                    << ", using the one from data dictionary (" << newTag.getVRName() << ")");
1139
0
            }
1140
237k
        } else {
1141
            /* set the VR which was read in the above created tag object */
1142
237k
            newTag.setVR(vr);
1143
237k
        }
1144
1145
237k
        if (!dcmPreferLengthFieldSizeFromDataDictionary.get() || newEVR == EVR_UNKNOWN || newEVR == EVR_UNKNOWN2B) {
1146
            /* determine VR read from dataset, because this VR specifies the number of bytes for the length-field */
1147
237k
            newEVR = vr.getEVR();
1148
237k
        } else {
1149
            /* use the VR from the dictionary for deciding the length of the length field */
1150
0
        }
1151
1152
        /* increase counter by 2 */
1153
237k
        bytesRead += 2;
1154
237k
    }
1155
1156
    /* special handling for private elements */
1157
305k
    if (isPrivate && (newTag.getElement() >= 0x1000))
1158
61.7k
    {
1159
61.7k
        const char *pc = privateCreatorCache.findPrivateCreator(newTag);
1160
61.7k
        if (pc)
1161
5.27k
        {
1162
            // we have a private creator for this element
1163
5.27k
            newTag.setPrivateCreator(pc);
1164
1165
5.27k
            if (xferSyn.isImplicitVR())
1166
0
            {
1167
                // try to update VR from dictionary now that private creator is known
1168
0
                newTag.lookupVRinDictionary();
1169
                // also update the VR
1170
0
                newEVR = newTag.getEVR();
1171
0
            }
1172
5.27k
        }
1173
61.7k
    }
1174
1175
    /* the next thing we want to do is read the value in the length field from inStream. */
1176
    /* determine if there is a corresponding amount of bytes (for the length field) still */
1177
    /* available in inStream. If not, return an error. */
1178
305k
    if (inStream.avail() < OFstatic_cast(offile_off_t, xferSyn.sizeofTagHeader(newEVR) - bytesRead))
1179
664
    {
1180
664
        inStream.putback();    // the UnsetPutbackMark is in readSubElement
1181
664
        bytesRead = 0;
1182
664
        l_error = EC_StreamNotifyClient;
1183
664
        return l_error;
1184
664
    }
1185
1186
    /* read the value in the length field. In some cases, it is 4 bytes wide, in other */
1187
    /* cases only 2 bytes (see DICOM standard part 5, section 7.1.1) */
1188
304k
    if (xferSyn.isImplicitVR() || newEVR == EVR_na) // note that delimitation items don't have a VR
1189
68.0k
    {
1190
68.0k
        inStream.read(&valueLength, 4);            // length field is 4 bytes wide
1191
68.0k
        swapIfNecessary(gLocalByteOrder, byteOrder, &valueLength, 4, 4);
1192
68.0k
        bytesRead += 4;
1193
236k
    } else {                                       // the transfer syntax is explicit VR
1194
236k
        DcmVR vr(newEVR);
1195
236k
        if (vr.usesExtendedLengthEncoding())
1196
54.5k
        {
1197
54.5k
            Uint16 reserved;
1198
54.5k
            inStream.read(&reserved, 2);           // 2 reserved bytes
1199
54.5k
            inStream.read(&valueLength, 4);        // length field is 4 bytes wide
1200
54.5k
            swapIfNecessary(gLocalByteOrder, byteOrder, &valueLength, 4, 4);
1201
54.5k
            bytesRead += 6;
1202
182k
        } else {
1203
182k
            Uint16 tmpValueLength;
1204
182k
            inStream.read(&tmpValueLength, 2);     // length field is 2 bytes wide
1205
182k
            swapIfNecessary(gLocalByteOrder, byteOrder, &tmpValueLength, 2, 2);
1206
182k
            bytesRead += 2;
1207
182k
            valueLength = tmpValueLength;
1208
182k
        }
1209
        /* check whether value in length field is appropriate for this VR */
1210
236k
        const size_t vrSize = vr.getValueWidth();
1211
236k
        if ((vrSize > 1) && (valueLength % vrSize != 0))
1212
11.7k
        {
1213
            /* warning is only reported for standard, fixed-size VRs that require more than 1 byte per value */
1214
11.7k
            if (valueLength == DCM_UndefinedLength)
1215
3.25k
            {
1216
                /* check whether the VR supports undefined length for the length field */
1217
3.25k
                if (!vr.supportsUndefinedLength())
1218
8
                {
1219
8
                    DCMDATA_WARN("DcmItem: Dubious use of undefined length for element " << newTag
1220
8
                        << " with VR=" << vr.getVRName());
1221
8
                }
1222
8.54k
            } else {
1223
8.54k
                DCMDATA_WARN("DcmItem: Length of element " << newTag << " is not a multiple of " << vrSize
1224
8.54k
                    << " (VR=" << vr.getVRName() << ")");
1225
8.54k
            }
1226
11.7k
        }
1227
236k
    }
1228
    /* check whether the correct VR is used for PixelData element in encapsulated format */
1229
304k
    if ((newTag == DCM_PixelData) && xferSyn.usesEncapsulatedFormat() &&
1230
2.65k
        (valueLength == DCM_UndefinedLength) && (readVR != "OB") /* this is the VR that was read */)
1231
1.24k
    {
1232
1.24k
        DCMDATA_WARN("DcmItem: Wrong VR for encapsulated PixelData " << newTag
1233
1.24k
            << ", should be 'OB' instead of '" << readVR << "'");
1234
1.24k
    }
1235
1236
    /* if the value in the length field is odd, print an error message */
1237
304k
    if ((valueLength & 1) && (valueLength != DCM_UndefinedLength))
1238
61.6k
    {
1239
61.6k
        DCMDATA_WARN("DcmItem: Length of element " << newTag << " is odd");
1240
61.6k
    }
1241
1242
    /* if desired, handle private attributes with maximum length as VR SQ */
1243
304k
    if (isPrivate && dcmReadImplPrivAttribMaxLengthAsSQ.get() && (valueLength == DCM_UndefinedLength))
1244
0
    {
1245
        /* re-set tag to be a sequence and also delete private creator cache */
1246
0
        newTag.setVR(EVR_SQ);
1247
0
        newTag.setPrivateCreator("");
1248
0
    }
1249
1250
    /* if desired, check if length is greater than length of surrounding item */
1251
304k
    const Uint32 valueLengthItem = getLengthField();
1252
304k
    if ((ident() == EVR_item /* e.g. meta info would have length 0 */) &&
1253
55.9k
        (valueLengthItem != DCM_UndefinedLength /* this does not work in undefined length items */) &&
1254
53.7k
        (valueLength != DCM_UndefinedLength) /* Also, do not check sequences with undefined length 0xFFFFFFFF */
1255
304k
       )
1256
50.6k
    {
1257
50.6k
        const offile_off_t remainingItemBytes = valueLengthItem - (inStream.tell() - fStartPosition);
1258
        /* is the explicit item length too small to cover the full value of the element value length to be read? */
1259
50.6k
        if (remainingItemBytes < 0)
1260
2.66k
        {
1261
2.66k
            DCMDATA_WARN("DcmItem: Explicit item length (" << valueLengthItem << " bytes) too large for the elements contained in the item");
1262
            /* if the next tag is the sequence delimiter item, we can adapt to the situation */
1263
2.66k
            if (newTag == DCM_SequenceDelimitationItem)
1264
5
            {
1265
5
                DCMDATA_WARN("DcmItem: Sequence delimitation occurred before all bytes announced by explicit item length could be read");
1266
5
                l_error = EC_PrematureSequDelimitationItem;
1267
                /* rewind to start of sequence delimiter which is read in a regular way */
1268
                /* by DcmSequenceOfItems later (if error is ignored in DcmItem::read()) */
1269
5
                inStream.putback();
1270
5
            }
1271
2.66k
        }
1272
47.9k
        else if (OFstatic_cast(offile_off_t, valueLength) > remainingItemBytes)
1273
126
        {
1274
126
            DCMDATA_WARN("DcmItem: Element " << newTag.getTagName() << " " << newTag
1275
126
                << " larger (" << valueLength << ") than remaining bytes ("
1276
                /* need to cast remainingItemBytes to unsigned long because VC6 cannot print offile_off_t (int64_t). */
1277
126
                << OFstatic_cast(unsigned long, remainingItemBytes) << ") of surrounding item");
1278
126
            l_error = EC_ElemLengthLargerThanItem;
1279
126
        }
1280
50.6k
    }
1281
1282
    /* assign values to out parameter */
1283
304k
    length = valueLength;
1284
304k
    tag = newTag;
1285
1286
    /* return return value */
1287
304k
    return l_error;
1288
305k
}
1289
1290
1291
// ********************************
1292
1293
1294
OFBool DcmItem::isLastElementIncomplete()
1295
6.56k
{
1296
    /* if the last element was read completely, nothing is pending */
1297
6.56k
    if (lastElementComplete)
1298
5.18k
        return OFFalse;
1299
    /* lastElementComplete is also OFFalse for an element with a value length of
1300
     * zero that was read at the very end of the stream, although the value of
1301
     * such an element is complete. Only an element whose value was partially
1302
     * read has reached state ERW_inWork.
1303
     */
1304
1.37k
    DcmObject *dO = elementList->get();
1305
1.37k
    return (dO != NULL) && (dO->transferState() == ERW_inWork);
1306
6.56k
}
1307
1308
1309
// ********************************
1310
1311
1312
OFCondition DcmItem::readSubElement(DcmInputStream &inStream,
1313
                                    DcmTag &newTag,
1314
                                    const Uint32 newLength,
1315
                                    const E_TransferSyntax xfer,
1316
                                    const E_GrpLenEncoding glenc,
1317
                                    const Uint32 maxReadLength)
1318
304k
{
1319
304k
    DcmElement *subElem = NULL;
1320
1321
    /* create a new DcmElement* object with corresponding tag and */
1322
    /* length; the object will be accessible through subElem */
1323
304k
    OFBool readAsUN = OFFalse;
1324
304k
    OFCondition l_error = DcmItem::newDicomElement(subElem, newTag, newLength, &privateCreatorCache, readAsUN);
1325
1326
    /* if no error occurred and subElem does not equal NULL, go ahead */
1327
304k
    if (l_error.good() && subElem != NULL)
1328
301k
    {
1329
        // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture
1330
1331
        /* insert the new element into the (sorted) element list and */
1332
        /* assign information which was read from the inStream to it */
1333
301k
        subElem->transferInit();
1334
        /* we need to read the content of the attribute, no matter if */
1335
        /* inserting the attribute succeeds or fails */
1336
301k
        l_error = subElem->read(inStream, (readAsUN ? EXS_LittleEndianImplicit : xfer), glenc, maxReadLength);
1337
        // try to insert element into item. Note that
1338
        // "elementList->insert(subElem, ELP_next)" would be faster,
1339
        // but this is better since this insert-function creates a
1340
        // sorted element list.
1341
        // We insert the element even if subElem->read() reported an error
1342
        // because otherwise I/O suspension would fail.
1343
301k
        OFCondition temp_error = insert(subElem, OFFalse, OFTrue);
1344
1345
301k
        if (temp_error.bad())
1346
188k
        {
1347
            // produce diagnostics
1348
188k
            DCMDATA_WARN("DcmItem: Element " << newTag
1349
188k
                << " found twice in one data set or item, ignoring second entry");
1350
188k
            delete subElem;
1351
188k
        }
1352
301k
    }
1353
    /* else if an error occurred, try to recover from this error */
1354
3.40k
    else if (l_error == EC_InvalidTag)
1355
183
    {
1356
        /* This is the second putback operation on the putback mark in */
1357
        /* readTagAndLength but it is impossible that both can be executed */
1358
        /* without setting the Mark twice. */
1359
183
        inStream.putback();
1360
183
        DCMDATA_WARN("DcmItem: Parse error while parsing element " << newTag);
1361
183
    }
1362
3.22k
    else if (l_error == EC_UndefinedLengthOBOW)
1363
22
    {
1364
        // do nothing
1365
22
    }
1366
3.20k
    else if (l_error == EC_VOI_LUT_OBOW)
1367
88
    {
1368
        // do nothing
1369
88
    }
1370
3.11k
    else if (l_error != EC_ItemEnd)
1371
461
    {
1372
        // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture
1373
1374
        // dump some information if required
1375
461
        if (dcmIgnoreParsingErrors.get() || (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_SequEnd)))
1376
0
        {
1377
0
            DCMDATA_WARN("DcmItem: Parse error in sequence item, found " << newTag
1378
0
                << " instead of item delimiter " << DCM_ItemDelimitationItem);
1379
461
        } else {
1380
461
            DCMDATA_ERROR("DcmItem: Parse error in sequence item, found " << newTag
1381
461
                << " instead of item delimiter " << DCM_ItemDelimitationItem);
1382
461
        }
1383
        // some systems use the wrong delimitation item at the end of a sequence
1384
461
        if (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_SequEnd))
1385
0
        {
1386
0
            DCMDATA_DEBUG("DcmItem::readSubItem() replacing wrong sequence delimiter "
1387
0
                << DCM_SequenceDelimitationItem << " by item delimiter "
1388
0
                << DCM_ItemDelimitationItem << " because it is expected here");
1389
0
            l_error = EC_ItemEnd;
1390
461
        } else {
1391
461
            DCMDATA_DEBUG("DcmItem::readSubElement() cannot create Sub Element " << newTag);
1392
            // treat this incorrect encoding as an error
1393
461
            if (!dcmIgnoreParsingErrors.get())
1394
461
                l_error = EC_ItemDelimitationItemMissing;
1395
461
        }
1396
2.65k
    } else {
1397
        // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture
1398
2.65k
    }
1399
1400
    /* dump some information if required */
1401
304k
    DCMDATA_TRACE("DcmItem::readSubItem() returns error = " << l_error.text());
1402
    /* return result value */
1403
304k
    return l_error;
1404
304k
}
1405
1406
1407
// ********************************
1408
1409
1410
OFCondition DcmItem::read(DcmInputStream & inStream,
1411
                          const E_TransferSyntax xfer,
1412
                          const E_GrpLenEncoding glenc,
1413
                          const Uint32 maxReadLength)
1414
116k
{
1415
116k
    return DcmItem::readUntilTag(inStream, xfer, glenc, maxReadLength, DCM_UndefinedTagKey);
1416
116k
}
1417
1418
OFCondition DcmItem::readUntilTag(DcmInputStream & inStream,
1419
                                  const E_TransferSyntax xfer,
1420
                                  const E_GrpLenEncoding glenc,
1421
                                  const Uint32 maxReadLength,
1422
                                  const DcmTagKey &stopParsingAtElement)
1423
126k
{
1424
    /* check if this is an illegal call; if so set the error flag and do nothing, else go ahead */
1425
126k
    if (getTransferState() == ERW_notInitialized)
1426
0
    {
1427
0
        errorFlag = EC_IllegalCall;
1428
0
        return errorFlag;
1429
0
    }
1430
1431
    /* apply configured nesting depth limit to the input stream (0 = use default, skip override) */
1432
126k
    if (getMaxNestingDepth() != 0)
1433
0
        inStream.setMaxNestingDepth(getMaxNestingDepth());
1434
1435
    /* apply configured element length limit to the input stream (0 = use default, skip override) */
1436
126k
    if (getMaxElementLength() != 0)
1437
0
        inStream.setMaxElementLength(getMaxElementLength());
1438
1439
    /* apply configured incremental load threshold to the input stream (0 = use default, skip override) */
1440
126k
    if (getIncrementalLoadThreshold() != 0)
1441
0
        inStream.setIncrementalLoadThreshold(getIncrementalLoadThreshold());
1442
1443
    /* figure out if the stream reported an error */
1444
126k
    errorFlag = inStream.status();
1445
    /* if the stream reported an error or if it is the end of the */
1446
    /* stream, set the error flag correspondingly; else go ahead */
1447
126k
    if (errorFlag.good() && inStream.eos())
1448
160
        errorFlag = EC_EndOfStream;
1449
125k
    else if (errorFlag.good() && getTransferState() != ERW_ready)
1450
125k
    {
1451
        /* if the transfer state of this item is ERW_init, get its start */
1452
        /* position in the stream and set the transfer state to ERW_inWork */
1453
125k
        if (getTransferState() == ERW_init)
1454
125k
        {
1455
125k
            fStartPosition = inStream.tell();  // start position of this item
1456
125k
            setTransferState(ERW_inWork);
1457
125k
        }
1458
125k
        DcmTag newTag;
1459
125k
        OFBool readStopElem = OFFalse;
1460
        /* start a loop in order to read all elements (attributes) which are contained in the inStream */
1461
404k
        while (inStream.good() && (getTransferredBytes() < getLengthField() || !lastElementComplete) && !readStopElem)
1462
300k
        {
1463
            /* initialize variables */
1464
300k
            Uint32 newValueLength = 0;
1465
300k
            Uint32 bytes_tagAndLen = 0;
1466
            /* if the reading of the last element was complete, go ahead and read the next element */
1467
300k
            if (lastElementComplete)
1468
300k
            {
1469
                /* read this element's tag and length information */
1470
                /* (and possibly also VR information) from the inStream */
1471
300k
                errorFlag = readTagAndLength(inStream, xfer, newTag, newValueLength, bytes_tagAndLen);
1472
                /* increase counter correspondingly */
1473
300k
                incTransferredBytes(bytes_tagAndLen);
1474
1475
                /* if desired, try to ignore parse error -> skip item */
1476
300k
                if ((errorFlag == EC_ElemLengthLargerThanItem) && dcmIgnoreParsingErrors.get())
1477
0
                {
1478
0
                    DCMDATA_WARN("DcmItem: Element " << newTag.getTagName() << " " << newTag
1479
0
                        << " too large, trying to skip over rest of item");
1480
                    /* we can call getLengthField because error does only occur for explicit length items */
1481
0
                    const offile_off_t bytesToSkip = getLengthField() - bytes_tagAndLen;
1482
0
                    if (bytesToSkip > inStream.avail()) // no chance to recover
1483
0
                       break;
1484
0
                    inStream.skip(bytesToSkip);
1485
0
                    errorFlag = EC_Normal;
1486
0
                }
1487
                /* if desired, accept premature sequence delimitation item and continue as if item has been completely read. */
1488
                /* The stream position has been rewound to the start position of the sequence end */
1489
                /* delimiter tag in order to let DcmSequenceOfItems handle the delimiter in the reading routine. */
1490
300k
                else if ((errorFlag == EC_PrematureSequDelimitationItem) && dcmIgnoreParsingErrors.get())
1491
0
                {
1492
0
                     DCMDATA_WARN("DcmItem: Sequence delimitation occurred before all bytes announced by explicit item length could be read"
1493
0
                         << ", trying to continue as if item was completely read");
1494
0
                    errorFlag = EC_ItemEnd;  // make sure that error code leads to normal return from item reading loop
1495
0
                    break; // we are completed with the item since sequence is closed
1496
0
                }
1497
300k
                else /* continue with normal case: parse rest of element */
1498
300k
                {
1499
                    /* if there was an error while we were reading from the stream, terminate the while-loop */
1500
                    /* (note that if the last element had been read from the inStream in the last iteration, */
1501
                    /* another iteration will be started, and of course then readTagAndLength(...) above will */
1502
                    /* return that it encountered the end of the stream. It is only then (and here) when the */
1503
                    /* while loop will be terminated.) */
1504
300k
                    if (errorFlag.bad())
1505
5.06k
                        break;
1506
                    /* If we get to this point, we just started reading the first part */
1507
                    /* of an element; hence, lastElementComplete is not longer true */
1508
295k
                    lastElementComplete = OFFalse;
1509
                    /* in case of implicit VR, check whether the "default VR" is really appropriate */
1510
295k
                    if (DcmXfer(xfer).isImplicitVR())
1511
63.7k
                        checkAndUpdateVR(*this, newTag);
1512
1513
                    /* check if we want to stop parsing at this point, in the main dataset only */
1514
295k
                    if ((stopParsingAtElement != DCM_UndefinedTagKey) && (newTag >= stopParsingAtElement) && (ident() == EVR_dataset))
1515
0
                    {
1516
0
                        lastElementComplete = OFTrue;
1517
0
                        readStopElem = OFTrue;
1518
0
                        DCMDATA_DEBUG("DcmItem: Element " << newTag.getTagName() << " " << newTag
1519
0
                            << " encountered, skipping rest of dataset (as requested)");
1520
0
                    }
1521
295k
                    else
1522
295k
                    {
1523
                        /* read the actual data value which belongs to this element */
1524
                        /* (attribute) and insert this information into the elementList */
1525
295k
                        errorFlag = readSubElement(inStream, newTag, newValueLength, xfer, glenc, maxReadLength);
1526
                        /* if reading was successful, we read the entire data value information */
1527
                        /* for this element; hence lastElementComplete is true again */
1528
295k
                        if (errorFlag.good())
1529
278k
                            lastElementComplete = OFTrue;
1530
1531
                        /* in data or command sets, group 0x0001 to 0x0003, 0x0005, 0x0007 and 0xFFFF are not allowed. */
1532
                        /* (we cannot check for group 0x0000 since we do not know whether we read a data or command set.)*/
1533
295k
                        if (!newTag.hasValidGroup() || (newTag.getGroup() == 0x0002))
1534
295k
                            DCMDATA_WARN("DcmItem: Invalid Element " << newTag << " found in data set");
1535
295k
                    }
1536
295k
                }
1537
300k
            } else {
1538
                /* if lastElementComplete is false, we have only read the current element's */
1539
                /* tag and length (and possibly VR) information as well as maybe some data */
1540
                /* data value information. We need to continue reading the data value */
1541
                /* information for this particular element. */
1542
0
                DcmObject *dO = elementList->get();
1543
0
                if (dO == NULL)
1544
0
                    errorFlag = EC_InternalError; // should never happen
1545
0
                else if (dO->transferState() == ERW_ready)
1546
0
                {
1547
                    /* the list cursor points to an element that has already been   */
1548
                    /* read completely, e.g. because the element whose value is     */
1549
                    /* still missing was inserted out of ascending tag order or was */
1550
                    /* dropped as a duplicate. Reading on would parse the remaining */
1551
                    /* value bytes as new elements and leave the incomplete element */
1552
                    /* with a partly filled value, so report an error instead.      */
1553
0
                    DCMDATA_ERROR("DcmItem: Cannot continue reading the value of element "
1554
0
                        << dO->getTag() << ", data set is inconsistent");
1555
0
                    errorFlag = EC_InvalidStream;
1556
0
                }
1557
0
                else
1558
0
                    errorFlag = dO->read(inStream, xfer, glenc, maxReadLength);
1559
1560
                /* if reading was successful, we read the entire information */
1561
                /* for this element; hence lastElementComplete is true */
1562
0
                if (errorFlag.good())
1563
0
                    lastElementComplete = OFTrue;
1564
0
            }
1565
            /* remember how many bytes were read */
1566
295k
            setTransferredBytes(OFstatic_cast(Uint32, inStream.tell() - fStartPosition));
1567
295k
            if (errorFlag.good())
1568
278k
            {
1569
                // If we completed one element, update the private tag cache.
1570
278k
                if (lastElementComplete)
1571
278k
                {
1572
278k
                    privateCreatorCache.updateCache(elementList->get());
1573
                    // evaluate option for skipping rest of dataset
1574
278k
                    if ( (dcmStopParsingAfterElement.get() != DCM_UndefinedTagKey) &&
1575
0
                         (dcmStopParsingAfterElement.get() == elementList->get()->getTag()) &&
1576
0
                          ident() == EVR_dataset)
1577
0
                    {
1578
0
                        DCMDATA_DEBUG("DcmItem: Element " << newTag.getTagName() << " " << newTag
1579
0
                            << " encountered, skipping rest of data set (as requested)");
1580
0
                        readStopElem = OFTrue;
1581
0
                    }
1582
278k
                }
1583
278k
            } else
1584
17.0k
                break; // if some error was encountered terminate the while-loop
1585
295k
        } //while
1586
1587
        /* determine an appropriate result value; note that if the above called read function */
1588
        /* encountered the end of the stream before all information for this element could be */
1589
        /* read from the stream, the errorFlag has already been set to EC_StreamNotifyClient. */
1590
125k
        if (errorFlag.good())
1591
103k
        {
1592
          // if stop element was read or end of stream occurs, tell parser end of stream is reached
1593
103k
          if (readStopElem || inStream.eos())
1594
1.64k
              errorFlag = EC_EndOfStream;
1595
          // if all bytes could be read or last element read could not be completed, set to error
1596
102k
          else if ((getTransferredBytes() < getLengthField() || !lastElementComplete))
1597
0
              errorFlag = EC_StreamNotifyClient;
1598
103k
        }
1599
125k
    } // else errorFlag
1600
    /* modify the result value: three kinds of special error codes do not count as an error */
1601
126k
    if (errorFlag == EC_EndOfStream)
1602
6.72k
    {
1603
        /* ... with one exception: if the stream ended while an element was still */
1604
        /* waiting for value bytes, the data set is truncated. The element keeps  */
1605
        /* its announced value length although only part of its value was ever   */
1606
        /* received, so this must not be reported as a complete data set.        */
1607
6.72k
        if ((getTransferState() == ERW_inWork) && isLastElementIncomplete())
1608
11
        {
1609
11
            DcmObject *dO = elementList->get();
1610
11
            if (dO != NULL)
1611
11
            {
1612
11
                DCMDATA_ERROR("DcmItem: Stream ended before the value of element "
1613
11
                    << dO->getTag() << " was complete, data set is truncated");
1614
11
            } else {
1615
0
                DCMDATA_ERROR("DcmItem: Stream ended before the value of the last "
1616
0
                    << "element was complete, data set is truncated");
1617
0
            }
1618
11
            errorFlag = EC_InvalidStream;
1619
11
        } else
1620
6.71k
            errorFlag = EC_Normal;
1621
6.72k
    }
1622
119k
    else if (errorFlag == EC_ItemEnd)
1623
2.64k
        errorFlag = EC_Normal;
1624
116k
    else if (errorFlag == EC_SequEnd)
1625
0
    {
1626
0
        if (dcmIgnoreParsingErrors.get())
1627
0
        {
1628
            /* do not treat the missing delimiter as an error */
1629
0
            errorFlag = EC_Normal;
1630
0
        } else
1631
0
            errorFlag = EC_ItemDelimitationItemMissing;
1632
0
    }
1633
1634
    /* if at this point the error flag indicates success, the item has */
1635
    /* been read completely; hence, set the transfer state to ERW_ready. */
1636
    /* Note that all information for this element could be read from the */
1637
    /* stream, the errorFlag is still set to EC_StreamNotifyClient. */
1638
126k
    if (errorFlag.good())
1639
111k
        setTransferState(ERW_ready);
1640
1641
    /* dump information if required */
1642
126k
    DCMDATA_TRACE("DcmItem::read() returns error = " << errorFlag.text());
1643
1644
    /* return result value */
1645
126k
    return errorFlag;
1646
126k
}
1647
1648
1649
// ********************************
1650
1651
1652
OFCondition DcmItem::write(DcmOutputStream &outStream,
1653
                           const E_TransferSyntax oxfer,
1654
                           const E_EncodingType enctype,
1655
                           DcmWriteCache *wcache)
1656
0
{
1657
0
  if (getTransferState() == ERW_notInitialized)
1658
0
    errorFlag = EC_IllegalCall;
1659
0
  else
1660
0
  {
1661
0
    errorFlag = outStream.status();
1662
0
    if (errorFlag.good() && getTransferState() != ERW_ready)
1663
0
    {
1664
0
      if (getTransferState() == ERW_init)
1665
0
      {
1666
        // Force a compression filter (if any) to process the input buffer, by calling outStream.write().
1667
        // This ensures that we cannot get stuck if there are just a few bytes available in the buffer
1668
0
        outStream.write(NULL, 0);
1669
0
        if (outStream.avail() >= 8)
1670
0
        {
1671
0
          if (enctype == EET_ExplicitLength)
1672
0
            setLengthField(getLength(oxfer, enctype));
1673
0
          else
1674
0
            setLengthField(DCM_UndefinedLength);
1675
0
          if (errorFlag == EC_SeqOrItemContentOverflow)
1676
0
            return errorFlag;
1677
0
          errorFlag = writeTag(outStream, getTag(), oxfer);
1678
0
          Uint32 valueLength = getLengthField();
1679
0
          DcmXfer outXfer(oxfer);
1680
0
          const E_ByteOrder oByteOrder = outXfer.getByteOrder();
1681
0
          if (oByteOrder == EBO_unknown) return EC_IllegalCall;
1682
0
          swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 4, 4);
1683
0
          outStream.write(&valueLength, 4); // 4 bytes length
1684
0
          elementList->seek(ELP_first);
1685
0
          setTransferState(ERW_inWork);
1686
0
        } else {
1687
0
          errorFlag = EC_StreamNotifyClient;
1688
0
        }
1689
0
      }
1690
0
      if (getTransferState() == ERW_inWork)
1691
0
      {
1692
        // elementList->get() can be NULL if buffer was full after
1693
        // writing the last item but before writing the sequence delimitation.
1694
0
        if (!elementList->empty() && (elementList->get() != NULL))
1695
0
        {
1696
0
          DcmObject *dO = NULL;
1697
0
          do
1698
0
          {
1699
0
              dO = elementList->get();
1700
0
              if (dO->transferState() != ERW_ready)
1701
0
                errorFlag = dO->write(outStream, oxfer, enctype, wcache);
1702
0
          } while (errorFlag.good() && elementList->seek(ELP_next));
1703
0
        }
1704
0
        if (errorFlag.good())
1705
0
        {
1706
0
          setTransferState(ERW_ready);
1707
0
          if (getLengthField() == DCM_UndefinedLength)
1708
0
          {
1709
            // Force a compression filter (if any) to process the input buffer, by calling outStream.write().
1710
            // This ensures that we cannot get stuck if there are just a few bytes available in the buffer
1711
0
            outStream.write(NULL, 0);
1712
0
            if (outStream.avail() >= 8)
1713
0
            {
1714
                // write Item delimitation
1715
0
                DcmTag delim(DCM_ItemDelimitationItemTag);
1716
0
                errorFlag = writeTag(outStream, delim, oxfer);
1717
0
                Uint32 delimLen = 0L;
1718
0
                outStream.write(&delimLen, 4); // 4 bytes length
1719
0
            }
1720
0
            else
1721
0
            {
1722
                // Every subelement of the item is written but it
1723
                // is not possible to write the delimitation item into the buffer.
1724
0
                errorFlag = EC_StreamNotifyClient;
1725
0
                setTransferState(ERW_inWork);
1726
0
            }
1727
0
          }
1728
0
        }
1729
0
      }
1730
0
    }
1731
0
  }
1732
0
  return errorFlag;
1733
0
}
1734
1735
1736
// ********************************
1737
1738
1739
OFCondition DcmItem::writeSignatureFormat(DcmOutputStream &outStream,
1740
                                          const E_TransferSyntax oxfer,
1741
                                          const E_EncodingType enctype,
1742
                                          DcmWriteCache *wcache)
1743
0
{
1744
0
  if (getTransferState() == ERW_notInitialized)
1745
0
    errorFlag = EC_IllegalCall;
1746
0
  else
1747
0
  {
1748
0
    errorFlag = outStream.status();
1749
0
    if (errorFlag.good() && getTransferState() != ERW_ready)
1750
0
    {
1751
0
      if (getTransferState() == ERW_init)
1752
0
      {
1753
        // Force a compression filter (if any) to process the input buffer, by calling outStream.write().
1754
        // This ensures that we cannot get stuck if there are just a few bytes available in the buffer
1755
0
        outStream.write(NULL, 0);
1756
0
        if (outStream.avail() >= 4)
1757
0
        {
1758
0
          if (enctype == EET_ExplicitLength)
1759
0
            setLengthField(getLength(oxfer, enctype));
1760
0
          else
1761
0
            setLengthField(DCM_UndefinedLength);
1762
0
          errorFlag = writeTag(outStream, getTag(), oxfer);
1763
          /* we don't write the item length */
1764
0
          elementList->seek(ELP_first);
1765
0
          setTransferState(ERW_inWork);
1766
0
        } else
1767
0
          errorFlag = EC_StreamNotifyClient;
1768
0
      }
1769
0
      if (getTransferState() == ERW_inWork)
1770
0
      {
1771
        // elementList->get() can be NULL if buffer was full after
1772
        // writing the last item but before writing the sequence delimitation.
1773
0
        if (!elementList->empty() && (elementList->get() != NULL))
1774
0
        {
1775
0
          DcmObject *dO = NULL;
1776
0
          do
1777
0
          {
1778
0
            dO = elementList->get();
1779
0
            if (dO->isSignable() && dO->transferState() != ERW_ready)
1780
0
              errorFlag = dO->writeSignatureFormat(outStream, oxfer, enctype, wcache);
1781
0
          } while (errorFlag.good() && elementList->seek(ELP_next));
1782
0
        }
1783
0
        if (errorFlag.good())
1784
0
        {
1785
0
          setTransferState(ERW_ready);
1786
          /* we don't write an item delimitation even if the item has undefined length */
1787
0
        }
1788
0
      }
1789
0
    }
1790
0
  }
1791
0
  return errorFlag;
1792
0
}
1793
1794
1795
// ********************************
1796
1797
1798
OFBool DcmItem::isNested() const
1799
0
{
1800
0
    OFBool nested = OFFalse;
1801
0
    if (getParent() != NULL)
1802
0
    {
1803
        // check for surrounding structure of sequence of items
1804
0
        const DcmEVR parentIdent = getParent()->ident();
1805
0
        if ((parentIdent == EVR_SQ) || (parentIdent == EVR_pixelSQ))
1806
0
            nested = OFTrue;
1807
0
    }
1808
0
    return nested;
1809
0
}
1810
1811
1812
DcmItem *DcmItem::getParentItem()
1813
0
{
1814
0
    DcmItem *parentItem = NULL;
1815
0
    if (getParent() != NULL)
1816
0
    {
1817
        // make sure that the direct parent has the correct type
1818
0
        const DcmEVR parentIdent = getParent()->ident();
1819
0
        if ((parentIdent == EVR_SQ) || (parentIdent == EVR_pixelSQ))
1820
0
        {
1821
0
            DcmObject *parent = getParent()->getParent();
1822
0
            if (parent != NULL)
1823
0
            {
1824
                // make sure that it is really a class derived from DcmItem
1825
0
                switch (parent->ident())
1826
0
                {
1827
0
                    case EVR_metainfo:
1828
0
                    case EVR_dataset:
1829
0
                    case EVR_item:
1830
0
                    case EVR_dirRecord:
1831
0
                        parentItem = OFreinterpret_cast(DcmItem *, parent);
1832
0
                        break;
1833
0
                    default:
1834
0
                        DCMDATA_DEBUG("DcmItem::getParentItem() Parent object has wrong class identifier: "
1835
0
                            << OFstatic_cast(int, parent->ident())
1836
0
                            << " (" << DcmVR(parent->ident()).getVRName() << ")");
1837
0
                        break;
1838
0
                }
1839
0
            }
1840
        // When our parent is a fileformat, we should be a dataset or a metainfo.
1841
        // In these cases, there really is no parent item, so no message.
1842
0
        } else if (parentIdent != EVR_fileFormat) {
1843
0
            DCMDATA_DEBUG("DcmItem::getParentItem() Direct parent object is not a sequence element");
1844
0
        }
1845
0
    }
1846
0
    return parentItem;
1847
0
}
1848
1849
1850
// ********************************
1851
1852
1853
void DcmItem::transferInit()
1854
0
{
1855
0
    DcmObject::transferInit();
1856
0
    fStartPosition = 0;
1857
0
    lastElementComplete = OFTrue;
1858
0
    privateCreatorCache.clear();
1859
0
    if (!elementList->empty())
1860
0
    {
1861
0
        elementList->seek(ELP_first);
1862
0
        do {
1863
0
            elementList->get()->transferInit();
1864
0
        } while (elementList->seek(ELP_next));
1865
0
    }
1866
0
}
1867
1868
1869
void DcmItem::transferEnd()
1870
0
{
1871
0
    DcmObject::transferEnd();
1872
0
    privateCreatorCache.clear();
1873
0
    if (!elementList->empty())
1874
0
    {
1875
0
        elementList->seek(ELP_first);
1876
0
        do {
1877
0
            elementList->get()->transferEnd();
1878
0
        } while (elementList->seek(ELP_next));
1879
0
    }
1880
0
}
1881
1882
1883
// ********************************
1884
1885
1886
OFCondition DcmItem::insert(DcmElement *elem,
1887
                            OFBool replaceOld,
1888
                            OFBool checkInsertOrder)
1889
301k
{
1890
    /* initialize error flag with ok */
1891
301k
    errorFlag = EC_Normal;
1892
    /* do something only if the pointer which was passed does not equal NULL */
1893
301k
    if (elem != NULL)
1894
301k
    {
1895
301k
        DcmElement *dE;
1896
301k
        E_ListPos seekmode = ELP_last;
1897
        /* iterate through elementList (from the last element to the first) */
1898
14.6M
        do {
1899
            /* get current element from elementList */
1900
14.6M
            dE = OFstatic_cast(DcmElement *, elementList->seek(seekmode));
1901
            /* if there is no element, i.e. elementList is empty */
1902
14.6M
            if (dE == NULL)
1903
55.7k
            {
1904
                /* insert new element at the beginning of elementList */
1905
55.7k
                const OFBool inserted = (elementList->insert(elem, ELP_first) != NULL);
1906
55.7k
                if (checkInsertOrder)
1907
55.7k
                {
1908
                    // check if we have inserted at the end of the list. Note that
1909
                    // elementList->seek(ELP_last) must not be used for this check:
1910
                    // it would move the list cursor away from the new element, and
1911
                    // the parser relies on that cursor to find the element whose
1912
                    // value it has to continue reading when more data arrives.
1913
                    // Only in the first iteration (i.e. seekmode is still ELP_last)
1914
                    // the list was empty, so the new element is also the last one.
1915
55.7k
                    if (seekmode != ELP_last)
1916
14.0k
                    {
1917
                        // produce diagnostics
1918
14.0k
                        DCMDATA_WARN("DcmItem: Dataset not in ascending tag order, at element " << elem->getTag());
1919
14.0k
                    }
1920
55.7k
                }
1921
                /* dump some information if required */
1922
55.7k
                DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag()
1923
55.7k
                    << " VR=\"" << DcmVR(elem->getVR()).getVRName() << "\" inserted at beginning");
1924
                /* check whether the new element already has a parent */
1925
55.7k
                if (elem->getParent() != NULL)
1926
0
                {
1927
0
                    DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: "
1928
0
                      << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName());
1929
0
                }
1930
55.7k
                if (inserted)
1931
55.7k
                {
1932
                    /* remember the parent (i.e. the surrounding item/dataset) */
1933
55.7k
                    elem->setParent(this);
1934
55.7k
                }
1935
                /* terminate do-while-loop */
1936
55.7k
                break;
1937
55.7k
            }
1938
            /* else if the new element's tag is greater than the current element's tag */
1939
            /* (i.e. we have found the position where the new element shall be inserted) */
1940
14.6M
            else if (elem->getTag() > dE->getTag().getTagKey() /* only compare the attribute tag */)
1941
56.8k
            {
1942
                /* insert the new element after the current element */
1943
56.8k
                const OFBool inserted = (elementList->insert(elem, ELP_next) != NULL);
1944
56.8k
                if (checkInsertOrder)
1945
56.8k
                {
1946
                    // check if we have inserted at the end of the list. Note that
1947
                    // elementList->seek(ELP_last) must not be used for this check:
1948
                    // it would move the list cursor away from the new element, and
1949
                    // the parser relies on that cursor to find the element whose
1950
                    // value it has to continue reading when more data arrives.
1951
                    // Only in the first iteration (i.e. seekmode is still ELP_last)
1952
                    // the new element was inserted after the last one.
1953
56.8k
                    if (seekmode != ELP_last)
1954
45.6k
                    {
1955
                        // produce diagnostics
1956
45.6k
                        DCMDATA_WARN("DcmItem: Dataset not in ascending tag order, at element " << elem->getTag());
1957
45.6k
                    }
1958
56.8k
                }
1959
                /* dump some information if required */
1960
56.8k
                DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag()
1961
56.8k
                    << " VR=\"" << DcmVR(elem->getVR()).getVRName() << "\" inserted");
1962
                /* check whether the new element already has a parent */
1963
56.8k
                if (elem->getParent() != NULL)
1964
0
                {
1965
0
                    DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: "
1966
0
                        << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName());
1967
0
                }
1968
56.8k
                if (inserted)
1969
56.8k
                {
1970
                    /* remember the parent (i.e. the surrounding item/dataset) */
1971
56.8k
                    elem->setParent(this);
1972
56.8k
                }
1973
                /* terminate do-while-loop */
1974
56.8k
                break;
1975
56.8k
            }
1976
            /* else if the current element and the new element show the same tag */
1977
14.5M
            else if (elem->getTag() == dE->getTag().getTagKey() /* only compare the attribute tag */)
1978
188k
            {
1979
                /* if new and current element are not identical */
1980
188k
                if (elem != dE)
1981
188k
                {
1982
                    /* if the current (old) element shall be replaced */
1983
188k
                    if (replaceOld)
1984
0
                    {
1985
                        /* remove current element from list */
1986
0
                        DcmObject *remObj = elementList->remove();
1987
1988
                        /* now the following holds: remObj == dE and elementList */
1989
                        /* points to the element after the former current element. */
1990
1991
                        /* if the pointer to the removed object does not */
1992
                        /* equal NULL (the usual case), delete this object */
1993
                        /* and dump some information if required */
1994
0
                        if (remObj != NULL)
1995
0
                        {
1996
                            /* dump some information if required */
1997
0
                            DCMDATA_TRACE("DcmItem::insert() Element " << remObj->getTag()
1998
0
                                << " VR=\"" << DcmVR(remObj->getVR()).getVRName()
1999
0
                                << "\" p=" << OFstatic_cast(void *, remObj) << " removed and deleted");
2000
0
                            delete remObj;
2001
0
                        }
2002
                        /* insert the new element before the current element */
2003
0
                        const OFBool inserted = (elementList->insert(elem, ELP_prev) != NULL);
2004
                        /* dump some information if required */
2005
0
                        DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag()
2006
0
                            << " VR=\"" << DcmVR(elem->getVR()).getVRName()
2007
0
                            << "\" p=" << OFstatic_cast(void *, elem) << " replaced older one");
2008
                        /* check whether the new element already has a parent */
2009
0
                        if (elem->getParent() != NULL)
2010
0
                        {
2011
0
                            DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: "
2012
0
                                << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName());
2013
0
                        }
2014
0
                        if (inserted)
2015
0
                        {
2016
                            /* remember the parent (i.e. the surrounding item/dataset) */
2017
0
                            elem->setParent(this);
2018
0
                        }
2019
0
                    }   // if (replaceOld)
2020
                    /* or else, i.e. the current element shall not be replaced by the new element */
2021
188k
                    else {
2022
                        /* set the error flag correspondingly; we do not */
2023
                        /* allow two elements with the same tag in elementList */
2024
188k
                        errorFlag = EC_DoubledTag;
2025
188k
                    }   // if (!replaceOld)
2026
188k
                }   // if (elem != dE)
2027
                /* if the new and the current element are identical, the caller tries to insert */
2028
                /* one element twice. Most probably an application error. */
2029
0
                else {
2030
0
                    errorFlag = EC_DoubledTag;
2031
0
                }
2032
                /* terminate do-while-loop */
2033
188k
                break;
2034
188k
            }
2035
            /* set the seek mode to "get the previous element" */
2036
14.3M
            seekmode = ELP_prev;
2037
14.3M
        } while (dE);
2038
301k
    }
2039
    /* if the pointer which was passed equals NULL, this is an illegal call */
2040
0
    else
2041
0
        errorFlag = EC_IllegalCall;
2042
    /* return result value */
2043
301k
    return errorFlag;
2044
301k
}
2045
2046
2047
// ********************************
2048
2049
2050
DcmElement *DcmItem::getElement(const unsigned long num)
2051
0
{
2052
0
    errorFlag = EC_Normal;
2053
0
    DcmElement *elem;
2054
0
    elem = OFstatic_cast(DcmElement *, elementList->seek_to(num));
2055
    /* reads element from list */
2056
0
    if (elem == NULL)
2057
0
        errorFlag = EC_IllegalCall;
2058
0
    return elem;
2059
0
}
2060
2061
2062
// ********************************
2063
2064
2065
DcmObject *DcmItem::nextInContainer(const DcmObject *obj)
2066
8.86k
{
2067
8.86k
    if (!obj)
2068
2.02k
        return elementList->get(ELP_first);
2069
6.84k
    else
2070
6.84k
    {
2071
6.84k
        if (elementList->get() != obj)
2072
0
        {
2073
0
            for(DcmObject * search_obj = elementList->seek(ELP_first);
2074
0
                search_obj && search_obj != obj;
2075
0
                search_obj = elementList->seek(ELP_next)
2076
0
               ) {
2077
                /* do nothing, just keep iterating */
2078
0
            }
2079
0
        }
2080
6.84k
        return elementList->seek(ELP_next);
2081
6.84k
    }
2082
8.86k
}
2083
2084
2085
// ********************************
2086
2087
2088
OFCondition DcmItem::nextObject(DcmStack &stack,
2089
                                const OFBool intoSub)
2090
8.86k
{
2091
8.86k
    OFCondition l_error = EC_Normal;
2092
8.86k
    DcmObject *container = NULL;
2093
8.86k
    DcmObject *obj = NULL;
2094
8.86k
    DcmObject *result = NULL;
2095
8.86k
    OFBool examSub = intoSub;
2096
2097
8.86k
    if (stack.empty())
2098
2.02k
    {
2099
2.02k
        stack.push(this);
2100
2.02k
        examSub = OFTrue;
2101
2.02k
    }
2102
2103
8.86k
    obj = stack.top();
2104
8.86k
    if (obj->isLeaf() || !intoSub)
2105
6.84k
    {
2106
6.84k
        stack.pop();
2107
6.84k
        if (stack.card() > 0)
2108
6.84k
        {
2109
6.84k
            container = stack.top();
2110
6.84k
            result = container->nextInContainer(obj);
2111
6.84k
        }
2112
6.84k
    } else if (examSub)
2113
2.02k
        result = obj->nextInContainer(NULL);
2114
2115
8.86k
    if (result)
2116
6.84k
        stack.push(result);
2117
2.02k
    else if (intoSub)
2118
478
        l_error = nextUp(stack);
2119
1.54k
    else
2120
1.54k
        l_error = EC_SequEnd;
2121
2122
8.86k
    return l_error;
2123
8.86k
}
2124
2125
2126
// ********************************
2127
2128
2129
DcmElement *DcmItem::remove(const unsigned long num)
2130
0
{
2131
0
    errorFlag = EC_Normal;
2132
0
    DcmElement *elem;
2133
0
    elem = OFstatic_cast(DcmElement *, elementList->seek_to(num));
2134
    // read element from list
2135
0
    if (elem != NULL)
2136
0
    {
2137
0
        elementList->remove();          // removes element from list but does not delete it
2138
0
        elem->setParent(NULL);          // forget about the parent
2139
0
    } else
2140
0
        errorFlag = EC_IllegalCall;
2141
0
    return elem;
2142
0
}
2143
2144
2145
// ********************************
2146
2147
2148
DcmElement *DcmItem::remove(DcmObject *elem)
2149
0
{
2150
0
    errorFlag = EC_IllegalCall;
2151
0
    if (!elementList->empty() && elem != NULL)
2152
0
    {
2153
0
        DcmObject *dO;
2154
0
        elementList->seek(ELP_first);
2155
0
        do {
2156
0
            dO = elementList->get();
2157
0
            if (dO == elem)
2158
0
            {
2159
0
                elementList->remove();     // removes element from list but does not delete it
2160
0
                elem->setParent(NULL);     // forget about the parent
2161
0
                errorFlag = EC_Normal;
2162
0
                break;
2163
0
            }
2164
0
        } while (elementList->seek(ELP_next));
2165
0
    }
2166
0
    if (errorFlag == EC_IllegalCall)
2167
0
        return NULL;
2168
0
    else
2169
0
        return OFstatic_cast(DcmElement *, elem);
2170
0
}
2171
2172
2173
// ********************************
2174
2175
2176
DcmElement *DcmItem::remove(const DcmTagKey &tag)
2177
0
{
2178
0
    errorFlag = EC_TagNotFound;
2179
0
    DcmObject *dO = NULL;
2180
0
    if (!elementList->empty())
2181
0
    {
2182
0
        elementList->seek(ELP_first);
2183
0
        do {
2184
0
            dO = elementList->get();
2185
0
            if (dO->getTag() == tag)
2186
0
            {
2187
0
                elementList->remove();     // removes element from list but does not delete it
2188
0
                dO->setParent(NULL);       // forget about the parent
2189
0
                errorFlag = EC_Normal;
2190
0
                break;
2191
0
            }
2192
0
        } while (elementList->seek(ELP_next));
2193
0
    }
2194
2195
0
    if (errorFlag == EC_TagNotFound)
2196
0
        return NULL;
2197
0
    else
2198
0
        return OFstatic_cast(DcmElement *, dO);
2199
0
}
2200
2201
2202
// ********************************
2203
2204
2205
OFCondition DcmItem::clear()
2206
0
{
2207
0
    errorFlag = EC_Normal;
2208
    // remove all elements from item and delete them from memory
2209
0
    elementList->deleteAllElements();
2210
0
    setLengthField(0);
2211
2212
0
    return errorFlag;
2213
0
}
2214
2215
2216
OFBool DcmItem::isEmpty(const OFBool /*normalize*/)
2217
10.3k
{
2218
10.3k
    return elementList->empty();
2219
10.3k
}
2220
2221
2222
// ********************************
2223
2224
2225
OFCondition DcmItem::verify(const OFBool autocorrect)
2226
0
{
2227
0
    errorFlag = EC_Normal;
2228
0
    if (!elementList->empty())
2229
0
    {
2230
0
        DcmObject *dO;
2231
0
        elementList->seek(ELP_first);
2232
0
        do {
2233
0
            dO = elementList->get();
2234
0
            if (dO->verify(autocorrect).bad())
2235
0
                errorFlag = EC_CorruptedData;
2236
0
        } while (elementList->seek(ELP_next));
2237
0
    }
2238
0
    if (autocorrect)
2239
0
        setLengthField(getLength());
2240
0
    return errorFlag;
2241
0
}
2242
2243
2244
// ********************************
2245
2246
// Precondition: elementList is non-empty!
2247
// Result:       - return EC_Normal;
2248
//                 push element pointer on resultStack
2249
//               - return EC_TagNotFound;
2250
//                 resultStack unmodified
2251
// Search again: push pointer of sub-element on resultStack and
2252
//               start sub-search
2253
2254
OFCondition DcmItem::searchSubFromHere(const DcmTagKey &tag,
2255
                                       DcmStack &resultStack,
2256
                                       OFBool searchIntoSub)
2257
47.8k
{
2258
47.8k
    DcmObject *dO;
2259
47.8k
    OFCondition l_error = EC_TagNotFound;
2260
47.8k
    if (!elementList->empty())
2261
47.3k
    {
2262
47.3k
        elementList->seek(ELP_first);
2263
135k
        do {
2264
135k
            dO = elementList->get();
2265
135k
            if (searchIntoSub)
2266
74.2k
            {
2267
74.2k
                resultStack.push(dO);
2268
74.2k
                if (dO->getTag() == tag)
2269
3.46k
                    l_error = EC_Normal;
2270
70.8k
                else
2271
70.8k
                    l_error = dO->search(tag, resultStack, ESM_fromStackTop, OFTrue);
2272
74.2k
                if (l_error.bad())
2273
68.2k
                    resultStack.pop();
2274
74.2k
            } else {
2275
61.3k
                if (dO->getTag() == tag)
2276
14.6k
                {
2277
14.6k
                    resultStack.push(dO);
2278
14.6k
                    l_error = EC_Normal;
2279
14.6k
                }
2280
61.3k
            }
2281
135k
        } while (l_error.bad() && elementList->seek(ELP_next));
2282
47.3k
        if (l_error==EC_Normal && dO->getTag()==tag)
2283
18.1k
        {
2284
18.1k
            DCMDATA_TRACE("DcmItem::searchSubFromHere() Element " << tag << " found");
2285
18.1k
        }
2286
47.3k
    }
2287
47.8k
    return l_error;
2288
47.8k
}
2289
2290
2291
// ********************************
2292
2293
2294
OFCondition DcmItem::search(const DcmTagKey &tag,
2295
                            DcmStack &resultStack,
2296
                            E_SearchMode mode,
2297
                            OFBool searchIntoSub)
2298
75.6k
{
2299
75.6k
    DcmObject *dO = NULL;
2300
75.6k
    OFCondition l_error = EC_TagNotFound;
2301
75.6k
    if (mode == ESM_afterStackTop && resultStack.top() == this)
2302
2.01k
    {
2303
2.01k
        l_error = searchSubFromHere(tag, resultStack, searchIntoSub);
2304
2.01k
    }
2305
73.6k
    else if (!elementList->empty())
2306
55.6k
    {
2307
55.6k
        if (mode == ESM_fromHere || resultStack.empty())
2308
32.0k
        {
2309
32.0k
            resultStack.clear();
2310
32.0k
            l_error = searchSubFromHere(tag, resultStack, searchIntoSub);
2311
32.0k
        }
2312
23.5k
        else if (mode == ESM_fromStackTop)
2313
13.7k
        {
2314
13.7k
            dO = resultStack.top();
2315
13.7k
            if (dO == this)
2316
13.7k
                l_error = searchSubFromHere(tag, resultStack, searchIntoSub);
2317
0
            else
2318
0
            {   // gehe direkt zu Sub-Baum und suche dort weiter
2319
0
                l_error = dO->search(tag, resultStack, mode, searchIntoSub);
2320
// The next two lines destroy the stack->so delete them
2321
//                if (l_error.bad()) // raeumt nur die oberste Stackebene
2322
//                    resultStack.pop();      // ab; der Rest ist unveraendert
2323
0
            }
2324
13.7k
        }
2325
9.81k
        else if (mode == ESM_afterStackTop && searchIntoSub)
2326
9.81k
        {
2327
            // resultStack enthaelt Zielinformationen:
2328
            // - stelle Zustand der letzen Suche in den einzelnen Suchroutinen
2329
            //   wieder her
2330
            // - finde Position von dO in Baum-Struktur
2331
            //   1. suche eigenen Stack-Eintrag
2332
            //      - bei Fehlschlag Suche beenden
2333
            //   2. nehme naechsthoeheren Eintrag dnO
2334
            //   3. stelle eigene Liste auf Position von dnO
2335
            //   4. starte Suche ab dnO
2336
2337
9.81k
            unsigned long i = resultStack.card();
2338
187k
            while (i > 0 && (dO = resultStack.elem(i-1)) != this)
2339
177k
            {
2340
177k
                i--;
2341
177k
            }
2342
9.81k
            if (dO != this && resultStack.card() > 0)
2343
0
            {                            // oberste Ebene steht nie in resultStack
2344
0
                i = resultStack.card()+1;// zeige jetzt auf hoechste Ebene+1
2345
0
                dO = this;               // Treffer der hoechsten Ebene!
2346
0
            }
2347
9.81k
            if (dO == this)
2348
9.81k
            {
2349
9.81k
                if (i == 1)                   // habe resultStack.top() gefunden
2350
0
                    l_error = EC_TagNotFound; // markiere als kein Treffer, s.o.
2351
9.81k
                else                          //   siehe oben
2352
9.81k
                {
2353
9.81k
                    E_SearchMode submode = mode;
2354
9.81k
                    OFBool searchNode = OFTrue;
2355
9.81k
                    DcmObject *dnO;
2356
9.81k
                    dnO = resultStack.elem(i - 2); // Knoten der naechsten Ebene
2357
9.81k
                    elementList->seek(ELP_first);
2358
24.4k
                    do {
2359
24.4k
                        dO = elementList->get();
2360
24.4k
                        searchNode = searchNode ? (dO != dnO) : OFFalse;
2361
24.4k
                        if (!searchNode)
2362
16.7k
                        {                             // suche jetzt weiter
2363
16.7k
                            if (submode == ESM_fromStackTop)
2364
6.92k
                                resultStack.push(dO); // Stack aktualisieren
2365
16.7k
                            if (submode == ESM_fromStackTop && dO->getTag() == tag)
2366
440
                                l_error = EC_Normal;
2367
16.2k
                            else
2368
16.2k
                                l_error = dO->search(tag, resultStack, submode, OFTrue);
2369
16.7k
                            if (l_error.bad())
2370
9.22k
                                resultStack.pop();
2371
7.51k
                            else
2372
7.51k
                                break;
2373
9.22k
                            submode = ESM_fromStackTop; // ab hier normale Suche
2374
9.22k
                        }
2375
24.4k
                    } while (elementList->seek(ELP_next));
2376
9.81k
                }
2377
9.81k
            } else
2378
0
                l_error = EC_IllegalCall;
2379
9.81k
        } // (mode == ESM_afterStackTop
2380
0
        else
2381
0
            l_error = EC_IllegalCall;
2382
55.6k
    }
2383
75.6k
    return l_error;
2384
75.6k
}
2385
2386
2387
// ********************************
2388
2389
2390
OFCondition DcmItem::loadAllDataIntoMemory()
2391
0
{
2392
0
    OFCondition l_error = EC_Normal;
2393
0
    if (!elementList->empty())
2394
0
    {
2395
0
        elementList->seek(ELP_first);
2396
0
        do {
2397
0
            OFCondition err = EC_Normal;
2398
0
            DcmObject *dO = elementList->get();
2399
0
            if ((err = dO->loadAllDataIntoMemory()).bad())
2400
0
                l_error = err;
2401
0
        } while (elementList->seek(ELP_next));
2402
0
    }
2403
0
    return l_error;
2404
0
}
2405
2406
2407
// ********************************
2408
2409
2410
void DcmItem::compactElements(const Uint32 maxLength)
2411
0
{
2412
0
    DcmStack stack;
2413
0
    DcmObject *object = NULL;
2414
    /* iterate over all elements */
2415
0
    while (nextObject(stack, OFTrue).good())
2416
0
    {
2417
0
        object = stack.top();
2418
        // compact element if maximum length is exceeded
2419
0
        if (object->isLeaf() && (object->getLength() > maxLength))
2420
0
            OFstatic_cast(DcmElement *, object)->compact();
2421
0
    }
2422
0
}
2423
2424
2425
// ********************************
2426
2427
// Support functions
2428
2429
2430
OFCondition nextUp(DcmStack &stack)
2431
478
{
2432
478
    DcmObject *oldContainer = stack.pop();
2433
478
    if (oldContainer->isLeaf())
2434
0
        return EC_IllegalCall;
2435
478
    else if (!stack.empty())
2436
0
    {
2437
0
        DcmObject *container = stack.top();
2438
0
        DcmObject *result = container->nextInContainer(oldContainer);
2439
0
        if (result)
2440
0
        {
2441
0
            stack.push(result);
2442
0
            return EC_Normal;
2443
0
        }
2444
0
        else
2445
0
            return nextUp(stack);
2446
0
    }
2447
478
    return EC_TagNotFound;
2448
478
}
2449
2450
2451
/*
2452
** Simple tests for existence
2453
*/
2454
2455
OFBool DcmItem::tagExists(const DcmTagKey &key,
2456
                          OFBool searchIntoSub)
2457
6.03k
{
2458
6.03k
    DcmStack stack;
2459
2460
6.03k
    OFCondition ec = search(key, stack, ESM_fromHere, searchIntoSub);
2461
6.03k
    return (ec.good());
2462
6.03k
}
2463
2464
2465
OFBool DcmItem::tagExistsWithValue(const DcmTagKey &key,
2466
                                   OFBool searchIntoSub)
2467
0
{
2468
0
    DcmStack stack;
2469
0
    OFBool result = OFFalse;
2470
2471
0
    if (search(key, stack, ESM_fromHere, searchIntoSub).good() && stack.top()->isElement())
2472
0
    {
2473
0
        DcmElement *elem = OFstatic_cast(DcmElement *, stack.top());
2474
0
        if (elem != NULL)
2475
0
            result = !(elem->isEmpty());
2476
0
    }
2477
2478
0
    return result;
2479
0
}
2480
2481
2482
// ********************************
2483
2484
/* --- findAndGet functions: find an element and get it or the value, respectively --- */
2485
2486
OFCondition DcmItem::findAndGetElement(const DcmTagKey &tagKey,
2487
                                       DcmElement *&element,
2488
                                       const OFBool searchIntoSub,
2489
                                       const OFBool createCopy)
2490
9.34k
{
2491
9.34k
    DcmStack stack;
2492
    /* find the element */
2493
9.34k
    OFCondition status = search(tagKey, stack, ESM_fromHere, searchIntoSub);
2494
9.34k
    if (status.good() && stack.top()->isElement())
2495
1.24k
    {
2496
1.24k
        element = OFstatic_cast(DcmElement *, stack.top());
2497
        /* should never happen but ... */
2498
1.24k
        if (element == NULL)
2499
0
            status = EC_CorruptedData;
2500
1.24k
        else if (createCopy)
2501
0
        {
2502
            /* create a copy of the element */
2503
0
            element = OFstatic_cast(DcmElement *, element->clone());
2504
0
            if (element == NULL)
2505
0
                status = EC_MemoryExhausted;
2506
0
        }
2507
8.10k
    } else {
2508
        /* reset element pointer */
2509
8.10k
        element = NULL;
2510
8.10k
    }
2511
9.34k
    return status;
2512
9.34k
}
2513
2514
2515
OFCondition DcmItem::findAndGetElements(const DcmTagKey &tagKey,
2516
                                        DcmStack &resultStack)
2517
0
{
2518
0
    OFCondition status = EC_TagNotFound;
2519
0
    DcmStack stack;
2520
0
    DcmObject *object = NULL;
2521
    /* iterate over all elements */
2522
0
    while (nextObject(stack, OFTrue).good())
2523
0
    {
2524
        /* get element */
2525
0
        object = stack.top();
2526
0
        if (object->getTag() == tagKey)
2527
0
        {
2528
            /* add it to the result stack */
2529
0
            resultStack.push(object);
2530
0
            status = EC_Normal;
2531
0
        }
2532
0
    }
2533
0
    return status;
2534
0
}
2535
2536
2537
OFCondition DcmItem::findAndGetString(const DcmTagKey &tagKey,
2538
                                      const char *&value,
2539
                                      const OFBool searchIntoSub)
2540
0
{
2541
0
    DcmElement *elem;
2542
    /* find the element */
2543
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2544
0
    if (status.good())
2545
0
    {
2546
        /* get the value */
2547
0
        status = elem->getString(OFconst_cast(char *&, value));
2548
0
    }
2549
    /* reset value */
2550
0
    if (status.bad())
2551
0
        value = NULL;
2552
0
    return status;
2553
0
}
2554
2555
2556
OFCondition DcmItem::findAndGetString(const DcmTagKey &tagKey,
2557
                                      const char *&value,
2558
                                      Uint32 &length,
2559
                                      const OFBool searchIntoSub)
2560
0
{
2561
0
    DcmElement *elem;
2562
    /* find the element */
2563
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2564
0
    if (status.good())
2565
0
    {
2566
        /* get the value */
2567
0
        status = elem->getString(OFconst_cast(char *&, value), length);
2568
0
    }
2569
    /* reset values */
2570
0
    if (status.bad())
2571
0
    {
2572
0
        value = NULL;
2573
0
        length = 0;
2574
0
    }
2575
0
    return status;
2576
0
}
2577
2578
2579
OFCondition DcmItem::findAndGetOFString(const DcmTagKey &tagKey,
2580
                                        OFString &value,
2581
                                        const unsigned long pos,
2582
                                        const OFBool searchIntoSub)
2583
6.09k
{
2584
6.09k
    DcmElement *elem;
2585
    /* find the element */
2586
6.09k
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2587
6.09k
    if (status.good())
2588
783
    {
2589
        /* get the value */
2590
783
        status = elem->getOFString(value, pos);
2591
783
    }
2592
    /* reset value */
2593
6.09k
    if (status.bad())
2594
5.52k
        value.clear();
2595
6.09k
    return status;
2596
6.09k
}
2597
2598
2599
OFCondition DcmItem::findAndGetOFStringArray(const DcmTagKey &tagKey,
2600
                                             OFString &value,
2601
                                             const OFBool searchIntoSub)
2602
0
{
2603
0
    DcmElement *elem;
2604
    /* find the element */
2605
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2606
0
    if (status.good())
2607
0
    {
2608
        /* get the value */
2609
0
        status = elem->getOFStringArray(value);
2610
0
    }
2611
    /* reset value */
2612
0
    if (status.bad())
2613
0
        value.clear();
2614
0
    return status;
2615
0
}
2616
2617
2618
OFCondition DcmItem::findAndGetUint8(const DcmTagKey &tagKey,
2619
                                     Uint8 &value,
2620
                                     const unsigned long pos,
2621
                                     const OFBool searchIntoSub)
2622
0
{
2623
0
    DcmElement *elem;
2624
    /* find the element */
2625
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2626
0
    if (status.good())
2627
0
    {
2628
        /* get the value */
2629
0
        status = elem->getUint8(value, pos);
2630
0
    }
2631
    /* reset value */
2632
0
    if (status.bad())
2633
0
        value = 0;
2634
0
    return status;
2635
0
}
2636
2637
2638
OFCondition DcmItem::findAndGetUint8Array(const DcmTagKey &tagKey,
2639
                                          const Uint8 *&value,
2640
                                          unsigned long *count,
2641
                                          const OFBool searchIntoSub)
2642
0
{
2643
0
    DcmElement *elem;
2644
    /* find the element */
2645
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2646
0
    if (status.good())
2647
0
    {
2648
        /* get the value */
2649
0
        Uint8 *array = NULL;
2650
0
        status = elem->getUint8Array(array);
2651
0
        value = array;
2652
0
    }
2653
    /* set optional count parameter */
2654
0
    if (count != NULL)
2655
0
    {
2656
0
        if (status.good())
2657
0
            *count = elem->getLength() / sizeof(Uint8);
2658
0
        else
2659
0
            *count = 0;
2660
0
    }
2661
    /* reset value */
2662
0
    if (status.bad())
2663
0
        value = NULL;
2664
0
    return status;
2665
0
}
2666
2667
2668
OFCondition DcmItem::findAndGetUint16(const DcmTagKey &tagKey,
2669
                                      Uint16 &value,
2670
                                      const unsigned long pos,
2671
                                      const OFBool searchIntoSub)
2672
0
{
2673
0
    DcmElement *elem;
2674
    /* find the element */
2675
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2676
0
    if (status.good())
2677
0
    {
2678
        /* get the value */
2679
0
        status = elem->getUint16(value, pos);
2680
0
    }
2681
    /* reset value */
2682
0
    if (status.bad())
2683
0
        value = 0;
2684
0
    return status;
2685
0
}
2686
2687
2688
OFCondition DcmItem::findAndGetUint16Array(const DcmTagKey &tagKey,
2689
                                           const Uint16 *&value,
2690
                                           unsigned long *count,
2691
                                           const OFBool searchIntoSub)
2692
0
{
2693
0
    DcmElement *elem;
2694
    /* find the element */
2695
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2696
0
    if (status.good())
2697
0
    {
2698
        /* get the value */
2699
0
        Uint16 *array = NULL;
2700
0
        status = elem->getUint16Array(array);
2701
0
        value = array;
2702
0
    }
2703
    /* set optional count parameter */
2704
0
    if (count != NULL)
2705
0
    {
2706
0
        if (status.good())
2707
0
        {
2708
            /* don't use getNumberOfValues() because of OB/OW for pixel data
2709
             * and since AT uses two 16-bit integers per value */
2710
0
            *count = elem->getLength() / sizeof(Uint16);
2711
0
        } else
2712
0
            *count = 0;
2713
0
    }
2714
    /* reset value */
2715
0
    if (status.bad())
2716
0
        value = NULL;
2717
0
    return status;
2718
0
}
2719
2720
2721
OFCondition DcmItem::findAndGetSint16(const DcmTagKey &tagKey,
2722
                                      Sint16 &value,
2723
                                      const unsigned long pos,
2724
                                      const OFBool searchIntoSub)
2725
0
{
2726
0
    DcmElement *elem;
2727
    /* find the element */
2728
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2729
0
    if (status.good())
2730
0
    {
2731
        /* get the value */
2732
0
        status = elem->getSint16(value, pos);
2733
0
    }
2734
    /* reset value */
2735
0
    if (status.bad())
2736
0
        value = 0;
2737
0
    return status;
2738
0
}
2739
2740
2741
OFCondition DcmItem::findAndGetSint16Array(const DcmTagKey &tagKey,
2742
                                           const Sint16 *&value,
2743
                                           unsigned long *count,
2744
                                           const OFBool searchIntoSub)
2745
0
{
2746
0
    DcmElement *elem;
2747
    /* find the element */
2748
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2749
0
    if (status.good())
2750
0
    {
2751
        /* get the value */
2752
0
        Sint16 *array = NULL;
2753
0
        status = elem->getSint16Array(array);
2754
0
        value = array;
2755
0
    }
2756
    /* set optional count parameter */
2757
0
    if (count != NULL)
2758
0
    {
2759
0
        if (status.good())
2760
0
            *count = elem->getLength() / sizeof(Sint16);
2761
0
        else
2762
0
            *count = 0;
2763
0
    }
2764
    /* reset value */
2765
0
    if (status.bad())
2766
0
        value = NULL;
2767
0
    return status;
2768
0
}
2769
2770
2771
OFCondition DcmItem::findAndGetUint32(const DcmTagKey &tagKey,
2772
                                      Uint32 &value,
2773
                                      const unsigned long pos,
2774
                                      const OFBool searchIntoSub)
2775
0
{
2776
0
    DcmElement *elem;
2777
    /* find the element */
2778
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2779
0
    if (status.good())
2780
0
    {
2781
        /* get the value */
2782
0
        status = elem->getUint32(value, pos);
2783
0
    }
2784
    /* reset value */
2785
0
    if (status.bad())
2786
0
        value = 0;
2787
0
    return status;
2788
0
}
2789
2790
2791
OFCondition DcmItem::findAndGetUint32Array(const DcmTagKey &tagKey,
2792
                                           const Uint32 *&value,
2793
                                           unsigned long *count,
2794
                                           const OFBool searchIntoSub)
2795
0
{
2796
0
    DcmElement *elem;
2797
    /* find the element */
2798
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2799
0
    if (status.good())
2800
0
    {
2801
        /* get the value */
2802
0
        Uint32 *array = NULL;
2803
0
        status = elem->getUint32Array(array);
2804
0
        value = array;
2805
0
    }
2806
    /* set optional count parameter */
2807
0
    if (count != NULL)
2808
0
    {
2809
0
        if (status.good())
2810
0
            *count = elem->getLength() / sizeof(Uint32);
2811
0
        else
2812
0
            *count = 0;
2813
0
    }
2814
    /* reset value */
2815
0
    if (status.bad())
2816
0
        value = NULL;
2817
0
    return status;
2818
0
}
2819
2820
2821
OFCondition DcmItem::findAndGetSint32(const DcmTagKey &tagKey,
2822
                                      Sint32 &value,
2823
                                      const unsigned long pos,
2824
                                      const OFBool searchIntoSub)
2825
0
{
2826
0
    DcmElement *elem;
2827
    /* find the element */
2828
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2829
0
    if (status.good())
2830
0
    {
2831
        /* get the value */
2832
0
        status = elem->getSint32(value, pos);
2833
0
    }
2834
    /* reset value */
2835
0
    if (status.bad())
2836
0
        value = 0;
2837
0
    return status;
2838
0
}
2839
2840
2841
OFCondition DcmItem::findAndGetSint32Array(const DcmTagKey &tagKey,
2842
                                           const Sint32 *&value,
2843
                                           unsigned long *count,
2844
                                           const OFBool searchIntoSub)
2845
0
{
2846
0
    DcmElement *elem;
2847
    /* find the element */
2848
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2849
0
    if (status.good())
2850
0
    {
2851
        /* get the value */
2852
0
        Sint32 *array = NULL;
2853
0
        status = elem->getSint32Array(array);
2854
0
        value = array;
2855
0
    }
2856
    /* set optional count parameter */
2857
0
    if (count != NULL)
2858
0
    {
2859
0
        if (status.good())
2860
0
            *count = elem->getLength() / sizeof(Sint32);
2861
0
        else
2862
0
            *count = 0;
2863
0
    }
2864
    /* reset value */
2865
0
    if (status.bad())
2866
0
        value = NULL;
2867
0
    return status;
2868
0
}
2869
2870
2871
OFCondition DcmItem::findAndGetUint64(const DcmTagKey &tagKey,
2872
                                      Uint64 &value,
2873
                                      const unsigned long pos,
2874
                                      const OFBool searchIntoSub)
2875
0
{
2876
0
    DcmElement *elem;
2877
    /* find the element */
2878
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2879
0
    if (status.good())
2880
0
    {
2881
        /* get the value */
2882
0
        status = elem->getUint64(value, pos);
2883
0
    }
2884
    /* reset value */
2885
0
    if (status.bad())
2886
0
        value = 0;
2887
0
    return status;
2888
0
}
2889
2890
2891
OFCondition DcmItem::findAndGetUint64Array(const DcmTagKey &tagKey,
2892
                                           const Uint64 *&value,
2893
                                           unsigned long *count,
2894
                                           const OFBool searchIntoSub)
2895
0
{
2896
0
    DcmElement *elem;
2897
    /* find the element */
2898
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2899
0
    if (status.good())
2900
0
    {
2901
        /* get the value */
2902
0
        Uint64 *array = NULL;
2903
0
        status = elem->getUint64Array(array);
2904
0
        value = array;
2905
0
    }
2906
    /* set optional count parameter */
2907
0
    if (count != NULL)
2908
0
    {
2909
0
        if (status.good())
2910
0
            *count = elem->getLength() / sizeof(Uint64);
2911
0
        else
2912
0
            *count = 0;
2913
0
    }
2914
    /* reset value */
2915
0
    if (status.bad())
2916
0
        value = NULL;
2917
0
    return status;
2918
0
}
2919
2920
2921
OFCondition DcmItem::findAndGetSint64(const DcmTagKey &tagKey,
2922
                                      Sint64 &value,
2923
                                      const unsigned long pos,
2924
                                      const OFBool searchIntoSub)
2925
0
{
2926
0
    DcmElement *elem;
2927
    /* find the element */
2928
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2929
0
    if (status.good())
2930
0
    {
2931
        /* get the value */
2932
0
        status = elem->getSint64(value, pos);
2933
0
    }
2934
    /* reset value */
2935
0
    if (status.bad())
2936
0
        value = 0;
2937
0
    return status;
2938
0
}
2939
2940
2941
OFCondition DcmItem::findAndGetSint64Array(const DcmTagKey &tagKey,
2942
                                           const Sint64 *&value,
2943
                                           unsigned long *count,
2944
                                           const OFBool searchIntoSub)
2945
0
{
2946
0
    DcmElement *elem;
2947
    /* find the element */
2948
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2949
0
    if (status.good())
2950
0
    {
2951
        /* get the value */
2952
0
        Sint64 *array = NULL;
2953
0
        status = elem->getSint64Array(array);
2954
0
        value = array;
2955
0
    }
2956
    /* set optional count parameter */
2957
0
    if (count != NULL)
2958
0
    {
2959
0
        if (status.good())
2960
0
            *count = elem->getLength() / sizeof(Sint64);
2961
0
        else
2962
0
            *count = 0;
2963
0
    }
2964
    /* reset value */
2965
0
    if (status.bad())
2966
0
        value = NULL;
2967
0
    return status;
2968
0
}
2969
2970
2971
OFCondition DcmItem::findAndGetLongInt(const DcmTagKey &tagKey,
2972
                                       long int &value,
2973
                                       const unsigned long pos,
2974
                                       const OFBool searchIntoSub)
2975
0
{
2976
0
    DcmElement *elem;
2977
    /* find the element */
2978
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
2979
0
    if (status.good())
2980
0
    {
2981
        /* distinguish supported VRs */
2982
0
        switch (elem->ident())
2983
0
        {
2984
0
            case EVR_UL:
2985
0
            case EVR_OL:
2986
0
            case EVR_up:
2987
0
                Uint32 ul;
2988
0
                status = elem->getUint32(ul, pos);
2989
0
                value = OFstatic_cast(long int, ul);
2990
0
                break;
2991
0
            case EVR_SL:
2992
0
            case EVR_IS:
2993
0
                Sint32 sl;
2994
0
                status = elem->getSint32(sl, pos);
2995
0
                value = OFstatic_cast(long int, sl);
2996
0
                break;
2997
0
            case EVR_US:
2998
0
            case EVR_xs:
2999
0
            case EVR_lt:
3000
0
                Uint16 us;
3001
0
                status = elem->getUint16(us, pos);
3002
0
                value = OFstatic_cast(long int, us);
3003
0
                break;
3004
0
            case EVR_SS:
3005
0
                Sint16 ss;
3006
0
                status = elem->getSint16(ss, pos);
3007
0
                value = OFstatic_cast(long int, ss);
3008
0
                break;
3009
0
            default:
3010
0
                status = EC_IllegalCall;
3011
0
                break;
3012
0
        }
3013
0
    }
3014
    /* reset value */
3015
0
    if (status.bad())
3016
0
        value = 0;
3017
0
    return status;
3018
0
}
3019
3020
3021
OFCondition DcmItem::findAndGetFloat32(const DcmTagKey &tagKey,
3022
                                       Float32 &value,
3023
                                       const unsigned long pos,
3024
                                       const OFBool searchIntoSub)
3025
0
{
3026
0
    DcmElement *elem;
3027
    /* find the element */
3028
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
3029
0
    if (status.good())
3030
0
    {
3031
        /* get the value */
3032
0
        status = elem->getFloat32(value, pos);
3033
0
    }
3034
    /* reset value */
3035
0
    if (status.bad())
3036
0
        value = 0;
3037
0
    return status;
3038
0
}
3039
3040
3041
OFCondition DcmItem::findAndGetFloat32Array(const DcmTagKey &tagKey,
3042
                                            const Float32 *&value,
3043
                                            unsigned long *count,
3044
                                            const OFBool searchIntoSub)
3045
0
{
3046
0
    DcmElement *elem;
3047
    /* find the element */
3048
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
3049
0
    if (status.good())
3050
0
    {
3051
        /* get the value */
3052
0
        Float32 *array = NULL;
3053
0
        status = elem->getFloat32Array(array);
3054
0
        value = array;
3055
0
    }
3056
    /* set optional count parameter */
3057
0
    if (count != NULL)
3058
0
    {
3059
0
        if (status.good())
3060
0
            *count = elem->getLength() / sizeof(Float32);
3061
0
        else
3062
0
            *count = 0;
3063
0
    }
3064
    /* reset value */
3065
0
    if (status.bad())
3066
0
        value = NULL;
3067
0
    return status;
3068
0
}
3069
3070
3071
OFCondition DcmItem::findAndGetFloat64(const DcmTagKey &tagKey,
3072
                                       Float64 &value,
3073
                                       const unsigned long pos,
3074
                                       const OFBool searchIntoSub)
3075
0
{
3076
0
    DcmElement *elem;
3077
    /* find the element */
3078
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
3079
0
    if (status.good())
3080
0
    {
3081
        /* get the value */
3082
0
        status = elem->getFloat64(value, pos);
3083
0
    }
3084
    /* reset value */
3085
0
    if (status.bad())
3086
0
        value = 0;
3087
0
    return status;
3088
0
}
3089
3090
3091
OFCondition DcmItem::findAndGetFloat64Array(const DcmTagKey &tagKey,
3092
                                            const Float64 *&value,
3093
                                            unsigned long *count,
3094
                                            const OFBool searchIntoSub)
3095
0
{
3096
0
    DcmElement *elem;
3097
    /* find the element */
3098
0
    OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub);
3099
0
    if (status.good())
3100
0
    {
3101
        /* get the value */
3102
0
        Float64 *array = NULL;
3103
0
        status = elem->getFloat64Array(array);
3104
0
        value = array;
3105
0
    }
3106
    /* set optional count parameter */
3107
0
    if (count != NULL)
3108
0
    {
3109
0
        if (status.good())
3110
0
            *count = elem->getLength() / sizeof(Float64);
3111
0
        else
3112
0
            *count = 0;
3113
0
    }
3114
    /* reset value */
3115
0
    if (status.bad())
3116
0
        value = NULL;
3117
0
    return status;
3118
0
}
3119
3120
3121
OFCondition DcmItem::findAndGetSequence(const DcmTagKey &seqTagKey,
3122
                                        DcmSequenceOfItems *&sequence,
3123
                                        const OFBool searchIntoSub,
3124
                                        const OFBool createCopy)
3125
0
{
3126
0
    DcmStack stack;
3127
    /* find the element */
3128
0
    OFCondition status = search(seqTagKey, stack, ESM_fromHere, searchIntoSub);
3129
0
    if (status.good() && stack.top()->isElement())
3130
0
    {
3131
0
        DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
3132
        /* should never happen but ... */
3133
0
        if (delem == NULL)
3134
0
            status = EC_CorruptedData;
3135
        /* check for correct VR */
3136
0
        else if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ))
3137
0
        {
3138
0
            sequence = OFstatic_cast(DcmSequenceOfItems *, delem);
3139
            /* create a copy of the sequence? */
3140
0
            if (createCopy)
3141
0
            {
3142
0
                sequence = OFstatic_cast(DcmSequenceOfItems *, sequence->clone());
3143
0
                if (sequence == NULL)
3144
0
                    status = EC_MemoryExhausted;
3145
0
            }
3146
0
        } else
3147
0
            status = EC_InvalidVR;
3148
0
    }
3149
0
    if (status.bad())
3150
0
    {
3151
        /* reset sequence pointer */
3152
0
        sequence = NULL;
3153
0
    }
3154
0
    return status;
3155
0
}
3156
3157
3158
OFCondition DcmItem::findAndGetSequenceItem(const DcmTagKey &seqTagKey,
3159
                                            DcmItem *&item,
3160
                                            const signed long itemNum,
3161
                                            const OFBool createCopy)
3162
0
{
3163
0
    DcmStack stack;
3164
    /* find sequence */
3165
0
    OFCondition status = search(seqTagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
3166
0
    if (status.good() && stack.top()->isElement())
3167
0
    {
3168
        /* get element */
3169
0
        DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
3170
0
        if (delem != NULL)
3171
0
        {
3172
            /* check VR */
3173
0
            if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ))
3174
0
            {
3175
0
                DcmSequenceOfItems *sequence = OFstatic_cast(DcmSequenceOfItems *, delem);
3176
0
                const unsigned long count = sequence->card();
3177
                /* empty sequence? */
3178
0
                if (count > 0)
3179
0
                {
3180
                    /* get last item */
3181
0
                    if (itemNum == -1)
3182
0
                        item = sequence->getItem(count - 1);
3183
                    /* get specified item */
3184
0
                    else if ((itemNum >= 0) && (OFstatic_cast(unsigned long, itemNum) < count))
3185
0
                        item = sequence->getItem(OFstatic_cast(unsigned long, itemNum));
3186
                    /* invalid item number */
3187
0
                    else
3188
0
                        status = EC_IllegalParameter;
3189
                    /* create a copy of the item? */
3190
0
                    if (createCopy)
3191
0
                    {
3192
0
                        if (status.good() && (item != NULL))
3193
0
                        {
3194
0
                            item = OFstatic_cast(DcmItem *, item->clone());
3195
0
                            if (item == NULL)
3196
0
                                status = EC_MemoryExhausted;
3197
0
                        }
3198
0
                    }
3199
0
                } else
3200
0
                    status = EC_IllegalParameter;
3201
0
            } else
3202
0
                status = EC_InvalidVR;
3203
0
        } else
3204
0
            status = EC_CorruptedData;
3205
0
    }
3206
    /* reset item value */
3207
0
    if (status.bad())
3208
0
        item = NULL;
3209
0
    else if (item == NULL)
3210
0
        status = EC_IllegalCall;
3211
0
    return status;
3212
0
}
3213
3214
3215
// ********************************
3216
3217
/* --- findOrCreate functions: find an element or create a new one --- */
3218
3219
OFCondition DcmItem::findOrCreateSequenceItem(const DcmTag &seqTag,
3220
                                              DcmItem *&item,
3221
                                              const signed long itemNum)
3222
0
{
3223
0
    DcmStack stack;
3224
    /* find sequence */
3225
0
    OFCondition status = search(seqTag, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
3226
0
    DcmSequenceOfItems *sequence = NULL;
3227
    /* sequence found? */
3228
0
    if (status.good() && stack.top()->isElement())
3229
0
    {
3230
        /* get element */
3231
0
        DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
3232
0
        if (delem != NULL)
3233
0
        {
3234
            /* check VR */
3235
0
            if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ))
3236
0
                sequence = OFstatic_cast(DcmSequenceOfItems *, delem);
3237
0
            else
3238
0
                status = EC_InvalidVR;
3239
0
        } else
3240
0
            status = EC_CorruptedData;
3241
0
    } else {
3242
        /* create new sequence element */
3243
0
        sequence = new DcmSequenceOfItems(seqTag);
3244
0
        if (sequence != NULL)
3245
0
        {
3246
            /* insert into item/dataset */
3247
0
            status = insert(sequence, OFTrue /*replaceOld*/);
3248
0
            if (status.bad())
3249
0
                delete sequence;
3250
0
        } else
3251
0
            status = EC_MemoryExhausted;
3252
0
    }
3253
0
    if (status.good())
3254
0
    {
3255
0
        if (sequence != NULL)
3256
0
        {
3257
0
            const unsigned long count = sequence->card();
3258
            /* existing item? */
3259
0
            if ((count > 0) && (itemNum >= -1) && (itemNum < OFstatic_cast(signed long, count)))
3260
0
            {
3261
0
                if (itemNum == -1)
3262
0
                {
3263
                    /* get last item */
3264
0
                    item = sequence->getItem(count - 1);
3265
0
                } else {
3266
                    /* get specified item */
3267
0
                    item = sequence->getItem(OFstatic_cast(unsigned long, itemNum));
3268
0
                }
3269
            /* create new item(s) */
3270
0
            } else {
3271
0
                unsigned long i = 0;
3272
                /* create empty trailing items if required */
3273
0
                const unsigned long itemCount = (itemNum > OFstatic_cast(signed long, count)) ? (itemNum - count + 1) : 1;
3274
0
                while ((i < itemCount) && status.good())
3275
0
                {
3276
0
                    item = new DcmItem();
3277
0
                    if (item != NULL)
3278
0
                    {
3279
                        /* append new item to end of sequence */
3280
0
                        status = sequence->append(item);
3281
0
                        if (status.bad())
3282
0
                            delete item;
3283
0
                    } else
3284
0
                        status = EC_MemoryExhausted;
3285
0
                    i++;
3286
0
                }
3287
0
            }
3288
0
        } else
3289
0
            status = EC_IllegalCall;
3290
0
    }
3291
    /* reset item value */
3292
0
    if (status.bad())
3293
0
        item = NULL;
3294
0
    else if (item == NULL)
3295
0
        status = EC_IllegalCall;
3296
0
    return status;
3297
0
}
3298
3299
3300
// ********************************
3301
3302
3303
/* --- findAndXXX functions: find an element and do something with it --- */
3304
3305
OFCondition DcmItem::findAndInsertCopyOfElement(const DcmTagKey &tagKey,
3306
                                                DcmItem *destItem,
3307
                                                const OFBool replaceOld)
3308
0
{
3309
0
    OFCondition status = EC_IllegalParameter;
3310
0
    if (destItem != NULL)
3311
0
    {
3312
0
        DcmElement *delem = NULL;
3313
        /* get copy of element from current dataset */
3314
0
        status = findAndGetElement(tagKey, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/);
3315
0
        if (status.good())
3316
0
        {
3317
            /* ... and insert it into the destination dataset */
3318
0
            status = destItem->insert(delem, replaceOld);
3319
0
            if (status.bad())
3320
0
                delete delem;
3321
0
        }
3322
0
    }
3323
0
    return status;
3324
0
}
3325
3326
3327
OFCondition DcmItem::findAndDeleteElement(const DcmTagKey &tagKey,
3328
                                          const OFBool allOccurrences,
3329
                                          const OFBool searchIntoSub)
3330
0
{
3331
0
    OFCondition status = EC_TagNotFound;
3332
0
    DcmStack stack;
3333
0
    DcmObject *object = NULL;
3334
0
    OFBool intoSub = OFTrue;
3335
    /* iterate over all elements */
3336
0
    while (nextObject(stack, intoSub).good())
3337
0
    {
3338
        /* get element */
3339
0
        object = stack.top();
3340
0
        if (object->getTag() == tagKey)
3341
0
        {
3342
0
            stack.pop();
3343
            /* remove element from dataset and free memory */
3344
0
            delete OFstatic_cast(DcmItem *, stack.top())->remove(object);
3345
0
            status = EC_Normal;
3346
            /* delete only the first element? */
3347
0
            if (!allOccurrences)
3348
0
                break;
3349
0
        }
3350
0
        intoSub = searchIntoSub || allOccurrences;
3351
0
    }
3352
0
    return status;
3353
0
}
3354
3355
3356
OFCondition DcmItem::findAndDeleteSequenceItem(const DcmTagKey &seqTagKey,
3357
                                               const signed long itemNum)
3358
0
{
3359
0
    DcmStack stack;
3360
    /* find sequence */
3361
0
    OFCondition status = search(seqTagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
3362
0
    if (status.good() && stack.top()->isElement())
3363
0
    {
3364
        /* get element */
3365
0
        DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
3366
0
        if (delem != NULL)
3367
0
        {
3368
            /* check VR */
3369
0
            if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ))
3370
0
            {
3371
0
                DcmSequenceOfItems *sequence = OFstatic_cast(DcmSequenceOfItems *, delem);
3372
0
                const unsigned long count = sequence->card();
3373
                /* last item? */
3374
0
                if (itemNum == -1)
3375
0
                    delete sequence->remove(count - 1);
3376
                /* valid item? */
3377
0
                else if ((itemNum >= 0) && (OFstatic_cast(unsigned long, itemNum) < count))
3378
0
                    delete sequence->remove(OFstatic_cast(unsigned long, itemNum));
3379
0
                else
3380
0
                    status = EC_IllegalParameter;
3381
0
            } else
3382
0
                status = EC_InvalidVR;
3383
0
        } else
3384
0
            status = EC_CorruptedData;
3385
0
    }
3386
0
    return status;
3387
0
}
3388
3389
3390
// ********************************
3391
3392
/* --- putAndInsert functions: put value and insert new element --- */
3393
3394
OFCondition DcmItem::putAndInsertString(const DcmTag &tag,
3395
                                        const char *value,
3396
                                        const OFBool replaceOld)
3397
0
{
3398
    /* determine length of the string value */
3399
0
    const Uint32 length = (value != NULL) ? OFstatic_cast(Uint32, strlen(value)) : 0;
3400
    /* call the real function */
3401
0
    return putAndInsertString(tag, value, length, replaceOld);
3402
0
}
3403
3404
3405
OFCondition DcmItem::putAndInsertString(const DcmTag &tag,
3406
                                        const char *value,
3407
                                        const Uint32 length,
3408
                                        const OFBool replaceOld)
3409
0
{
3410
0
    OFCondition status = EC_Normal;
3411
    /* create new element */
3412
0
    DcmElement *elem = NULL;
3413
0
    switch(tag.getEVR())
3414
0
    {
3415
0
        case EVR_AE:
3416
0
            elem = new DcmApplicationEntity(tag);
3417
0
            break;
3418
0
        case EVR_AS:
3419
0
            elem = new DcmAgeString(tag);
3420
0
            break;
3421
0
        case EVR_AT:
3422
0
            elem = new DcmAttributeTag(tag);
3423
0
            break;
3424
0
        case EVR_CS:
3425
0
            elem = new DcmCodeString(tag);
3426
0
            break;
3427
0
        case EVR_DA:
3428
0
            elem = new DcmDate(tag);
3429
0
            break;
3430
0
        case EVR_DS:
3431
0
            elem = new DcmDecimalString(tag);
3432
0
            break;
3433
0
        case EVR_DT:
3434
0
            elem = new DcmDateTime(tag);
3435
0
            break;
3436
0
        case EVR_FL:
3437
0
            elem = new DcmFloatingPointSingle(tag);
3438
0
            break;
3439
0
        case EVR_FD:
3440
0
            elem = new DcmFloatingPointDouble(tag);
3441
0
            break;
3442
0
        case EVR_IS:
3443
0
            elem = new DcmIntegerString(tag);
3444
0
            break;
3445
0
        case EVR_LO:
3446
0
            elem = new DcmLongString(tag);
3447
0
            break;
3448
0
        case EVR_LT:
3449
0
            elem = new DcmLongText(tag);
3450
0
            break;
3451
0
        case EVR_OB:
3452
0
        case EVR_OW:
3453
0
            elem = new DcmOtherByteOtherWord(tag);
3454
0
            break;
3455
0
        case EVR_OD:
3456
0
            elem = new DcmOtherDouble(tag);
3457
0
            break;
3458
0
        case EVR_OF:
3459
0
            elem = new DcmOtherFloat(tag);
3460
0
            break;
3461
0
        case EVR_OL:
3462
0
            elem = new DcmOtherLong(tag);
3463
0
            break;
3464
0
        case EVR_OV:
3465
0
            elem = new DcmOther64bitVeryLong(tag);
3466
0
            break;
3467
0
        case EVR_PN:
3468
0
            elem = new DcmPersonName(tag);
3469
0
            break;
3470
0
        case EVR_SH:
3471
0
            elem = new DcmShortString(tag);
3472
0
            break;
3473
0
        case EVR_SL:
3474
0
            elem = new DcmSignedLong(tag);
3475
0
            break;
3476
0
        case EVR_SS:
3477
0
            elem = new DcmSignedShort(tag);
3478
0
            break;
3479
0
        case EVR_ST:
3480
0
            elem = new DcmShortText(tag);
3481
0
            break;
3482
0
        case EVR_SV:
3483
0
            elem = new DcmSigned64bitVeryLong(tag);
3484
0
            break;
3485
0
        case EVR_TM:
3486
0
            elem = new DcmTime(tag);
3487
0
            break;
3488
0
        case EVR_UC:
3489
0
            elem = new DcmUnlimitedCharacters(tag);
3490
0
            break;
3491
0
        case EVR_UI:
3492
0
            elem = new DcmUniqueIdentifier(tag);
3493
0
            break;
3494
0
        case EVR_UL:
3495
0
            elem = new DcmUnsignedLong(tag);
3496
0
            break;
3497
0
        case EVR_UR:
3498
0
            elem = new DcmUniversalResourceIdentifierOrLocator(tag);
3499
0
            break;
3500
0
        case EVR_US:
3501
0
            elem = new DcmUnsignedShort(tag);
3502
0
            break;
3503
0
        case EVR_UT:
3504
0
            elem = new DcmUnlimitedText(tag);
3505
0
            break;
3506
0
        case EVR_UV:
3507
0
            elem = new DcmUnsigned64bitVeryLong(tag);
3508
0
            break;
3509
0
        case EVR_UNKNOWN:
3510
            /* Unknown VR, e.g. tag not found in data dictionary */
3511
0
            status = EC_UnknownVR;
3512
0
            break;
3513
0
        default:
3514
0
            status = EC_IllegalCall;
3515
0
            break;
3516
0
    }
3517
0
    if (elem != NULL)
3518
0
    {
3519
        /* put value */
3520
0
        status = elem->putString(value, length);
3521
        /* insert into dataset/item */
3522
0
        if (status.good())
3523
0
            status = insert(elem, replaceOld);
3524
        /* could not be inserted, therefore, delete it immediately */
3525
0
        if (status.bad())
3526
0
            delete elem;
3527
0
    } else if (status.good())
3528
0
        status = EC_MemoryExhausted;
3529
0
    return status;
3530
0
}
3531
3532
3533
OFCondition DcmItem::putAndInsertOFStringArray(const DcmTag &tag,
3534
                                               const OFString &value,
3535
                                               const OFBool replaceOld)
3536
0
{
3537
0
    OFCondition status = EC_Normal;
3538
    /* create new element */
3539
0
    DcmElement *elem = NULL;
3540
0
    switch(tag.getEVR())
3541
0
    {
3542
0
        case EVR_AE:
3543
0
            elem = new DcmApplicationEntity(tag);
3544
0
            break;
3545
0
        case EVR_AS:
3546
0
            elem = new DcmAgeString(tag);
3547
0
            break;
3548
0
        case EVR_CS:
3549
0
            elem = new DcmCodeString(tag);
3550
0
            break;
3551
0
        case EVR_DA:
3552
0
            elem = new DcmDate(tag);
3553
0
            break;
3554
0
        case EVR_DS:
3555
0
            elem = new DcmDecimalString(tag);
3556
0
            break;
3557
0
        case EVR_DT:
3558
0
            elem = new DcmDateTime(tag);
3559
0
            break;
3560
0
        case EVR_IS:
3561
0
            elem = new DcmIntegerString(tag);
3562
0
            break;
3563
0
        case EVR_LO:
3564
0
            elem = new DcmLongString(tag);
3565
0
            break;
3566
0
        case EVR_LT:
3567
0
            elem = new DcmLongText(tag);
3568
0
            break;
3569
0
        case EVR_PN:
3570
0
            elem = new DcmPersonName(tag);
3571
0
            break;
3572
0
        case EVR_SH:
3573
0
            elem = new DcmShortString(tag);
3574
0
            break;
3575
0
        case EVR_ST:
3576
0
            elem = new DcmShortText(tag);
3577
0
            break;
3578
0
        case EVR_TM:
3579
0
            elem = new DcmTime(tag);
3580
0
            break;
3581
0
        case EVR_UC:
3582
0
            elem = new DcmUnlimitedCharacters(tag);
3583
0
            break;
3584
0
        case EVR_UI:
3585
0
            elem = new DcmUniqueIdentifier(tag);
3586
0
            break;
3587
0
        case EVR_UR:
3588
0
            elem = new DcmUniversalResourceIdentifierOrLocator(tag);
3589
0
            break;
3590
0
        case EVR_UT:
3591
0
            elem = new DcmUnlimitedText(tag);
3592
0
            break;
3593
0
        case EVR_UNKNOWN:
3594
            /* Unknown VR, e.g. tag not found in data dictionary */
3595
0
            status = EC_UnknownVR;
3596
0
            break;
3597
0
        default:
3598
0
            status = EC_IllegalCall;
3599
0
            break;
3600
0
    }
3601
0
    if (elem != NULL)
3602
0
    {
3603
        /* put value */
3604
0
        status = elem->putOFStringArray(value);
3605
        /* insert into dataset/item */
3606
0
        if (status.good())
3607
0
            status = insert(elem, replaceOld);
3608
        /* could not be inserted, therefore, delete it immediately */
3609
0
        if (status.bad())
3610
0
            delete elem;
3611
0
    } else if (status.good())
3612
0
        status = EC_MemoryExhausted;
3613
0
    return status;
3614
0
}
3615
3616
3617
OFCondition DcmItem::putAndInsertUint8Array(const DcmTag &tag,
3618
                                            const Uint8 *value,
3619
                                            const unsigned long count,
3620
                                            const OFBool replaceOld)
3621
0
{
3622
0
    OFCondition status = EC_Normal;
3623
    /* create new element */
3624
0
    DcmElement *elem = NULL;
3625
0
    switch(tag.getEVR())
3626
0
    {
3627
0
        case EVR_OB:
3628
0
            elem = new DcmOtherByteOtherWord(tag);
3629
0
            break;
3630
0
        case EVR_ox:
3631
            /* special handling for Pixel Data */
3632
0
            if (tag == DCM_PixelData)
3633
0
            {
3634
0
                elem = new DcmPixelData(tag);
3635
0
                if (elem != NULL)
3636
0
                    elem->setVR(EVR_OB);
3637
0
            } else
3638
0
                elem = new DcmPolymorphOBOW(tag);
3639
0
            break;
3640
0
        case EVR_px:
3641
0
            elem = new DcmPixelData(tag);
3642
0
            if (elem != NULL)
3643
0
                elem->setVR(EVR_OB);
3644
0
            break;
3645
0
        case EVR_UNKNOWN:
3646
            /* Unknown VR, e.g. tag not found in data dictionary */
3647
0
            status = EC_UnknownVR;
3648
0
            break;
3649
0
        default:
3650
0
            status = EC_IllegalCall;
3651
0
            break;
3652
0
    }
3653
0
    if (elem != NULL)
3654
0
    {
3655
        /* put value */
3656
0
        status = elem->putUint8Array(value, count);
3657
        /* insert into dataset/item */
3658
0
        if (status.good())
3659
0
            status = insert(elem, replaceOld);
3660
        /* could not be inserted, therefore, delete it immediately */
3661
0
        if (status.bad())
3662
0
            delete elem;
3663
0
    } else if (status.good())
3664
0
        status = EC_MemoryExhausted;
3665
0
    return status;
3666
0
}
3667
3668
3669
OFCondition DcmItem::putAndInsertUint16(const DcmTag &tag,
3670
                                        const Uint16 value,
3671
                                        const unsigned long pos,
3672
                                        const OFBool replaceOld)
3673
0
{
3674
0
    OFCondition status = EC_Normal;
3675
    /* create new element */
3676
0
    DcmElement *elem = NULL;
3677
0
    switch(tag.getEVR())
3678
0
    {
3679
0
        case EVR_US:
3680
0
            elem = new DcmUnsignedShort(tag);
3681
0
            break;
3682
0
        case EVR_lt:
3683
0
        case EVR_xs:
3684
            /* special handling */
3685
0
            elem = new DcmUnsignedShort(DcmTag(tag, EVR_US));
3686
0
            break;
3687
0
        case EVR_UNKNOWN:
3688
            /* Unknown VR, e.g. tag not found in data dictionary */
3689
0
            status = EC_UnknownVR;
3690
0
            break;
3691
0
        default:
3692
0
            status = EC_IllegalCall;
3693
0
            break;
3694
0
    }
3695
0
    if (elem != NULL)
3696
0
    {
3697
        /* put value */
3698
0
        status = elem->putUint16(value, pos);
3699
        /* insert into dataset/item */
3700
0
        if (status.good())
3701
0
            status = insert(elem, replaceOld);
3702
        /* could not be inserted, therefore, delete it immediately */
3703
0
        if (status.bad())
3704
0
            delete elem;
3705
0
    } else if (status.good())
3706
0
        status = EC_MemoryExhausted;
3707
0
    return status;
3708
0
}
3709
3710
3711
OFCondition DcmItem::putAndInsertUint16Array(const DcmTag &tag,
3712
                                             const Uint16 *value,
3713
                                             const unsigned long count,
3714
                                             const OFBool replaceOld)
3715
0
{
3716
0
    OFCondition status = EC_Normal;
3717
    /* create new element */
3718
0
    DcmElement *elem = NULL;
3719
0
    switch(tag.getEVR())
3720
0
    {
3721
0
        case EVR_AT:
3722
0
            elem = new DcmAttributeTag(tag);
3723
0
            break;
3724
0
        case EVR_US:
3725
0
            elem = new DcmUnsignedShort(tag);
3726
0
            break;
3727
0
        case EVR_lt:
3728
0
        case EVR_OW:
3729
0
            elem = new DcmOtherByteOtherWord(tag);
3730
0
            break;
3731
0
        case EVR_ox:
3732
            /* special handling */
3733
0
            if (tag == DCM_PixelData)
3734
0
            {
3735
0
                elem = new DcmPixelData(tag);
3736
0
                if (elem != NULL)
3737
0
                    elem->setVR(EVR_OW);
3738
0
            } else
3739
0
                elem = new DcmPolymorphOBOW(tag);
3740
0
            break;
3741
0
        case EVR_px:
3742
0
            elem = new DcmPixelData(tag);
3743
0
            if (elem != NULL)
3744
0
                elem->setVR(EVR_OW);
3745
0
            break;
3746
0
        case EVR_xs:
3747
            /* special handling */
3748
0
            elem = new DcmUnsignedShort(DcmTag(tag, EVR_US));
3749
0
            break;
3750
0
        case EVR_UNKNOWN:
3751
            /* Unknown VR, e.g. tag not found in data dictionary */
3752
0
            status = EC_UnknownVR;
3753
0
            break;
3754
0
        default:
3755
0
            status = EC_IllegalCall;
3756
0
            break;
3757
0
    }
3758
0
    if (elem != NULL)
3759
0
    {
3760
        /* put value */
3761
0
        status = elem->putUint16Array(value, count);
3762
        /* insert into dataset/item */
3763
0
        if (status.good())
3764
0
            status = insert(elem, replaceOld);
3765
        /* could not be inserted, therefore, delete it immediately */
3766
0
        if (status.bad())
3767
0
            delete elem;
3768
0
    } else if (status.good())
3769
0
        status = EC_MemoryExhausted;
3770
0
    return status;
3771
0
}
3772
3773
3774
OFCondition DcmItem::putAndInsertSint16(const DcmTag &tag,
3775
                                        const Sint16 value,
3776
                                        const unsigned long pos,
3777
                                        const OFBool replaceOld)
3778
0
{
3779
0
    OFCondition status = EC_Normal;
3780
    /* create new element */
3781
0
    DcmElement *elem = NULL;
3782
0
    switch(tag.getEVR())
3783
0
    {
3784
0
        case EVR_SS:
3785
0
            elem = new DcmSignedShort(tag);
3786
0
            break;
3787
0
        case EVR_lt:
3788
0
        case EVR_xs:
3789
            /* special handling */
3790
0
            elem = new DcmSignedShort(DcmTag(tag, EVR_SS));
3791
0
            break;
3792
0
        case EVR_UNKNOWN:
3793
            /* Unknown VR, e.g. tag not found in data dictionary */
3794
0
            status = EC_UnknownVR;
3795
0
            break;
3796
0
        default:
3797
0
            status = EC_IllegalCall;
3798
0
            break;
3799
0
    }
3800
0
    if (elem != NULL)
3801
0
    {
3802
        /* put value */
3803
0
        status = elem->putSint16(value, pos);
3804
        /* insert into dataset/item */
3805
0
        if (status.good())
3806
0
            status = insert(elem, replaceOld);
3807
        /* could not be inserted, therefore, delete it immediately */
3808
0
        if (status.bad())
3809
0
            delete elem;
3810
0
    } else if (status.good())
3811
0
        status = EC_MemoryExhausted;
3812
0
    return status;
3813
0
}
3814
3815
3816
OFCondition DcmItem::putAndInsertSint16Array(const DcmTag &tag,
3817
                                             const Sint16 *value,
3818
                                             const unsigned long count,
3819
                                             const OFBool replaceOld)
3820
0
{
3821
0
    OFCondition status = EC_Normal;
3822
    /* create new element */
3823
0
    DcmElement *elem = NULL;
3824
0
    switch(tag.getEVR())
3825
0
    {
3826
0
        case EVR_SS:
3827
0
            elem = new DcmSignedShort(tag);
3828
0
            break;
3829
0
        case EVR_lt:
3830
0
        case EVR_xs:
3831
            /* special handling */
3832
0
            elem = new DcmSignedShort(DcmTag(tag, EVR_SS));
3833
0
            break;
3834
0
        case EVR_UNKNOWN:
3835
            /* Unknown VR, e.g. tag not found in data dictionary */
3836
0
            status = EC_UnknownVR;
3837
0
            break;
3838
0
        default:
3839
0
            status = EC_IllegalCall;
3840
0
            break;
3841
0
    }
3842
0
    if (elem != NULL)
3843
0
    {
3844
        /* put value */
3845
0
        status = elem->putSint16Array(value, count);
3846
        /* insert into dataset/item */
3847
0
        if (status.good())
3848
0
            status = insert(elem, replaceOld);
3849
        /* could not be inserted, therefore, delete it immediately */
3850
0
        if (status.bad())
3851
0
            delete elem;
3852
0
    } else if (status.good())
3853
0
        status = EC_MemoryExhausted;
3854
0
    return status;
3855
0
}
3856
3857
3858
OFCondition DcmItem::putAndInsertUint32(const DcmTag &tag,
3859
                                        const Uint32 value,
3860
                                        const unsigned long pos,
3861
                                        const OFBool replaceOld)
3862
0
{
3863
0
    OFCondition status = EC_Normal;
3864
    /* create new element */
3865
0
    DcmElement *elem = NULL;
3866
0
    switch(tag.getEVR())
3867
0
    {
3868
0
        case EVR_UL:
3869
0
            elem = new DcmUnsignedLong(tag);
3870
0
            break;
3871
0
        case EVR_OL:
3872
0
            elem = new DcmOtherLong(tag);
3873
0
            break;
3874
0
        case EVR_UNKNOWN:
3875
            /* Unknown VR, e.g. tag not found in data dictionary */
3876
0
            status = EC_UnknownVR;
3877
0
            break;
3878
0
        default:
3879
0
            status = EC_IllegalCall;
3880
0
            break;
3881
0
    }
3882
0
    if (elem != NULL)
3883
0
    {
3884
        /* put value */
3885
0
        status = elem->putUint32(value, pos);
3886
        /* insert into dataset/item */
3887
0
        if (status.good())
3888
0
            status = insert(elem, replaceOld);
3889
        /* could not be inserted, therefore, delete it immediately */
3890
0
        if (status.bad())
3891
0
            delete elem;
3892
0
    } else if (status.good())
3893
0
        status = EC_MemoryExhausted;
3894
0
    return status;
3895
0
}
3896
3897
3898
OFCondition DcmItem::putAndInsertUint32Array(const DcmTag &tag,
3899
                                             const Uint32 *value,
3900
                                             const unsigned long count,
3901
                                             const OFBool replaceOld)
3902
0
{
3903
0
    OFCondition status = EC_Normal;
3904
    /* create new element */
3905
0
    DcmElement *elem = NULL;
3906
0
    switch(tag.getEVR())
3907
0
    {
3908
0
        case EVR_UL:
3909
0
            elem = new DcmUnsignedLong(tag);
3910
0
            break;
3911
0
        case EVR_OL:
3912
0
            elem = new DcmOtherLong(tag);
3913
0
            break;
3914
0
        case EVR_UNKNOWN:
3915
            /* Unknown VR, e.g. tag not found in data dictionary */
3916
0
            status = EC_UnknownVR;
3917
0
            break;
3918
0
        default:
3919
0
            status = EC_IllegalCall;
3920
0
            break;
3921
0
    }
3922
0
    if (elem != NULL)
3923
0
    {
3924
        /* put value */
3925
0
        status = elem->putUint32Array(value, count);
3926
        /* insert into dataset/item */
3927
0
        if (status.good())
3928
0
            status = insert(elem, replaceOld);
3929
        /* could not be inserted, therefore, delete it immediately */
3930
0
        if (status.bad())
3931
0
            delete elem;
3932
0
    } else if (status.good())
3933
0
        status = EC_MemoryExhausted;
3934
0
    return status;
3935
0
}
3936
3937
3938
OFCondition DcmItem::putAndInsertSint32(const DcmTag &tag,
3939
                                        const Sint32 value,
3940
                                        const unsigned long pos,
3941
                                        const OFBool replaceOld)
3942
0
{
3943
0
    OFCondition status = EC_Normal;
3944
    /* create new element */
3945
0
    DcmElement *elem = NULL;
3946
0
    switch(tag.getEVR())
3947
0
    {
3948
0
        case EVR_SL:
3949
0
            elem = new DcmSignedLong(tag);
3950
0
            break;
3951
0
        case EVR_UNKNOWN:
3952
            /* Unknown VR, e.g. tag not found in data dictionary */
3953
0
            status = EC_UnknownVR;
3954
0
            break;
3955
0
        default:
3956
0
            status = EC_IllegalCall;
3957
0
            break;
3958
0
    }
3959
0
    if (elem != NULL)
3960
0
    {
3961
        /* put value */
3962
0
        status = elem->putSint32(value, pos);
3963
        /* insert into dataset/item */
3964
0
        if (status.good())
3965
0
            status = insert(elem, replaceOld);
3966
        /* could not be inserted, therefore, delete it immediately */
3967
0
        if (status.bad())
3968
0
            delete elem;
3969
0
    } else if (status.good())
3970
0
        status = EC_MemoryExhausted;
3971
0
    return status;
3972
0
}
3973
3974
3975
OFCondition DcmItem::putAndInsertSint32Array(const DcmTag &tag,
3976
                                             const Sint32 *value,
3977
                                             const unsigned long count,
3978
                                             const OFBool replaceOld)
3979
0
{
3980
0
    OFCondition status = EC_Normal;
3981
    /* create new element */
3982
0
    DcmElement *elem = NULL;
3983
0
    switch(tag.getEVR())
3984
0
    {
3985
0
        case EVR_SL:
3986
0
            elem = new DcmSignedLong(tag);
3987
0
            break;
3988
0
        case EVR_UNKNOWN:
3989
            /* Unknown VR, e.g. tag not found in data dictionary */
3990
0
            status = EC_UnknownVR;
3991
0
            break;
3992
0
        default:
3993
0
            status = EC_IllegalCall;
3994
0
            break;
3995
0
    }
3996
0
    if (elem != NULL)
3997
0
    {
3998
        /* put value */
3999
0
        status = elem->putSint32Array(value, count);
4000
        /* insert into dataset/item */
4001
0
        if (status.good())
4002
0
            status = insert(elem, replaceOld);
4003
        /* could not be inserted, therefore, delete it immediately */
4004
0
        if (status.bad())
4005
0
            delete elem;
4006
0
    } else if (status.good())
4007
0
        status = EC_MemoryExhausted;
4008
0
    return status;
4009
0
}
4010
4011
4012
OFCondition DcmItem::putAndInsertUint64(const DcmTag &tag,
4013
                                        const Uint64 value,
4014
                                        const unsigned long pos,
4015
                                        const OFBool replaceOld)
4016
0
{
4017
0
    OFCondition status = EC_Normal;
4018
    /* create new element */
4019
0
    DcmElement *elem = NULL;
4020
0
    switch(tag.getEVR())
4021
0
    {
4022
0
        case EVR_UV:
4023
0
            elem = new DcmUnsigned64bitVeryLong(tag);
4024
0
            break;
4025
0
        case EVR_OV:
4026
0
            elem = new DcmOther64bitVeryLong(tag);
4027
0
            break;
4028
0
        case EVR_UNKNOWN:
4029
            /* Unknown VR, e.g. tag not found in data dictionary */
4030
0
            status = EC_UnknownVR;
4031
0
            break;
4032
0
        default:
4033
0
            status = EC_IllegalCall;
4034
0
            break;
4035
0
    }
4036
0
    if (elem != NULL)
4037
0
    {
4038
        /* put value */
4039
0
        status = elem->putUint64(value, pos);
4040
        /* insert into dataset/item */
4041
0
        if (status.good())
4042
0
            status = insert(elem, replaceOld);
4043
        /* could not be inserted, therefore, delete it immediately */
4044
0
        if (status.bad())
4045
0
            delete elem;
4046
0
    } else if (status.good())
4047
0
        status = EC_MemoryExhausted;
4048
0
    return status;
4049
0
}
4050
4051
4052
OFCondition DcmItem::putAndInsertUint64Array(const DcmTag &tag,
4053
                                             const Uint64 *value,
4054
                                             const unsigned long count,
4055
                                             const OFBool replaceOld)
4056
0
{
4057
0
    OFCondition status = EC_Normal;
4058
    /* create new element */
4059
0
    DcmElement *elem = NULL;
4060
0
    switch(tag.getEVR())
4061
0
    {
4062
0
        case EVR_UV:
4063
0
            elem = new DcmUnsigned64bitVeryLong(tag);
4064
0
            break;
4065
0
        case EVR_OV:
4066
0
            elem = new DcmOther64bitVeryLong(tag);
4067
0
            break;
4068
0
        case EVR_UNKNOWN:
4069
            /* Unknown VR, e.g. tag not found in data dictionary */
4070
0
            status = EC_UnknownVR;
4071
0
            break;
4072
0
        default:
4073
0
            status = EC_IllegalCall;
4074
0
            break;
4075
0
    }
4076
0
    if (elem != NULL)
4077
0
    {
4078
        /* put value */
4079
0
        status = elem->putUint64Array(value, count);
4080
        /* insert into dataset/item */
4081
0
        if (status.good())
4082
0
            status = insert(elem, replaceOld);
4083
        /* could not be inserted, therefore, delete it immediately */
4084
0
        if (status.bad())
4085
0
            delete elem;
4086
0
    } else if (status.good())
4087
0
        status = EC_MemoryExhausted;
4088
0
    return status;
4089
0
}
4090
4091
4092
OFCondition DcmItem::putAndInsertSint64(const DcmTag &tag,
4093
                                        const Sint64 value,
4094
                                        const unsigned long pos,
4095
                                        const OFBool replaceOld)
4096
0
{
4097
0
    OFCondition status = EC_Normal;
4098
    /* create new element */
4099
0
    DcmElement *elem = NULL;
4100
0
    switch(tag.getEVR())
4101
0
    {
4102
0
        case EVR_SV:
4103
0
            elem = new DcmSigned64bitVeryLong(tag);
4104
0
            break;
4105
0
        case EVR_UNKNOWN:
4106
            /* Unknown VR, e.g. tag not found in data dictionary */
4107
0
            status = EC_UnknownVR;
4108
0
            break;
4109
0
        default:
4110
0
            status = EC_IllegalCall;
4111
0
            break;
4112
0
    }
4113
0
    if (elem != NULL)
4114
0
    {
4115
        /* put value */
4116
0
        status = elem->putSint64(value, pos);
4117
        /* insert into dataset/item */
4118
0
        if (status.good())
4119
0
            status = insert(elem, replaceOld);
4120
        /* could not be inserted, therefore, delete it immediately */
4121
0
        if (status.bad())
4122
0
            delete elem;
4123
0
    } else if (status.good())
4124
0
        status = EC_MemoryExhausted;
4125
0
    return status;
4126
0
}
4127
4128
4129
OFCondition DcmItem::putAndInsertSint64Array(const DcmTag &tag,
4130
                                             const Sint64 *value,
4131
                                             const unsigned long count,
4132
                                             const OFBool replaceOld)
4133
0
{
4134
0
    OFCondition status = EC_Normal;
4135
    /* create new element */
4136
0
    DcmElement *elem = NULL;
4137
0
    switch(tag.getEVR())
4138
0
    {
4139
0
        case EVR_SV:
4140
0
            elem = new DcmSigned64bitVeryLong(tag);
4141
0
            break;
4142
0
        case EVR_UNKNOWN:
4143
            /* Unknown VR, e.g. tag not found in data dictionary */
4144
0
            status = EC_UnknownVR;
4145
0
            break;
4146
0
        default:
4147
0
            status = EC_IllegalCall;
4148
0
            break;
4149
0
    }
4150
0
    if (elem != NULL)
4151
0
    {
4152
        /* put value */
4153
0
        status = elem->putSint64Array(value, count);
4154
        /* insert into dataset/item */
4155
0
        if (status.good())
4156
0
            status = insert(elem, replaceOld);
4157
        /* could not be inserted, therefore, delete it immediately */
4158
0
        if (status.bad())
4159
0
            delete elem;
4160
0
    } else if (status.good())
4161
0
        status = EC_MemoryExhausted;
4162
0
    return status;
4163
0
}
4164
4165
4166
OFCondition DcmItem::putAndInsertFloat32(const DcmTag &tag,
4167
                                         const Float32 value,
4168
                                         const unsigned long pos,
4169
                                         const OFBool replaceOld)
4170
0
{
4171
0
    OFCondition status = EC_Normal;
4172
    /* create new element */
4173
0
    DcmElement *elem = NULL;
4174
0
    switch(tag.getEVR())
4175
0
    {
4176
0
        case EVR_FL:
4177
0
            elem = new DcmFloatingPointSingle(tag);
4178
0
            break;
4179
0
        case EVR_OF:
4180
0
            elem = new DcmOtherFloat(tag);
4181
0
            break;
4182
0
        case EVR_UNKNOWN:
4183
            /* Unknown VR, e.g. tag not found in data dictionary */
4184
0
            status = EC_UnknownVR;
4185
0
            break;
4186
0
        default:
4187
0
            status = EC_IllegalCall;
4188
0
            break;
4189
0
    }
4190
0
    if (elem != NULL)
4191
0
    {
4192
        /* put value */
4193
0
        status = elem->putFloat32(value, pos);
4194
        /* insert into dataset/item */
4195
0
        if (status.good())
4196
0
            status = insert(elem, replaceOld);
4197
        /* could not be inserted, therefore, delete it immediately */
4198
0
        if (status.bad())
4199
0
            delete elem;
4200
0
    } else if (status.good())
4201
0
        status = EC_MemoryExhausted;
4202
0
    return status;
4203
0
}
4204
4205
4206
OFCondition DcmItem::putAndInsertFloat32Array(const DcmTag &tag,
4207
                                              const Float32 *value,
4208
                                              const unsigned long count,
4209
                                              const OFBool replaceOld)
4210
0
{
4211
0
    OFCondition status = EC_Normal;
4212
    /* create new element */
4213
0
    DcmElement *elem = NULL;
4214
0
    switch(tag.getEVR())
4215
0
    {
4216
0
        case EVR_FL:
4217
0
            elem = new DcmFloatingPointSingle(tag);
4218
0
            break;
4219
0
        case EVR_OF:
4220
0
            elem = new DcmOtherFloat(tag);
4221
0
            break;
4222
0
        case EVR_UNKNOWN:
4223
            /* Unknown VR, e.g. tag not found in data dictionary */
4224
0
            status = EC_UnknownVR;
4225
0
            break;
4226
0
        default:
4227
0
            status = EC_IllegalCall;
4228
0
            break;
4229
0
    }
4230
0
    if (elem != NULL)
4231
0
    {
4232
        /* put value */
4233
0
        status = elem->putFloat32Array(value, count);
4234
        /* insert into dataset/item */
4235
0
        if (status.good())
4236
0
            status = insert(elem, replaceOld);
4237
        /* could not be inserted, therefore, delete it immediately */
4238
0
        if (status.bad())
4239
0
            delete elem;
4240
0
    } else if (status.good())
4241
0
        status = EC_MemoryExhausted;
4242
0
    return status;
4243
0
}
4244
4245
4246
OFCondition DcmItem::putAndInsertFloat64(const DcmTag &tag,
4247
                                         const Float64 value,
4248
                                         const unsigned long pos,
4249
                                         const OFBool replaceOld)
4250
0
{
4251
0
    OFCondition status = EC_Normal;
4252
    /* create new element */
4253
0
    DcmElement *elem = NULL;
4254
0
    switch(tag.getEVR())
4255
0
    {
4256
0
        case EVR_DS:
4257
0
            elem = new DcmDecimalString(tag);
4258
0
            break;
4259
0
        case EVR_FD:
4260
0
            elem = new DcmFloatingPointDouble(tag);
4261
0
            break;
4262
0
        case EVR_OD:
4263
0
            elem = new DcmOtherDouble(tag);
4264
0
            break;
4265
0
        case EVR_UNKNOWN:
4266
            /* Unknown VR, e.g. tag not found in data dictionary */
4267
0
            status = EC_UnknownVR;
4268
0
            break;
4269
0
        default:
4270
0
            status = EC_IllegalCall;
4271
0
            break;
4272
0
    }
4273
0
    if (elem != NULL)
4274
0
    {
4275
        /* put value */
4276
0
        status = elem->putFloat64(value, pos);
4277
        /* insert into dataset/item */
4278
0
        if (status.good())
4279
0
            status = insert(elem, replaceOld);
4280
        /* could not be inserted, therefore, delete it immediately */
4281
0
        if (status.bad())
4282
0
            delete elem;
4283
0
    } else if (status.good())
4284
0
        status = EC_MemoryExhausted;
4285
0
    return status;
4286
0
}
4287
4288
4289
OFCondition DcmItem::putAndInsertFloat64Array(const DcmTag &tag,
4290
                                              const Float64 *value,
4291
                                              const unsigned long count,
4292
                                              const OFBool replaceOld)
4293
0
{
4294
0
    OFCondition status = EC_Normal;
4295
    /* create new element */
4296
0
    DcmElement *elem = NULL;
4297
0
    switch(tag.getEVR())
4298
0
    {
4299
0
        case EVR_FD:
4300
0
            elem = new DcmFloatingPointDouble(tag);
4301
0
            break;
4302
0
        case EVR_OD:
4303
0
            elem = new DcmOtherDouble(tag);
4304
0
            break;
4305
0
        case EVR_UNKNOWN:
4306
            /* Unknown VR, e.g. tag not found in data dictionary */
4307
0
            status = EC_UnknownVR;
4308
0
            break;
4309
0
        default:
4310
0
            status = EC_IllegalCall;
4311
0
            break;
4312
0
    }
4313
0
    if (elem != NULL)
4314
0
    {
4315
        /* put value */
4316
0
        status = elem->putFloat64Array(value, count);
4317
        /* insert into dataset/item */
4318
0
        if (status.good())
4319
0
            status = insert(elem, replaceOld);
4320
        /* could not be inserted, therefore, delete it immediately */
4321
0
        if (status.bad())
4322
0
            delete elem;
4323
0
    } else if (status.good())
4324
0
        status = EC_MemoryExhausted;
4325
0
    return status;
4326
0
}
4327
4328
4329
OFCondition DcmItem::putAndInsertTagKey(const DcmTag &tag,
4330
                                        const DcmTagKey &value,
4331
                                        const unsigned long pos,
4332
                                        const OFBool replaceOld)
4333
0
{
4334
0
    OFCondition status = EC_Normal;
4335
    /* create new element */
4336
0
    DcmElement *elem = NULL;
4337
0
    switch(tag.getEVR())
4338
0
    {
4339
0
        case EVR_AT:
4340
0
            elem = new DcmAttributeTag(tag);
4341
0
            break;
4342
0
        case EVR_UNKNOWN:
4343
            /* Unknown VR, e.g. tag not found in data dictionary */
4344
0
            status = EC_UnknownVR;
4345
0
            break;
4346
0
        default:
4347
0
            status = EC_IllegalCall;
4348
0
            break;
4349
0
    }
4350
0
    if (elem != NULL)
4351
0
    {
4352
        /* put value */
4353
0
        status = elem->putTagVal(value, pos);
4354
        /* insert into dataset/item */
4355
0
        if (status.good())
4356
0
            status = insert(elem, replaceOld);
4357
        /* could not be inserted, therefore, delete it immediately */
4358
0
        if (status.bad())
4359
0
            delete elem;
4360
0
    } else if (status.good())
4361
0
        status = EC_MemoryExhausted;
4362
0
    return status;
4363
0
}
4364
4365
4366
// ********************************
4367
4368
4369
OFCondition DcmItem::insertEmptyElement(const DcmTag &tag,
4370
                                        const OFBool replaceOld)
4371
0
{
4372
0
    OFCondition status = EC_Normal;
4373
    /* create new element */
4374
0
    DcmElement *elem = NULL;
4375
0
    switch(tag.getEVR())
4376
0
    {
4377
0
        case EVR_AE:
4378
0
            elem = new DcmApplicationEntity(tag);
4379
0
            break;
4380
0
        case EVR_AS:
4381
0
            elem = new DcmAgeString(tag);
4382
0
            break;
4383
0
        case EVR_AT:
4384
0
            elem = new DcmAttributeTag(tag);
4385
0
            break;
4386
0
        case EVR_CS:
4387
0
            elem = new DcmCodeString(tag);
4388
0
            break;
4389
0
        case EVR_DA:
4390
0
            elem = new DcmDate(tag);
4391
0
            break;
4392
0
        case EVR_DS:
4393
0
            elem = new DcmDecimalString(tag);
4394
0
            break;
4395
0
        case EVR_DT:
4396
0
            elem = new DcmDateTime(tag);
4397
0
            break;
4398
0
        case EVR_FL:
4399
0
            elem = new DcmFloatingPointSingle(tag);
4400
0
            break;
4401
0
        case EVR_FD:
4402
0
            elem = new DcmFloatingPointDouble(tag);
4403
0
            break;
4404
0
        case EVR_IS:
4405
0
            elem = new DcmIntegerString(tag);
4406
0
            break;
4407
0
        case EVR_LO:
4408
0
            elem = new DcmLongString(tag);
4409
0
            break;
4410
0
        case EVR_LT:
4411
0
            elem = new DcmLongText(tag);
4412
0
            break;
4413
0
        case EVR_OB:
4414
0
        case EVR_OW:
4415
0
            elem = new DcmOtherByteOtherWord(tag);
4416
0
            break;
4417
0
        case EVR_OD:
4418
0
            elem = new DcmOtherDouble(tag);
4419
0
            break;
4420
0
        case EVR_OF:
4421
0
            elem = new DcmOtherFloat(tag);
4422
0
            break;
4423
0
        case EVR_OL:
4424
0
            elem = new DcmOtherLong(tag);
4425
0
            break;
4426
0
        case EVR_OV:
4427
0
            elem = new DcmOther64bitVeryLong(tag);
4428
0
            break;
4429
0
        case EVR_PN:
4430
0
            elem = new DcmPersonName(tag);
4431
0
            break;
4432
0
        case EVR_SH:
4433
0
            elem = new DcmShortString(tag);
4434
0
            break;
4435
0
        case EVR_SL:
4436
0
            elem = new DcmSignedLong(tag);
4437
0
            break;
4438
0
        case EVR_SQ:
4439
0
            elem = new DcmSequenceOfItems(tag);
4440
0
            break;
4441
0
        case EVR_SS:
4442
0
            elem = new DcmSignedShort(tag);
4443
0
            break;
4444
0
        case EVR_ST:
4445
0
            elem = new DcmShortText(tag);
4446
0
            break;
4447
0
        case EVR_SV:
4448
0
            elem = new DcmSigned64bitVeryLong(tag);
4449
0
            break;
4450
0
        case EVR_TM:
4451
0
            elem = new DcmTime(tag);
4452
0
            break;
4453
0
        case EVR_UC:
4454
0
            elem = new DcmUnlimitedCharacters(tag);
4455
0
            break;
4456
0
        case EVR_UI:
4457
0
            elem = new DcmUniqueIdentifier(tag);
4458
0
            break;
4459
0
        case EVR_UL:
4460
0
            elem = new DcmUnsignedLong(tag);
4461
0
            break;
4462
0
        case EVR_UR:
4463
0
            elem = new DcmUniversalResourceIdentifierOrLocator(tag);
4464
0
            break;
4465
0
        case EVR_US:
4466
0
            elem = new DcmUnsignedShort(tag);
4467
0
            break;
4468
0
        case EVR_UT:
4469
0
            elem = new DcmUnlimitedText(tag);
4470
0
            break;
4471
0
        case EVR_UV:
4472
0
            elem = new DcmUnsigned64bitVeryLong(tag);
4473
0
            break;
4474
0
        case EVR_PixelData:
4475
0
            elem = new DcmPixelData(tag);
4476
            // set VR to OW to make sure that we never write/send the internal VR
4477
0
            if (elem) elem->setVR(EVR_OW);
4478
0
            break;
4479
0
        case EVR_OverlayData:
4480
0
            elem = new DcmOverlayData(tag);
4481
            // set VR to OW to make sure that we never write/send the internal VR
4482
0
            if (elem) elem->setVR(EVR_OW);
4483
0
            break;
4484
0
        case EVR_UNKNOWN:
4485
            /* Unknown VR, e.g. tag not found in data dictionary */
4486
0
            status = EC_UnknownVR;
4487
0
            break;
4488
0
        default:
4489
0
            status = EC_IllegalCall;
4490
0
            break;
4491
0
    }
4492
0
    if (elem != NULL)
4493
0
    {
4494
        /* insert new element into dataset/item */
4495
0
        status = insert(elem, replaceOld);
4496
        /* could not be inserted, therefore, delete it immediately */
4497
0
        if (status.bad())
4498
0
            delete elem;
4499
0
    } else if (status.good())
4500
0
        status = EC_MemoryExhausted;
4501
0
    return status;
4502
0
}
4503
4504
4505
OFCondition DcmItem::insertSequenceItem(const DcmTag &seqTag,
4506
                                        DcmItem *item,
4507
                                        const signed long itemNum)
4508
0
{
4509
0
    OFCondition status = EC_IllegalParameter;
4510
0
    if (item != NULL)
4511
0
    {
4512
0
        DcmStack stack;
4513
        /* find sequence */
4514
0
        status = search(seqTag, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
4515
0
        DcmSequenceOfItems *sequence = NULL;
4516
        /* sequence found? */
4517
0
        if (status.good() && stack.top()->isElement())
4518
0
        {
4519
            /* get element */
4520
0
            DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
4521
0
            if (delem != NULL)
4522
0
            {
4523
                /* check VR */
4524
0
                if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ))
4525
0
                    sequence = OFstatic_cast(DcmSequenceOfItems *, delem);
4526
0
                else
4527
0
                    status = EC_InvalidVR;
4528
0
            } else
4529
0
                status = EC_CorruptedData;
4530
0
        } else {
4531
            /* create new sequence element */
4532
0
            sequence = new DcmSequenceOfItems(seqTag);
4533
0
            if (sequence != NULL)
4534
0
            {
4535
                /* insert into item/dataset */
4536
0
                status = insert(sequence, OFTrue /*replaceOld*/);
4537
0
                if (status.bad())
4538
0
                    delete sequence;
4539
0
            } else
4540
0
                status = EC_MemoryExhausted;
4541
0
        }
4542
0
        if (status.good())
4543
0
        {
4544
0
            if (sequence != NULL)
4545
0
            {
4546
0
                const unsigned long count = sequence->card();
4547
                /* 'itemNum' specifies and existing item? */
4548
0
                if ((count > 0) && (itemNum >= -1) && (itemNum < OFstatic_cast(signed long, count)))
4549
0
                {
4550
0
                    if (itemNum == -1)
4551
0
                    {
4552
                        /* insert given item before last entry */
4553
0
                        status = sequence->insert(item, DCM_EndOfListIndex, OFTrue /*before*/);
4554
0
                    } else {
4555
                        /* insert given item before specified entry */
4556
0
                        status = sequence->insert(item, OFstatic_cast(unsigned long, itemNum), OFTrue /*before*/);
4557
0
                    }
4558
                /* create empty item(s) and append */
4559
0
                } else {
4560
0
                    DcmItem *newItem = NULL;
4561
0
                    unsigned long i = 0;
4562
                    /* create empty trailing items if required */
4563
0
                    const unsigned long itemCount = (itemNum > OFstatic_cast(signed long, count)) ? (itemNum - count) : 0;
4564
0
                    while ((i < itemCount) && status.good())
4565
0
                    {
4566
0
                        newItem = new DcmItem();
4567
0
                        if (newItem != NULL)
4568
0
                        {
4569
                            /* append new item to end of sequence */
4570
0
                            status = sequence->append(newItem);
4571
0
                            if (status.bad())
4572
0
                                delete newItem;
4573
0
                        } else
4574
0
                            status = EC_MemoryExhausted;
4575
0
                        i++;
4576
0
                    }
4577
                    /* append given item to end of sequence */
4578
0
                    status = sequence->append(item);
4579
0
                }
4580
0
            } else
4581
0
                status = EC_IllegalCall;
4582
0
        }
4583
0
    }
4584
0
    return status;
4585
0
}
4586
4587
4588
// ********************************
4589
4590
4591
OFBool DcmItem::containsUnknownVR() const
4592
0
{
4593
0
    if (!elementList->empty())
4594
0
    {
4595
0
        elementList->seek(ELP_first);
4596
0
        do {
4597
0
            if (elementList->get()->containsUnknownVR())
4598
0
                return OFTrue;
4599
0
        } while (elementList->seek(ELP_next));
4600
0
    }
4601
0
    return OFFalse;
4602
0
}
4603
4604
4605
OFBool DcmItem::containsExtendedCharacters(const OFBool checkAllStrings)
4606
0
{
4607
0
    if (!elementList->empty())
4608
0
    {
4609
0
        elementList->seek(ELP_first);
4610
0
        do {
4611
0
            if (elementList->get()->containsExtendedCharacters(checkAllStrings))
4612
0
                return OFTrue;
4613
0
        } while (elementList->seek(ELP_next));
4614
0
    }
4615
0
    return OFFalse;
4616
0
}
4617
4618
4619
OFBool DcmItem::isAffectedBySpecificCharacterSet() const
4620
0
{
4621
0
    if (!elementList->empty())
4622
0
    {
4623
0
        elementList->seek(ELP_first);
4624
0
        do {
4625
0
            if (elementList->get()->isAffectedBySpecificCharacterSet())
4626
0
                return OFTrue;
4627
0
        } while (elementList->seek(ELP_next));
4628
0
    }
4629
0
    return OFFalse;
4630
0
}
4631
4632
4633
// ********************************
4634
4635
4636
void DcmItem::updateSpecificCharacterSet(OFCondition &status,
4637
                                         const DcmSpecificCharacterSet &converter)
4638
0
{
4639
0
    const OFString encoding = converter.getDestinationEncoding();
4640
0
    if (status.good())
4641
0
    {
4642
        // check whether the attribute Specific Character Set (0008,0005) should be present at all
4643
0
        if (checkForSpecificCharacterSet())
4644
0
        {
4645
0
            const OFString toCharset = converter.getDestinationCharacterSet();
4646
            // check for default character set (ASCII), also make sure that the value "ISO_IR 6" is never used
4647
            // in a dataset; open question: should we also check for non-ASCII characters in the element value?
4648
0
            if (toCharset.empty() || (toCharset == "ISO_IR 6"))
4649
0
            {
4650
                // delete Specific Character Set (0008,0005) data element (type 1C)
4651
0
                if (findAndDeleteElement(DCM_SpecificCharacterSet, OFFalse /*allOccurrences*/, OFFalse /*searchIntoSub*/).good())
4652
0
                {
4653
0
                    DCMDATA_DEBUG("DcmItem::updateSpecificCharacterSet() deleted element SpecificCharacterSet "
4654
0
                        << DCM_SpecificCharacterSet << " during the conversion to " << encoding << " encoding");
4655
0
                }
4656
0
            } else {
4657
0
                DCMDATA_DEBUG("DcmItem::updateSpecificCharacterSet() updating value of element SpecificCharacterSet "
4658
0
                    << DCM_SpecificCharacterSet << " to '" << toCharset << "'");
4659
                // update/set value of Specific Character Set (0008,0005) if needed
4660
0
                status = putAndInsertOFStringArray(DCM_SpecificCharacterSet, toCharset);
4661
0
            }
4662
0
        } else {
4663
            // otherwise delete it (if present)
4664
0
            if (findAndDeleteElement(DCM_SpecificCharacterSet, OFFalse /*allOccurrences*/, OFFalse /*searchIntoSub*/).good())
4665
0
            {
4666
0
                DCMDATA_WARN("DcmItem: Deleted element SpecificCharacterSet " << DCM_SpecificCharacterSet
4667
0
                    << " during the conversion to " << encoding << " encoding");
4668
0
            }
4669
0
        }
4670
0
    } else {
4671
        // an error occurred in a previous processing step
4672
0
        DCMDATA_WARN("DcmItem: An error occurred during the conversion to " << encoding << " encoding, "
4673
0
            << "the value of SpecificCharacterSet " << DCM_SpecificCharacterSet << " is not updated");
4674
0
    }
4675
0
}
4676
4677
4678
OFCondition DcmItem::convertCharacterSet(const OFString &fromCharset,
4679
                                         const OFString &toCharset,
4680
                                         const size_t flags,
4681
                                         const OFBool updateCharset)
4682
0
{
4683
0
    OFCondition status = EC_Normal;
4684
    // if the item is empty, there is nothing to do
4685
0
    if (!elementList->empty())
4686
0
    {
4687
0
        DcmSpecificCharacterSet converter;
4688
        // create a new character set converter
4689
0
        DCMDATA_DEBUG("DcmItem::convertCharacterSet() creating a new character set converter for '"
4690
0
            << fromCharset << "'" << (fromCharset.empty() ? " (ASCII)" : "") << " to '"
4691
0
            << toCharset << "'" << (toCharset.empty() ? " (ASCII)" : ""));
4692
        // select source and destination character set
4693
0
        status = converter.selectCharacterSet(fromCharset, toCharset);
4694
0
        if (status.good())
4695
0
        {
4696
0
            unsigned cflags = 0;
4697
            /* pass flags to underlying implementation */
4698
0
            if (flags & DCMTypes::CF_discardIllegal)
4699
0
                cflags |= OFCharacterEncoding::DiscardIllegalSequences;
4700
0
            if (flags & DCMTypes::CF_transliterate)
4701
0
                cflags |= OFCharacterEncoding::TransliterateIllegalSequences;
4702
0
            if (cflags > 0)
4703
0
                status = converter.setConversionFlags(cflags);
4704
0
            if (status.good())
4705
0
            {
4706
                // convert all affected element values in the item
4707
0
                status = convertCharacterSet(converter);
4708
0
                if (updateCharset)
4709
0
                {
4710
                    // update the Specific Character Set (0008,0005) element
4711
0
                    updateSpecificCharacterSet(status, converter);
4712
0
                }
4713
0
            }
4714
0
        }
4715
0
    }
4716
0
    return status;
4717
0
}
4718
4719
4720
OFCondition DcmItem::convertCharacterSet(const OFString &toCharset,
4721
                                         const size_t flags,
4722
                                         const OFBool ignoreCharset)
4723
0
{
4724
0
    OFString fromCharset;
4725
    // check whether this item can contain the attribute SpecificCharacterSet (0008,0005)
4726
0
    if (checkForSpecificCharacterSet() && !ignoreCharset)
4727
0
    {
4728
        // determine value of Specific Character Set (0008,0005) if present in this item
4729
0
        findAndGetOFStringArray(DCM_SpecificCharacterSet, fromCharset, OFFalse /*searchIntoSub*/);
4730
0
    }
4731
    // do the real work, if Specific Character Set is missing or empty use the default (ASCII)
4732
0
    return convertCharacterSet(fromCharset, toCharset, flags, !ignoreCharset /*updateCharset*/);
4733
0
}
4734
4735
4736
OFCondition DcmItem::convertCharacterSet(DcmSpecificCharacterSet &converter)
4737
0
{
4738
0
    OFCondition status = EC_Normal;
4739
    // if the item is empty, there is nothing to do
4740
0
    if (!elementList->empty())
4741
0
    {
4742
        // iterate over all data elements in this item and convert the strings
4743
0
        elementList->seek(ELP_first);
4744
0
        do {
4745
0
            status = elementList->get()->convertCharacterSet(converter);
4746
0
        } while (status.good() && elementList->seek(ELP_next));
4747
0
    }
4748
0
    return status;
4749
0
}
4750
4751
4752
OFCondition DcmItem::convertToUTF8()
4753
0
{
4754
    // the DICOM defined term "ISO_IR 192" is used for "UTF-8"
4755
0
    return convertCharacterSet("ISO_IR 192", 0 /*flags*/);
4756
0
}
4757
4758
4759
// ********************************
4760
4761
4762
DcmElement* DcmItem::newDicomElement(const DcmTagKey& tag,
4763
                                     const char *privateCreator)
4764
0
{
4765
0
  DcmTag temp(tag, privateCreator);
4766
0
  DcmElement* elem = NULL;
4767
0
  OFBool readAsUN = OFFalse;
4768
0
  newDicomElement(
4769
0
      elem,
4770
0
      temp,
4771
0
      0,          // Length
4772
0
      NULL,       // Private creator
4773
0
      readAsUN);  // read as VR UN (result ignored)
4774
0
  return elem;
4775
0
}
4776
4777
4778
OFCondition DcmItem::newDicomElementWithVR(DcmElement*& newElement, const DcmTag& tag)
4779
0
{
4780
0
  DcmTag temp(tag);
4781
0
  OFBool readAsUN = OFFalse;
4782
0
  return newDicomElement(
4783
0
      newElement,
4784
0
      temp,
4785
0
      0,          // Length
4786
0
      NULL,       // Private creator
4787
0
      readAsUN);  // read as VR UN (result ignored)
4788
0
}
4789
4790
4791
OFCondition DcmItem::newDicomElement(DcmElement*& newElement,
4792
                                     const DcmTagKey& tag,
4793
                                     const char *privateCreator)
4794
0
{
4795
0
    DcmTag temp(tag, privateCreator);
4796
0
    newElement = NULL;
4797
0
    OFBool readAsUN = OFFalse;
4798
0
    return newDicomElement(
4799
0
        newElement,
4800
0
        temp,
4801
0
        0,          // Length
4802
0
        NULL,       // Private creator
4803
0
        readAsUN);  // read as VR UN (result ignored)
4804
0
}
4805
4806
4807
OFCondition DcmItem::newDicomElement(DcmElement *&newElement,
4808
                                     DcmTag &tag,
4809
                                     const Uint32 length,
4810
                                     DcmPrivateTagCache *privateCreatorCache,
4811
                                     OFBool& readAsUN)
4812
304k
{
4813
    /* initialize variables */
4814
304k
    OFCondition l_error = EC_Normal;
4815
304k
    newElement = NULL;
4816
304k
    DcmEVR evr = tag.getEVR();
4817
304k
    readAsUN = OFFalse;
4818
4819
    /* revert UN elements with finite length back to known VR if possible */
4820
304k
    if ((evr == EVR_UN) && (length != DCM_UndefinedLength) && dcmEnableUnknownVRConversion.get())
4821
0
    {
4822
        /* look up VR in data dictionary */
4823
0
        DcmTag newTag(tag.getGroup(), tag.getElement());
4824
4825
        /* special handling for private elements */
4826
0
        if (privateCreatorCache && (newTag.getGroup() & 1) && (newTag.getElement() >= 0x1000))
4827
0
        {
4828
0
            const char *pc = privateCreatorCache->findPrivateCreator(newTag);
4829
0
            if (pc != NULL)
4830
0
            {
4831
                // we have a private creator for this element
4832
0
                newTag.setPrivateCreator(pc);
4833
0
                newTag.lookupVRinDictionary();
4834
0
            }
4835
0
        }
4836
4837
        /* update VR for tag, set "readAsUN" flag that makes sure the element value
4838
         * is read in Little Endian Implicit VR (i.e. the UN encoding)
4839
         */
4840
0
        if (newTag.getEVR() != EVR_UNKNOWN)
4841
0
        {
4842
0
            DCMDATA_DEBUG("DcmItem::newDicomElement() reverted VR of element " << tag
4843
0
                << " from 'UN' to '" << newTag.getVRName() << "'");
4844
0
            tag.setVR(newTag.getVR());
4845
0
            evr = tag.getEVR();
4846
0
            readAsUN = OFTrue;
4847
0
        }
4848
0
    }
4849
4850
    /* depending on the VR of the tag which was passed, create the new object */
4851
304k
    switch (evr)
4852
304k
    {
4853
        // byte strings:
4854
4.14k
        case EVR_AE :
4855
4.14k
            newElement = new DcmApplicationEntity(tag, length);
4856
4.14k
            break;
4857
4.74k
        case EVR_AS :
4858
4.74k
            newElement = new DcmAgeString(tag, length);
4859
4.74k
            break;
4860
16.8k
        case EVR_CS :
4861
16.8k
            newElement = new DcmCodeString(tag, length);
4862
16.8k
            break;
4863
5.16k
        case EVR_DA :
4864
5.16k
            newElement = new DcmDate(tag, length);
4865
5.16k
            break;
4866
9.36k
        case EVR_DS :
4867
9.36k
            newElement = new DcmDecimalString(tag, length);
4868
9.36k
            break;
4869
4.63k
        case EVR_DT :
4870
4.63k
            newElement = new DcmDateTime(tag, length);
4871
4.63k
            break;
4872
2.36k
        case EVR_IS :
4873
2.36k
            newElement = new DcmIntegerString(tag, length);
4874
2.36k
            break;
4875
7.48k
        case EVR_TM :
4876
7.48k
            newElement = new DcmTime(tag, length);
4877
7.48k
            break;
4878
16.7k
        case EVR_UI :
4879
16.7k
            newElement = new DcmUniqueIdentifier(tag, length);
4880
16.7k
            break;
4881
1.84k
        case EVR_UR:
4882
1.84k
            newElement = new DcmUniversalResourceIdentifierOrLocator(tag, length);
4883
1.84k
            break;
4884
4885
        // character strings:
4886
5.36k
        case EVR_LO :
4887
5.36k
            newElement = new DcmLongString(tag, length);
4888
5.36k
            break;
4889
5.63k
        case EVR_LT :
4890
5.63k
            newElement = new DcmLongText(tag, length);
4891
5.63k
            break;
4892
3.85k
        case EVR_PN :
4893
3.85k
            newElement = new DcmPersonName(tag, length);
4894
3.85k
            break;
4895
11.9k
        case EVR_SH :
4896
11.9k
            newElement = new DcmShortString(tag, length);
4897
11.9k
            break;
4898
3.80k
        case EVR_ST :
4899
3.80k
            newElement = new DcmShortText(tag, length);
4900
3.80k
            break;
4901
1.20k
        case EVR_UC:
4902
1.20k
            newElement = new DcmUnlimitedCharacters(tag, length);
4903
1.20k
            break;
4904
737
        case EVR_UT:
4905
737
            newElement = new DcmUnlimitedText(tag, length);
4906
737
            break;
4907
4908
        // dependent on byte order:
4909
2.56k
        case EVR_AT :
4910
2.56k
            newElement = new DcmAttributeTag(tag, length);
4911
2.56k
            break;
4912
5.07k
        case EVR_SS :
4913
5.07k
            newElement = new DcmSignedShort(tag, length);
4914
5.07k
            break;
4915
975
        case EVR_xs : // according to DICOM standard
4916
2.96k
        case EVR_US :
4917
2.96k
            newElement = new DcmUnsignedShort(tag, length);
4918
2.96k
            break;
4919
1.02k
        case EVR_SL :
4920
1.02k
            newElement = new DcmSignedLong(tag, length);
4921
1.02k
            break;
4922
499
        case EVR_up : // for (0004,eeee) according to DICOM standard
4923
30.6k
        case EVR_UL :
4924
30.6k
            {
4925
                // generate tag with VR from dictionary!
4926
30.6k
                DcmTag ulupTag(tag.getTagKey());
4927
30.6k
                if (ulupTag.getEVR() == EVR_up)
4928
0
                    newElement = new DcmUnsignedLongOffset(ulupTag, length);
4929
30.6k
                else
4930
30.6k
                    newElement = new DcmUnsignedLong(tag, length);
4931
30.6k
            }
4932
30.6k
            break;
4933
1.10k
        case EVR_OL :
4934
1.10k
            newElement = new DcmOtherLong(tag, length);
4935
1.10k
            break;
4936
784
        case EVR_SV :
4937
784
            newElement = new DcmSigned64bitVeryLong(tag, length);
4938
784
            break;
4939
1.74k
        case EVR_UV :
4940
1.74k
            newElement = new DcmUnsigned64bitVeryLong(tag, length);
4941
1.74k
            break;
4942
1.19k
        case EVR_OV :
4943
1.19k
            newElement = new DcmOther64bitVeryLong(tag, length);
4944
1.19k
            break;
4945
2.69k
        case EVR_FL :
4946
2.69k
            newElement = new DcmFloatingPointSingle(tag, length);
4947
2.69k
            break;
4948
1.63k
        case EVR_FD :
4949
1.63k
            newElement = new DcmFloatingPointDouble(tag, length);
4950
1.63k
            break;
4951
550
        case EVR_OF :
4952
550
            newElement = new DcmOtherFloat(tag, length);
4953
550
            break;
4954
1.31k
        case EVR_OD :
4955
1.31k
            newElement = new DcmOtherDouble(tag, length);
4956
1.31k
            break;
4957
4958
        // sequences and items:
4959
18.2k
        case EVR_SQ :
4960
18.2k
            newElement = new DcmSequenceOfItems(tag, length, readAsUN);
4961
18.2k
            break;
4962
2.85k
        case EVR_na :
4963
2.85k
            if (tag == DCM_Item)
4964
51
                l_error = EC_InvalidTag;
4965
2.80k
            else if (tag == DCM_SequenceDelimitationItem)
4966
17
                l_error = EC_SequEnd;
4967
2.78k
            else if (tag == DCM_ItemDelimitationItem)
4968
2.65k
                l_error = EC_ItemEnd;
4969
132
            else
4970
132
                l_error = EC_InvalidTag;
4971
2.85k
            break;
4972
4973
        // pixel sequences (EVR_pixelSQ) are handled through class DcmPixelData
4974
        // and should never appear here.
4975
4976
        // unclear 8 or 16 bit:
4977
3.01k
        case EVR_ox :
4978
3.01k
            if (tag == DCM_PixelData)
4979
872
                newElement = new DcmPixelData(tag, length);
4980
2.13k
            else if (tag.getBaseTag() == DCM_OverlayData)
4981
484
                newElement = new DcmOverlayData(tag, length);
4982
1.65k
            else
4983
                /* we don't know this element's real transfer syntax, so we just
4984
                 * use the defaults of class DcmOtherByteOtherWord and let the
4985
                 * application handle it.
4986
                 */
4987
1.65k
                newElement = new DcmOtherByteOtherWord(tag, length);
4988
3.01k
            break;
4989
4990
2.71k
        case EVR_px :
4991
2.71k
            newElement = new DcmPixelData(tag, length);
4992
2.71k
            break;
4993
4994
        // This case should only occur if we encounter an element with an invalid
4995
        // "Pi" VR. Make sure this does not cause problems later on
4996
0
        case EVR_PixelData :
4997
0
            newElement = new DcmPixelData(tag, length);
4998
            // set VR to OW to make sure that we never write/send the internal VR
4999
0
            if (newElement) newElement->setVR(EVR_OW);
5000
0
            break;
5001
5002
        // This case should only occur if we encounter an element with an invalid
5003
        // "Ov" VR. Make sure this does not cause problems later on
5004
0
        case EVR_OverlayData :
5005
0
            newElement = new DcmOverlayData(tag, length);
5006
            // set VR to OW to make sure that we never write/send the internal VR
5007
0
            if (newElement) newElement->setVR(EVR_OW);
5008
0
            break;
5009
5010
242
        case EVR_lt :
5011
242
            newElement = new DcmOtherByteOtherWord(tag, length);
5012
242
            break;
5013
5014
4.34k
        case EVR_OB :
5015
14.7k
        case EVR_OW :
5016
14.7k
            if (tag == DCM_PixelData)
5017
7.16k
                newElement = new DcmPixelData(tag, length);
5018
7.60k
            else if (tag.getBaseTag() == DCM_OverlayData)
5019
761
                newElement = new DcmOverlayData(tag, length);
5020
6.83k
            else if ((tag == DCM_VOILUTSequence) && (length != DCM_UndefinedLength))
5021
88
            {
5022
                // this is an incorrectly encoded VOI LUT Sequence.
5023
                // Real-world examples of this issue have been reported in 2016.
5024
88
                if (dcmConvertVOILUTSequenceOWtoSQ.get())
5025
0
                {
5026
                    // Silently fix the error by interpreting as a sequence.
5027
0
                    DcmTag newTag(tag);
5028
0
                    newTag.setVR(DcmVR(EVR_SQ)); // on writing we will handle this element as SQ, not OB/OW
5029
0
                    newElement = new DcmSequenceOfItems(newTag, length);
5030
88
                } else {
5031
5032
88
                    if (dcmIgnoreParsingErrors.get())
5033
0
                    {
5034
                        // ignore parse error, keep VR unchanged
5035
0
                        DCMDATA_WARN("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered");
5036
0
                        newElement = new DcmOtherByteOtherWord(tag, length);
5037
0
                    }
5038
88
                    else
5039
88
                    {
5040
                        // bail out with an error
5041
88
                        DCMDATA_ERROR("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered");
5042
88
                        l_error = EC_VOI_LUT_OBOW;
5043
88
                    }
5044
88
                }
5045
88
            }
5046
6.75k
            else if (tag.isPrivate())
5047
1.99k
            {
5048
                // look up VR in private data dictionary
5049
1.99k
                DcmTag newTag(tag.getTagKey(), tag.getPrivateCreator());
5050
                // special handling for private pixel data (compressed or uncompressed)
5051
1.99k
                if (newTag.getEVR() == EVR_px)
5052
0
                {
5053
0
                    if (length == DCM_UndefinedLength)
5054
0
                    {
5055
0
                        DCMDATA_WARN("DcmItem: Found private element " << tag << " with VR=" << tag.getVRName()
5056
0
                            << " and undefined length, reading a pixel sequence according to data dictionary");
5057
0
                    }
5058
0
                    newElement = new DcmPixelData(tag, length);
5059
0
                }
5060
1.99k
            }
5061
            // no element has been created yet and no error reported
5062
14.7k
            if ((newElement == NULL) && l_error.good())
5063
6.75k
            {
5064
6.75k
                if (length == DCM_UndefinedLength)
5065
22
                {
5066
                    // The attribute is OB or OW but is encoded with undefined
5067
                    // length, and it is not Pixel Data. This is illegal.
5068
22
                    if (dcmConvertUndefinedLengthOBOWtoSQ.get())
5069
0
                    {
5070
                        // Assume that this is in fact a sequence so that we can
5071
                        // catch the sequence delimitation item.
5072
0
                        DcmTag newTag(tag);
5073
0
                        newTag.setVR(DcmVR(EVR_SQ)); // on writing we will handle this element as SQ, not OB/OW
5074
0
                        newElement = new DcmSequenceOfItems(newTag, length);
5075
22
                    } else {
5076
22
                        if (dcmIgnoreParsingErrors.get())
5077
0
                        {
5078
                            // ignore parse error, keep VR unchanged
5079
0
                            OFCondition tempcond = EC_UndefinedLengthOBOW;
5080
0
                            DCMDATA_WARN("DcmItem: Parse error in " << tag << ": " << tempcond.text());
5081
0
                            newElement = new DcmSequenceOfItems(tag, length);
5082
22
                        } else {
5083
                            // bail out with an error
5084
22
                            l_error = EC_UndefinedLengthOBOW;
5085
22
                            DCMDATA_ERROR("DcmItem: Parse error in " << tag << ": " << l_error.text());
5086
22
                        }
5087
22
                    }
5088
6.72k
                } else {
5089
                    // default case
5090
6.72k
                    newElement = new DcmOtherByteOtherWord(tag, length);
5091
6.72k
                }
5092
6.75k
            }
5093
14.7k
            break;
5094
5095
        // read unknown types as byte string:
5096
41.2k
        case EVR_UNKNOWN :
5097
102k
        case EVR_UNKNOWN2B :
5098
103k
        case EVR_UN :
5099
103k
            if (length == DCM_UndefinedLength)
5100
8.81k
            {
5101
                // The attribute VR is UN with undefined length. Assume it is really
5102
                // a sequence so that we can catch the sequence delimitation item.
5103
8.81k
                DcmTag newTag(tag);
5104
8.81k
                newTag.setVR(DcmVR(EVR_SQ)); // on writing we will handle this element as SQ, not UN
5105
8.81k
                if (dcmEnableCP246Support.get())
5106
8.81k
                {
5107
8.81k
                    DCMDATA_WARN("DcmItem: Found element " << newTag << " with VR=UN and undefined length, "
5108
8.81k
                        << "reading a sequence with transfer syntax LittleEndianImplicit (CP-246)");
5109
8.81k
                } else {
5110
0
                    DCMDATA_WARN("DcmItem: Found element " << newTag << " with VR=UN and undefined length");
5111
0
                }
5112
8.81k
                newElement = new DcmSequenceOfItems(newTag, length, dcmEnableCP246Support.get());
5113
94.4k
            } else {
5114
                // defined length UN element, treat like OB
5115
94.4k
                newElement = new DcmOtherByteOtherWord(tag, length);
5116
94.4k
            }
5117
103k
            break;
5118
5119
        // these types should never occur
5120
0
        case EVR_item :
5121
0
        case EVR_metainfo :
5122
0
        case EVR_dataset :
5123
0
        case EVR_fileFormat :
5124
0
        case EVR_dicomDir :
5125
0
        case EVR_dirRecord :
5126
0
        case EVR_pixelSQ :
5127
5
        case EVR_pixelItem :
5128
444
        case EVR_invalid :
5129
444
            l_error = EC_IllegalCall;
5130
444
            break;
5131
5132
        // we deliberately have no default clause to make sure a warning is raised
5133
        // when an DcmEVR enum is not explicitly handled here
5134
304k
    }
5135
5136
    /* check for valid element pointer */
5137
304k
    if (l_error.good() && (newElement == NULL))
5138
0
        l_error = EC_MemoryExhausted;
5139
5140
    /* return result value */
5141
304k
    return l_error;
5142
304k
}