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

Generated on Thu Nov 28 2013 07:02:50 for GDCM by doxygen 1.7.6.1
SourceForge.net Logo