]> Creatis software - gdcm.git/blobdiff - src/gdcmElementSet.cxx
Coding Style + Doxygenation
[gdcm.git] / src / gdcmElementSet.cxx
index 33325c3fda8ba30b71857eac771eaf988534e90b..ef76254bd4c62f1d6f7d06518aab23f8f1acf821 100644 (file)
-// gdcmElementSet.cxx
-//-----------------------------------------------------------------------------
-//
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmElementSet.cxx,v $
+  Language:  C++
+  Date:      $Date: 2005/01/06 20:03:27 $
+  Version:   $Revision: 1.36 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
 #include "gdcmElementSet.h"
-#include "gdcmTS.h"
+#include "gdcmDebug.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmSeqEntry.h"
 
+namespace gdcm 
+{
 
 //-----------------------------------------------------------------------------
 // Constructor / Destructor
 /**
- * \ingroup gdcmElementSet
- * \brief   Constructor from a given gdcmElementSet
+ * \ingroup ElementSet
+ * \brief   Constructor from a given ElementSet
  */
-gdcmDocEntrySet::gdcmDocEntrySet() {
-
+//BOZ depthLevel is not usefull anymore
+ElementSet::ElementSet(int depthLevel) 
+              : DocEntrySet()
+{
+  (void)depthLevel;
 }
 
 /**
- * \ingroup gdcmElementSet
+ * \ingroup ElementSet
  * \brief   Canonical destructor.
  */
-gdcmElementSet::~gdcmElementSet() 
+ElementSet::~ElementSet() 
 {
-/*   for(tous les DocEntry)
+   for(TagDocEntryHT::iterator cc = TagHT.begin();cc != TagHT.end(); ++cc)
    {
-      delete *cc;
+      if ( cc->second )
+      {
+         delete cc->second;
+      }
    }
-   */
+   TagHT.clear();
 }
 
+//-----------------------------------------------------------------------------
+// Print
+/**
+  * \brief   Prints the Header Entries (Dicom Elements)
+  *          from the H Table
+  * @return
+  */ 
+void ElementSet::Print(std::ostream &os)
+{
+   for( TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i)
+   {
+      DocEntry* entry = i->second;
+
+      entry->SetPrintLevel(PrintLevel);
+      entry->Print(os);   
+
+      if ( SeqEntry *seqEntry = dynamic_cast<SeqEntry*>(entry) )
+      {
+         (void)seqEntry;
+         // Avoid the newline for a sequence:
+         continue;
+      }
+      os << std::endl;
+   }
+}
 
 //-----------------------------------------------------------------------------
 // Public
-
+/**
+  * \brief   Writes the Header Entries (Dicom Elements)
+  *          from the H Table
+  * @return
+  */ 
+void ElementSet::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   for (TagDocEntryHT::const_iterator i = TagHT.begin(); 
+                                     i != TagHT.end(); 
+                                    ++i)
+   {
+      i->second->WriteContent(fp, filetype);
+   } 
+}
 
 //-----------------------------------------------------------------------------
 // Protected
@@ -40,113 +104,91 @@ gdcmElementSet::~gdcmElementSet()
 // Private
 
 /**
- * \brief  Find the value Length of the passed Header Entry
- * @param  Entry Header Entry whose length of the value shall be loaded. 
+ * \brief   add a new Dicom Element pointer to the H Table
+ * @param   newEntry entry to add
  */
- void gdcmElementSet::FindDocEntryLength (gdcmDocEntry *Entry) {
-   guint16 element = Entry->GetElement();
-   //guint16 group   = Entry->GetGroup(); //FIXME
-   std::string  vr = Entry->GetVR();
-   guint16 length16;
-       
-   
-   if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) 
+bool ElementSet::AddEntry(DocEntry *newEntry)
+{
+   const TagKey &key = newEntry->GetKey();
+
+   if( TagHT.count(key) == 1 )
    {
-      if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) 
-      {
-         // The following reserved two bytes (see PS 3.5-2001, section
-         // 7.1.2 Data element structure with explicit vr p27) must be
-         // skipped before proceeding on reading the length on 4 bytes.
-         fseek(fp, 2L, SEEK_CUR);
-         guint32 length32 = ReadInt32();
-
-         if ( (vr == "OB") && (length32 == 0xffffffff) ) 
-         {
-            Entry->SetLength(FindHeaderEntryLengthOB());
-            return;
-         }
-         FixHeaderEntryFoundLength(Entry, length32); 
-         return;
-      }
+      dbg.Verbose(1, "ElementSet::AddEntry key already present: ",
+                  key.c_str());
+      return false;
+   }
+   else
+   {
+      TagHT.insert(TagDocEntryHT::value_type(newEntry->GetKey(), newEntry));
+      return true;
+   }
+}
 
-      // Length is encoded on 2 bytes.
-      length16 = ReadInt16();
-      
-      // We can tell the current file is encoded in big endian (like
-      // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag
-      // and it's value is the one of the encoding of a big endian file.
-      // In order to deal with such big endian encoded files, we have
-      // (at least) two strategies:
-      // * when we load the "Transfer Syntax" tag with value of big endian
-      //   encoding, we raise the proper flags. Then we wait for the end
-      //   of the META group (0x0002) among which is "Transfer Syntax",
-      //   before switching the swap code to big endian. We have to postpone
-      //   the switching of the swap code since the META group is fully encoded
-      //   in little endian, and big endian coding only starts at the next
-      //   group. The corresponding code can be hard to analyse and adds
-      //   many additional unnecessary tests for regular tags.
-      // * the second strategy consists in waiting for trouble, that shall
-      //   appear when we find the first group with big endian encoding. This
-      //   is easy to detect since the length of a "Group Length" tag (the
-      //   ones with zero as element number) has to be of 4 (0x0004). When we
-      //   encounter 1024 (0x0400) chances are the encoding changed and we
-      //   found a group with big endian encoding.
-      // We shall use this second strategy. In order to make sure that we
-      // can interpret the presence of an apparently big endian encoded
-      // length of a "Group Length" without committing a big mistake, we
-      // add an additional check: we look in the already parsed elements
-      // for the presence of a "Transfer Syntax" whose value has to be "big
-      // endian encoding". When this is the case, chances are we have got our
-      // hands on a big endian encoded file: we switch the swap code to
-      // big endian and proceed...
-      if ( (element  == 0x0000) && (length16 == 0x0400) ) 
-      {
-         if ( ! IsExplicitVRBigEndianTransferSyntax() ) 
-         {
-            dbg.Verbose(0, "gdcmDocument::FindLength", "not explicit VR");
-            errno = 1;
-            return;
-         }
-         length16 = 4;
-         SwitchSwapToBigEndian();
-         // Restore the unproperly loaded values i.e. the group, the element
-         // and the dictionary entry depending on them.
-         guint16 CorrectGroup   = SwapShort(Entry->GetGroup());
-         guint16 CorrectElem    = SwapShort(Entry->GetElement());
-         gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
-                                                       CorrectElem);
-         if (!NewTag) 
-         {
-            // This correct tag is not in the dictionary. Create a new one.
-            NewTag = NewVirtualDictEntry(CorrectGroup, CorrectElem);
-         }
-         // FIXME this can create a memory leaks on the old entry that be
-         // left unreferenced.
-         Entry->SetDictEntry(NewTag);
-      }
-       
-      // Heuristic: well some files are really ill-formed.
-      if ( length16 == 0xffff) 
-      {
-         length16 = 0;
-         //dbg.Verbose(0, "gdcmDocument::FindLength",
-         //            "Erroneous element length fixed.");
-         // Actually, length= 0xffff means that we deal with
-         // Unknown Sequence Length 
-      }
-      FixHeaderEntryFoundLength(Entry, (guint32)length16);
-      return;
+/**
+ * \brief   Clear the hash table from given entry AND delete the entry.
+ * @param   entryToRemove Entry to remove AND delete.
+ * \warning Some problems when using under Windows... prefer the use of
+ *          Initialize / GetNext methods
+ */
+bool ElementSet::RemoveEntry( DocEntry *entryToRemove)
+{
+   const TagKey &key = entryToRemove->GetKey();
+   if( TagHT.count(key) == 1 )
+   {
+      TagHT.erase(key);
+      dbg.Verbose(0, "ElementSet::RemoveEntry: one element erased.");
+      delete entryToRemove;
+      return true;
+   }
+
+   dbg.Verbose(0, "ElementSet::RemoveEntry: key not present");
+   return false ;
+}
+
+/**
+ * \brief   Clear the hash table from given entry BUT keep the entry.
+ * @param   entryToRemove Entry to remove.
+ */
+bool ElementSet::RemoveEntryNoDestroy(DocEntry *entryToRemove)
+{
+   const TagKey &key = entryToRemove->GetKey();
+   if( TagHT.count(key) == 1 )
+   {
+      TagHT.erase(key);
+      dbg.Verbose(0, "ElementSet::RemoveEntry: one element erased.");
+      return true;
+   }
+
+   dbg.Verbose(0, "ElementSet::RemoveEntry: key not present");
+   return false ;
+}
+
+/**
+ * \brief   Initialise the visit of the Hash table (TagHT)
+ */
+void ElementSet::Initialize()
+{
+   ItTagHT = TagHT.begin();
+}
+
+/**
+ * \brief   Get the next entry whil visiting the Hash table (TagHT)
+ * \return  The next DocEntry if found, otherwhise NULL
+ */
+DocEntry *ElementSet::GetNextEntry()
+{
+   if (ItTagHT != TagHT.end())
+   {
+      DocEntry *tmp = ItTagHT->second;
+      ++ItTagHT;
+
+      return(tmp);
    }
    else
    {
-      // Either implicit VR or a non DICOM conformal (see note below) explicit
-      // VR that ommited the VR of (at least) this element. Farts happen.
-      // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
-      // on Data elements "Implicit and Explicit VR Data Elements shall
-      // not coexist in a Data Set and Data Sets nested within it".]
-      // Length is on 4 bytes.
-      
-      FixHeaderEntryFoundLength(Entry, ReadInt32());
-      return;
+      return(NULL);
    }
 }
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm