Coverage Report

Created: 2026-06-05 06:37

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