]> Creatis software - gdcm.git/blob - src/gdcmSeqEntry.cxx
8f5e4731c6dc33e6745d1c507fbcd904653812a1
[gdcm.git] / src / gdcmSeqEntry.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmSeqEntry.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/08/24 03:42:40 $
7   Version:   $Revision: 1.57 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmSeqEntry.h"
20 #include "gdcmSQItem.h"
21 #include "gdcmValEntry.h"
22 #include "gdcmTS.h"
23 #include "gdcmGlobal.h"
24 #include "gdcmUtil.h"
25 #include "gdcmDebug.h"
26
27 #include <iostream>
28 #include <iomanip>
29 #include <fstream>
30
31 namespace gdcm 
32 {
33 //-----------------------------------------------------------------------------
34 // Constructor / Destructor
35 /**
36  * \brief   Constructor from a given SeqEntry
37  */
38 SeqEntry::SeqEntry( DictEntry *e ) 
39              : DocEntry(e)
40 {
41    Length       = 0;
42    ReadLength   = 0xffffffff;
43    SQDepthLevel = -1;
44
45    DelimitorMode = false;
46    SeqTerm  = NULL;
47 }
48
49 /**
50  * \brief   Constructor from a given DocEntry
51  * @param   e Pointer to existing Doc entry
52  * @param   depth depth level of the current Seq entry
53  */
54 SeqEntry::SeqEntry( DocEntry *e, int depth )
55              : DocEntry( e->GetDictEntry() )
56 {
57    Length       = 0;
58    ReadLength   = 0xffffffff;
59    SQDepthLevel = depth;
60
61    ImplicitVR   = e->IsImplicitVR();
62    Offset       = e->GetOffset();
63    SeqTerm = NULL;
64 }
65
66 /**
67  * \brief   Canonical destructor.
68  */
69 SeqEntry::~SeqEntry()
70 {
71    ClearSQItem();
72 }
73
74 //-----------------------------------------------------------------------------
75 // Public
76 /*
77  * \brief   canonical Writer
78  * @param fp pointer to an already open file
79  * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
80  */
81 void SeqEntry::WriteContent(std::ofstream *fp, FileType filetype)
82 {
83    uint16_t seq_term_gr = 0xfffe;
84    uint16_t seq_term_el = 0xe0dd;
85    uint32_t seq_term_lg = 0xffffffff;
86
87    //uint16_t item_term_gr = 0xfffe;
88    //uint16_t item_term_el = 0xe00d;
89    
90    DocEntry::WriteContent(fp, filetype);
91    for(ListSQItem::iterator cc  = Items.begin();
92                             cc != Items.end();
93                           ++cc)
94    {        
95       (*cc)->WriteContent(fp, filetype);
96    }
97    
98    // we force the writting of a Sequence Delimitation item
99    // because we wrote the Sequence as a 'no Length' sequence
100    binary_write(*fp, seq_term_gr);
101    binary_write(*fp, seq_term_el);
102    binary_write(*fp, seq_term_lg);
103 }
104
105 /**
106  * \brief   adds the passed ITEM to the ITEM chained List for this SeQuence.
107  * @param sqItem SQItem to be pushed back in the SeqEntry
108  * @param itemNumber ordinal number of the SQItem
109  *  \note NOT end-user intendend method !
110  */
111 void SeqEntry::AddSQItem(SQItem *sqItem, int itemNumber)
112 {
113 // FIXME : SQItemNumber is supposed to be the ordinal number of the SQItem
114 //         within the Sequence.
115 //         Either only 'push_back' is allowed, 
116 //                and we just have to do something like SeqEntry::lastNb++
117 //         Or we can add (or remove) anywhere, and SQItemNumber will be broken
118    sqItem->SetSQItemNumber(itemNumber);
119    Items.push_back(sqItem);
120 }
121
122 /**
123  * \brief Remove all SQItem.
124  */
125 void SeqEntry::ClearSQItem()
126 {
127    for(ListSQItem::iterator cc = Items.begin(); cc != Items.end(); ++cc)
128    {
129       delete *cc;
130    }
131    if (SeqTerm)
132    {
133       delete SeqTerm;
134    }
135 }
136
137 /**
138  * \brief   Get the first entry while visiting the SeqEntry
139  * \return  The first SQItem if found, otherwhise NULL
140  */ 
141 SQItem *SeqEntry::GetFirstSQItem()
142 {
143    ItSQItem = Items.begin();
144    if (ItSQItem != Items.end())
145       return *ItSQItem;
146    return NULL;
147
148
149 /**
150  * \brief   Get the next SQItem while visiting the SeqEntry
151  * \note : meaningfull only if GetFirstEntry already called
152  * \return  The next SQItem if found, otherwhise NULL
153  */
154
155 SQItem *SeqEntry::GetNextSQItem()
156 {
157    gdcmAssertMacro (ItSQItem != Items.end())
158    {
159       ++ItSQItem;
160       if (ItSQItem != Items.end())
161          return *ItSQItem;
162    }
163    return NULL;
164 }
165  
166 /**
167  * \brief return a pointer to the SQItem referenced by its ordinal number.
168  *        Returns the first item when argument is negative.
169  *        Returns the  last item when argument is bigger than the total
170  *        item number.
171  */
172 SQItem *SeqEntry::GetSQItem(int nb)
173 {
174    if (nb<0)
175    {
176       return *(Items.begin());
177    }
178    int count = 0 ;
179    for(ListSQItem::iterator cc = Items.begin();
180                            cc != Items.end();
181                            count ++, ++cc)
182    {
183       if (count == nb)
184       {
185          return *cc;
186       }
187    }
188    return *(Items.end());
189 }
190
191 /**
192  * \brief returns the number of SQItems within the current Sequence
193  */
194 unsigned int SeqEntry::GetNumberOfSQItems()
195 {
196    return Items.size();
197 }
198
199 //-----------------------------------------------------------------------------
200 // Protected
201
202
203 //-----------------------------------------------------------------------------
204 // Private
205
206 //-----------------------------------------------------------------------------
207 // Print
208 /**
209  * \brief   canonical Printer
210  */
211 void SeqEntry::Print( std::ostream &os, std::string const & )
212 {
213    // First, Print the Dicom Element itself.
214    os << "S ";
215    DocEntry::Print(os);
216    os << std::endl;
217
218    if (GetReadLength() == 0)
219       return;
220
221    // Then, Print each SQ Item   
222    for(ListSQItem::iterator cc = Items.begin(); cc != Items.end(); ++cc)
223    {
224       (*cc)->SetPrintLevel(PrintLevel);
225       (*cc)->Print(os);   
226    }
227
228    // at end, print the sequence terminator item, if any
229    if (DelimitorMode)
230    {
231       int i;
232       for ( i = 0; i < SQDepthLevel; i++ )
233          os << "   | " ;
234       os << " --- "  << std::endl;
235       for ( i = 0; i < SQDepthLevel; i++ )
236          os << "   | " ;
237       if (SeqTerm != NULL)
238       {
239          SeqTerm->SetPrintLevel(PrintLevel);
240          SeqTerm->Print(os);
241          os << std::endl;
242       } 
243       else 
244       {
245          // fuse
246          gdcmWarningMacro("  -------- should have a sequence terminator item");
247       }
248    }
249 }
250
251 //-----------------------------------------------------------------------------
252 } // end namespace gdcm