]> Creatis software - gdcm.git/blob - src/gdcmSeqEntry.cxx
* Some classes inherit now from gdcm::RefCounter
[gdcm.git] / src / gdcmSeqEntry.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmSeqEntry.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/10/25 14:52:35 $
7   Version:   $Revision: 1.60 $
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 "gdcmTS.h"
22 #include "gdcmGlobal.h"
23 #include "gdcmUtil.h"
24 #include "gdcmDebug.h"
25
26 #include <iostream>
27 #include <iomanip>
28 #include <fstream>
29
30 namespace gdcm 
31 {
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 /**
35  * \brief   Constructor from a given SeqEntry
36  */
37 SeqEntry::SeqEntry( DictEntry *e ) 
38              : DocEntry(e)
39 {
40    Length       = 0;
41    ReadLength   = 0xffffffff;
42    SQDepthLevel = -1;
43
44    DelimitorMode = false;
45    SeqTerm  = NULL;
46 }
47
48 /**
49  * \brief   Constructor from a given DocEntry
50  * @param   e Pointer to existing Doc entry
51  * @param   depth depth level of the current Seq entry
52  */
53 SeqEntry::SeqEntry( DocEntry *e, int depth )
54              : DocEntry( e->GetDictEntry() )
55 {
56    Length       = 0;
57    ReadLength   = 0xffffffff;
58    SQDepthLevel = depth;
59
60    ImplicitVR   = e->IsImplicitVR();
61    Offset       = e->GetOffset();
62    SeqTerm = NULL;
63 }
64
65 /**
66  * \brief   Canonical destructor.
67  */
68 SeqEntry::~SeqEntry()
69 {
70    ClearSQItem();
71 }
72
73 //-----------------------------------------------------------------------------
74 // Public
75 /*
76  * \brief   canonical Writer
77  * @param fp pointer to an already open file
78  * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
79  */
80 void SeqEntry::WriteContent(std::ofstream *fp, FileType filetype)
81 {
82    uint16_t seq_term_gr = 0xfffe;
83    uint16_t seq_term_el = 0xe0dd;
84    uint32_t seq_term_lg = 0xffffffff;
85
86    //uint16_t item_term_gr = 0xfffe;
87    //uint16_t item_term_el = 0xe00d;
88    
89    DocEntry::WriteContent(fp, filetype);
90    for(ListSQItem::iterator cc  = Items.begin();
91                             cc != Items.end();
92                           ++cc)
93    {        
94       (*cc)->WriteContent(fp, filetype);
95    }
96    
97    // we force the writting of a Sequence Delimitation item
98    // because we wrote the Sequence as a 'no Length' sequence
99    binary_write(*fp, seq_term_gr);
100    binary_write(*fp, seq_term_el);
101    binary_write(*fp, seq_term_lg);
102 }
103
104 /**
105  * \brief   adds the passed ITEM to the ITEM chained List for this SeQuence.
106  * @param sqItem SQItem to be pushed back in the SeqEntry
107  * @param itemNumber ordinal number of the SQItem
108  *  \note NOT end-user intendend method !
109  */
110 void SeqEntry::AddSQItem(SQItem *sqItem, int itemNumber)
111 {
112 // FIXME : SQItemNumber is supposed to be the ordinal number of the SQItem
113 //         within the Sequence.
114 //         Either only 'push_back' is allowed, 
115 //                and we just have to do something like SeqEntry::lastNb++
116 //         Or we can add (or remove) anywhere, and SQItemNumber will be broken
117    sqItem->SetSQItemNumber(itemNumber);
118    Items.push_back(sqItem);
119    sqItem->Register();
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       (*cc)->Unregister();
130    }
131    if (SeqTerm)
132    {
133       SeqTerm->Unregister();
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  * \brief Sets the Sequence Delimitation Item
201  * \param e Delimitation item
202  */
203 void SeqEntry::SetDelimitationItem(DocEntry *e)
204 {
205    if( SeqTerm != e )
206    {
207       if( SeqTerm )
208          SeqTerm->Unregister();
209       SeqTerm = e;
210       if( SeqTerm )
211          SeqTerm->Register();
212    }
213 }
214
215 //-----------------------------------------------------------------------------
216 // Protected
217
218
219 //-----------------------------------------------------------------------------
220 // Private
221
222 //-----------------------------------------------------------------------------
223 // Print
224 /**
225  * \brief   canonical Printer
226  */
227 void SeqEntry::Print( std::ostream &os, std::string const & )
228 {
229    // First, Print the Dicom Element itself.
230    os << "S ";
231    DocEntry::Print(os);
232    os << std::endl;
233
234    if (GetReadLength() == 0)
235       return;
236
237    // Then, Print each SQ Item   
238    for(ListSQItem::iterator cc = Items.begin(); cc != Items.end(); ++cc)
239    {
240       (*cc)->SetPrintLevel(PrintLevel);
241       (*cc)->Print(os);   
242    }
243
244    // at end, print the sequence terminator item, if any
245    if (DelimitorMode)
246    {
247       int i;
248       for ( i = 0; i < SQDepthLevel; i++ )
249          os << "   | " ;
250       os << " --- "  << std::endl;
251       for ( i = 0; i < SQDepthLevel; i++ )
252          os << "   | " ;
253       if (SeqTerm != NULL)
254       {
255          SeqTerm->SetPrintLevel(PrintLevel);
256          SeqTerm->Print(os);
257          os << std::endl;
258       } 
259       else 
260       {
261          // fuse
262          gdcmWarningMacro("  -------- should have a sequence terminator item");
263       }
264    }
265 }
266
267 //-----------------------------------------------------------------------------
268 } // end namespace gdcm