GDCM  2.2.0
gdcmDataSet.h
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program: GDCM (Grassroots DICOM). A DICOM library
00004 
00005   Copyright (c) 2006-2011 Mathieu Malaterre
00006   All rights reserved.
00007   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
00008 
00009      This software is distributed WITHOUT ANY WARRANTY; without even
00010      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00011      PURPOSE.  See the above copyright notice for more information.
00012 
00013 =========================================================================*/
00014 #ifndef GDCMDATASET_H
00015 #define GDCMDATASET_H
00016 
00017 #include "gdcmDataElement.h"
00018 #include "gdcmTag.h"
00019 #include "gdcmVR.h"
00020 #include "gdcmElement.h"
00021 
00022 #include <set>
00023 #include <iterator>
00024 
00025 namespace gdcm
00026 {
00027 class GDCM_EXPORT DataElementException : public std::exception {};
00028 
00029 class PrivateTag;
00054 class GDCM_EXPORT DataSet
00055 {
00056   friend class CSAHeader;
00057 public:
00058   typedef std::set<DataElement> DataElementSet;
00059   typedef DataElementSet::const_iterator ConstIterator;
00060   typedef DataElementSet::iterator Iterator;
00061   typedef DataElementSet::size_type SizeType;
00062   //typedef typename DataElementSet::iterator iterator;
00063   ConstIterator Begin() const { return DES.begin(); }
00064   Iterator Begin() { return DES.begin(); }
00065   ConstIterator End() const { return DES.end(); }
00066   Iterator End() { return DES.end(); }
00067   const DataElementSet &GetDES() const { return DES; }
00068   DataElementSet &GetDES() { return DES; }
00069   void Clear() {
00070     DES.clear();
00071     assert( DES.empty() );
00072   }
00073 
00074   SizeType Size() const {
00075     return DES.size();
00076   }
00077 
00078   void Print(std::ostream &os, std::string const &indent = "") const {
00079     // CT_Phillips_JPEG2K_Decompr_Problem.dcm has a SQ of length == 0
00080     //int s = DES.size();
00081     //assert( s );
00082     //std::copy(DES.begin(), DES.end(),
00083     //  std::ostream_iterator<DataElement>(os, "\n"));
00084     ConstIterator it = DES.begin();
00085     for( ; it != DES.end(); ++it)
00086       {
00087       os << indent << *it << "\n";
00088       }
00089   }
00090 
00091   template <typename TDE>
00092   unsigned int ComputeGroupLength(Tag const &tag) const
00093     {
00094     assert( tag.GetElement() == 0x0 );
00095     const DataElement r(tag);
00096     ConstIterator it = DES.find(r);
00097     unsigned int res = 0;
00098     for( ++it; it != DES.end()
00099       && it->GetTag().GetGroup() == tag.GetGroup(); ++it)
00100       {
00101       assert( it->GetTag().GetElement() != 0x0 );
00102       assert( it->GetTag().GetGroup() == tag.GetGroup() );
00103       res += it->GetLength<TDE>();
00104       }
00105     return res;
00106     }
00107 
00108   template <typename TDE>
00109   VL GetLength() const {
00110     if( DES.empty() ) return 0;
00111     assert( !DES.empty() );
00112     VL ll = 0;
00113     assert( ll == 0 );
00114     ConstIterator it = DES.begin();
00115     for( ; it != DES.end(); ++it)
00116       {
00117       assert( !(it->GetLength<TDE>().IsUndefined()) );
00118       if ( it->GetTag() != Tag(0xfffe,0xe00d) )
00119         {
00120         ll += it->GetLength<TDE>();
00121         }
00122       }
00123     return ll;
00124   }
00127   void Insert(const DataElement& de) {
00128     // FIXME: there is a special case where a dataset can have value < 0x8, see:
00129     // $ gdcmdump --csa gdcmData/SIEMENS-JPEG-CorruptFrag.dcm
00130     if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x4 )
00131       {
00132       // prevent user error:
00133       if( de.GetTag() == Tag(0xfffe,0xe00d)
00134       || de.GetTag() == Tag(0xfffe,0xe0dd)
00135       || de.GetTag() == Tag(0xfffe,0xe000) )
00136         {
00137         }
00138       else
00139         {
00140         InsertDataElement( de );
00141         }
00142       }
00143     else
00144       {
00145       gdcmErrorMacro( "Cannot add element with group < 0x0008 and != 0x4 in the dataset: " << de.GetTag() );
00146       }
00147   }
00149   void Replace(const DataElement& de) {
00150     if( DES.find(de) != DES.end() ) DES.erase(de);
00151     Insert(de);
00152   }
00154   void ReplaceEmpty(const DataElement& de) {
00155     ConstIterator it = DES.find(de);
00156     if( it != DES.end() && it->IsEmpty() )
00157       DES.erase(de);
00158     Insert(de);
00159   }
00161   SizeType Remove(const Tag& tag) {
00162     DataElementSet::size_type count = DES.erase(tag);
00163     assert( count == 0 || count == 1 );
00164     return count;
00165   }
00166 
00170   //DataElement& GetDataElement(const Tag &t) {
00171   //  DataElement r(t);
00172   //  Iterator it = DES.find(r);
00173   //  if( it != DES.end() )
00174   //    return *it;
00175   //  return GetDEEnd();
00176   //  }
00177   const DataElement& GetDataElement(const Tag &t) const {
00178     const DataElement r(t);
00179     ConstIterator it = DES.find(r);
00180     if( it != DES.end() )
00181       return *it;
00182     return GetDEEnd();
00183     }
00184   const DataElement& operator[] (const Tag &t) const { return GetDataElement(t); }
00185   const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); }
00186 
00188   std::string GetPrivateCreator(const Tag &t) const;
00189 
00191   bool FindDataElement(const PrivateTag &t) const;
00193   const DataElement& GetDataElement(const PrivateTag &t) const;
00194 
00195   // DUMB: this only search within the level of the current DataSet
00196   bool FindDataElement(const Tag &t) const {
00197     const DataElement r(t);
00198     //ConstIterator it = DES.find(r);
00199     if( DES.find(r) != DES.end() )
00200       {
00201       return true;
00202       }
00203     return false;
00204     }
00205 
00206   // WARNING:
00207   // This only search at the same level as the DataSet is !
00208   const DataElement& FindNextDataElement(const Tag &t) const {
00209     const DataElement r(t);
00210     ConstIterator it = DES.lower_bound(r);
00211     if( it != DES.end() )
00212       return *it;
00213     return GetDEEnd();
00214     }
00215 
00217   bool IsEmpty() const { return DES.empty(); };
00218 
00219   DataSet& operator=(DataSet const &val)
00220   {
00221     DES = val.DES;
00222     return *this;
00223   }
00224 
00225 /*
00226   template <typename TOperation>
00227   void ExecuteOperation(TOperation & operation) {
00228     assert( !DES.empty() );
00229     DataElementSet::iterator it = Begin();
00230     for( ; it != End(); ++it)
00231       {
00232       DataElement &de = (DataElement&)*it;
00233       operation( de );
00234       }
00235   }
00236 */
00237 
00238   template <typename TDE, typename TSwap>
00239   std::istream &ReadNested(std::istream &is);
00240 
00241   template <typename TDE, typename TSwap>
00242   std::istream &Read(std::istream &is);
00243 
00244   template <typename TDE, typename TSwap>
00245   std::istream &ReadUpToTag(std::istream &is, const Tag &t, std::set<Tag> const & skiptags);
00246 
00247   template <typename TDE, typename TSwap>
00248   std::istream &ReadUpToTagWithLength(std::istream &is, const Tag &t, VL & length);
00249 
00250   template <typename TDE, typename TSwap>
00251   std::istream &ReadSelectedTags(std::istream &is, const std::set<Tag> & tags);
00252   template <typename TDE, typename TSwap>
00253   std::istream &ReadSelectedTagsWithLength(std::istream &is, const std::set<Tag> & tags, VL & length);
00254 
00255   template <typename TDE, typename TSwap>
00256   std::ostream const &Write(std::ostream &os) const;
00257 
00258   template <typename TDE, typename TSwap>
00259   std::istream &ReadWithLength(std::istream &is, VL &length);
00260 
00261 protected:
00262   /* GetDEEnd is a Win32 only issue, one cannot use a dllexported
00263    * static member data in an inline function, otherwise symbol
00264    * will get reported as missing in any dll using the inlined function
00265    */
00266   const DataElement& GetDEEnd() const;
00267 
00268   // This function is not safe, it does not check for the value of the tag
00269   // so depending whether we are getting called from a dataset or file meta header
00270   // the condition is different
00271   void InsertDataElement(const DataElement& de) {
00272     //if( de.GetTag() == Tag(0xfffe,0xe00d) ) return;
00273     //if( de.GetTag() == Tag(0xfffe,0xe0dd) ) return;
00274 #ifndef NDEBUG
00275     std::pair<Iterator,bool> pr = DES.insert(de);
00276     if( pr.second == false )
00277       {
00278       gdcmWarningMacro( "DataElement: " << de << " was already found, skipping duplicate entry.\n"
00279         "Original entry kept is: " << *pr.first );
00280       }
00281 #else
00282     DES.insert(de);
00283 #endif
00284     assert( de.IsEmpty() || de.GetVL() == de.GetValue().GetLength() );
00285     }
00286 
00287 protected:
00288   // Internal function, that will compute the actual Tag (if found) of
00289   // a requested Private Tag (XXXX,YY,"PRIVATE")
00290   Tag ComputeDataElement(const PrivateTag & t) const;
00291 
00292 private:
00293   DataElementSet DES;
00294   static DataElement DEEnd;
00295   friend std::ostream& operator<<(std::ostream &_os, const DataSet &val);
00296 };
00297 //-----------------------------------------------------------------------------
00298 inline std::ostream& operator<<(std::ostream &os, const DataSet &val)
00299 {
00300   val.Print(os);
00301   return os;
00302 }
00303 
00304 #if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
00305 /*
00306  * HACK: I need this temp class to be able to manipulate a std::set from python,
00307  * swig does not support wrapping of simple class like std::set...
00308  */
00309 class SWIGDataSet
00310 {
00311 public:
00312   SWIGDataSet(DataSet &des):Internal(des),it(des.Begin()) {}
00313   const DataElement& GetCurrent() const { return *it; }
00314   void Start() { it = Internal.Begin(); }
00315   bool IsAtEnd() const { return it == Internal.End(); }
00316   void Next() { ++it; }
00317 private:
00318   DataSet & Internal;
00319   DataSet::ConstIterator it;
00320 };
00321 #endif /* SWIG */
00322 
00328 } // end namespace gdcm
00329 
00330 #include "gdcmDataSet.txx"
00331 
00332 #endif //GDCMDATASET_H

Generated on Fri Jun 1 2012 19:00:32 for GDCM by doxygen 1.7.6.1
SourceForge.net Logo