# gdcmTag.h

Go to the documentation of this file.

    00001 /*=========================================================================
    00002
    00003   Program: GDCM (Grassroots DICOM). A DICOM library
    00004   Module:  $URL$
    00005
    00006   Copyright (c) 2006-2009 Mathieu Malaterre
    00007   All rights reserved.
    00008   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
    00009
    00010      This software is distributed WITHOUT ANY WARRANTY; without even
    00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    00012      PURPOSE.  See the above copyright notice for more information.
    00013
    00014 =========================================================================*/
    00015 #ifndef __gdcmTag_h
    00016 #define __gdcmTag_h
    00017
    00018 #include "gdcmTypes.h"
    00019
    00020 #include <iostream>
    00021 #include <iomanip>
    00022
    00023 namespace gdcm
    00024 {
    00025
    00038 class GDCM_EXPORT Tag
    00039 {
    00040 public:
    00042   Tag(uint16_t group, uint16_t element) {
    00043     ElementTag.tags[0] = group; ElementTag.tags[1] = element;
    00044   }
    00047   Tag(uint32_t tag = 0) {
    00048     SetElementTag(tag);
    00049   }
    00050
    00051   friend std::ostream& operator<<(std::ostream &_os, const Tag &_val);
    00052   friend std::istream& operator>>(std::istream &_is, Tag &_val);
    00053
    00055   uint16_t GetGroup() const { return ElementTag.tags[0]; }
    00057   uint16_t GetElement() const { return ElementTag.tags[1]; }
    00059   void SetGroup(uint16_t group) { ElementTag.tags[0] = group; }
    00061   void SetElement(uint16_t element) { ElementTag.tags[1] = element; }
    00063   void SetElementTag(uint16_t group, uint16_t element) {
    00064     ElementTag.tags[0] = group; ElementTag.tags[1] = element;
    00065   }
    00066
    00068   uint32_t GetElementTag() const {
    00069 #ifndef GDCM_WORDS_BIGENDIAN
    00070     return (ElementTag.tag<<16) | (ElementTag.tag>>16);
    00071 #else
    00072     return ElementTag.tag;
    00073 #endif
    00074   }
    00075
    00077   void SetElementTag(uint32_t tag) {
    00078 #ifndef GDCM_WORDS_BIGENDIAN
    00079     tag = ( (tag<<16) | (tag>>16) );
    00080 #endif
    00081     ElementTag.tag = tag;
    00082   }
    00083
    00084   // \brief Returns the Group or Element of the given Tag, depending on id (0/1)
    00085   const uint16_t &operator[](const unsigned int &_id) const
    00086     {
    00087     assert(_id<2);
    00088     return ElementTag.tags[_id];
    00089     }
    00090   // \brief Returns the Group or Element of the given Tag, depending on id (0/1)
    00091   uint16_t &operator[](const unsigned int &_id)
    00092     {
    00093     assert(_id<2);
    00094     return ElementTag.tags[_id];
    00095     }
    00096
    00097   Tag &operator=(const Tag &_val)
    00098     {
    00099     ElementTag.tag = _val.ElementTag.tag;
    00100     return *this;
    00101     }
    00102
    00103   bool operator==(const Tag &_val) const
    00104     {
    00105     return ElementTag.tag == _val.ElementTag.tag;
    00106     }
    00107   bool operator!=(const Tag &_val) const
    00108     {
    00109     return ElementTag.tag != _val.ElementTag.tag;
    00110     }
    00111
    00114   // FIXME FIXME FIXME TODO
    00115   // the following is pretty dumb. Since we have control over who is group
    00116   // and who is element, we should reverse them in little endian and big endian case
    00117   // since what we really want is fast comparison and not garantee that group is in #0
    00118   // ...
    00119   bool operator<(const Tag &_val) const
    00120     {
    00121 #ifndef GDCM_WORDS_BIGENDIAN
    00122     if( ElementTag.tags[0] < _val.ElementTag.tags[0] )
    00123       return true;
    00124     if( ElementTag.tags[0] == _val.ElementTag.tags[0]
    00125      && ElementTag.tags[1] <  _val.ElementTag.tags[1] )
    00126       return true;
    00127     return false;
    00128 #else
    00129      // Plain comparison is enough!
    00130      return ( ElementTag.tag < _val.ElementTag.tag );
    00131 #endif
    00132    }
    00133   bool operator<=(const Tag &t2) const
    00134     {
    00135     const Tag &t1 = *this;
    00136     return t1 == t2 || t1 < t2;
    00137     }
    00138
    00139   Tag(const Tag &_val)
    00140     {
    00141     ElementTag.tag = _val.ElementTag.tag;
    00142     }
    00144   uint32_t GetLength() const { return 4; }
    00145
    00150   bool IsPublic() const { return !(ElementTag.tags[0] % 2); }
    00151
    00155   bool IsPrivate() const { return !IsPublic(); }
    00156
    00157   //-----------------------------------------------------------------------------
    00159   template <typename TSwap>
    00160   std::istream &Read(std::istream &is)
    00161     {
    00162     is.read(ElementTag.bytes, 4);
    00163     TSwap::SwapArray(ElementTag.tags, 2);
    00164     return is;
    00165     }
    00166
    00168   template <typename TSwap>
    00169   const std::ostream &Write(std::ostream &os) const
    00170     {
    00171     uint16_t copy[2];
    00172     copy[0]= ElementTag.tags[0];
    00173     copy[1]= ElementTag.tags[1];
    00174     TSwap::SwapArray(copy, 2);
    00175     return os.write((char*)(&copy), 4);
    00176     }
    00177
    00179   Tag GetPrivateCreator() const
    00180     {
    00181     // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS
    00182     // eg: 0x0123,0x1425 -> 0x0123,0x0014
    00183     assert( IsPrivate() && !IsPrivateCreator() );
    00184     Tag r = *this;
    00185     r.SetElement( GetElement() >> 8 );
    00186     return r;
    00187     }
    00189   void SetPrivateCreator(Tag const &t)
    00190     {
    00191     // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS
    00192     // eg: 0x0123,0x0045 -> 0x0123,0x4567
    00193     assert( t.IsPrivate() /*&& t.IsPrivateCreator()*/ );
    00194     uint16_t element = t.GetElement() << 8;
    00195     uint16_t base = GetElement() << 8;
    00196     SetElement( (base >> 8) + element );
    00197     }
    00198
    00200   bool IsPrivateCreator() const
    00201     {
    00202     return IsPrivate() && (GetElement() <= 0xFF && GetElement() >= 0x10);
    00203     }
    00204
    00206   bool IsIllegal() const
    00207     {
    00208     // DICOM reserved those groups:
    00209     return GetGroup() == 0x0001 || GetGroup() == 0x0003 || GetGroup() == 0x0005 || GetGroup() == 0x0007
    00210     // This is a very special case, in private group, one cannot use element [0x01,0x09] ...
    00211 //      || (IsPrivate() && !IsPrivateCreator() && !IsGroupLength());
    00212       || (IsPrivate() && GetElement() > 0x0 && GetElement() < 0x10 );
    00213     }
    00214
    00216   bool IsGroupLength() const
    00217     {
    00218     return GetElement() == 0x0;
    00219     }
    00220
    00222   bool IsGroupXX(const Tag &t) const
    00223     {
    00224     if( t.GetElement() == GetElement() )
    00225       {
    00226       if( t.IsPrivate() ) return false;
    00227       uint16_t group = (GetGroup() >> 8 ) << 8;
    00228       return group == t.GetGroup();
    00229       }
    00230     return false;
    00231     }
    00232
    00238   bool ReadFromCommaSeparatedString(const char *str);
    00239
    00242   bool ReadFromPipeSeparatedString(const char *str);
    00243
    00246   std::string PrintAsPipeSeparatedString() const;
    00247
    00248 private:
    00249   union { uint32_t tag; uint16_t tags[2]; char bytes[4]; } ElementTag;
    00250 };
    00251 //-----------------------------------------------------------------------------
    00252 inline std::istream& operator>>(std::istream &_is, Tag &_val)
    00253 {
    00254   char c;
    00255   _is >> c;
    00256   uint16_t a, b;
    00257   _is >> std::hex >> a;
    00258   //_is >> std::hex >> _val[0];
    00259   //_is >> std::hex >> _val.ElementTag.tags[0];
    00260   _is >> c;
    00261   //_is >> _val[1];
    00262   //_is >> std::hex >> _val.ElementTag.tags[1];
    00263   _is >> std::hex >> b;
    00264   _is >> c;
    00265   _val.SetGroup( a );
    00266   _val.SetElement( b );
    00267   return _is;
    00268 }
    00269
    00270 inline std::ostream& operator<<(std::ostream &_os, const Tag &_val)
    00271 {
    00272   _os.setf( std::ios::right);
    00273   _os << std::hex << '(' << std::setw( 4 ) << std::setfill( '0' )
    00274     << _val[0] << ',' << std::setw( 4 ) << std::setfill( '0' )
    00275     << _val[1] << ')' << std::setfill( ' ' ) << std::dec;
    00276   return _os;
    00277 }
    00278
    00279 } // end namespace gdcm
    00280
    00281 #endif //__gdcmTag_h
    00282