#ifndef GDCMDATASET_H
#define GDCMDATASET_H
#include "gdcmDataElement.h"
#include "gdcmTag.h"
#include "gdcmVR.h"
#include "gdcmElement.h"
#include "gdcmMediaStorage.h"
#include <set>
#include <iterator>
namespace gdcm_ns
{
class GDCM_EXPORT DataElementException : public std::exception {};
class PrivateTag;
class GDCM_EXPORT DataSet
{
friend class CSAHeader;
public:
typedef std::set<DataElement> DataElementSet;
typedef DataElementSet::const_iterator ConstIterator;
typedef DataElementSet::iterator Iterator;
typedef DataElementSet::size_type SizeType;
ConstIterator Begin() const { return DES.begin(); }
Iterator Begin() { return DES.begin(); }
ConstIterator End() const { return DES.end(); }
Iterator End() { return DES.end(); }
const DataElementSet &GetDES() const { return DES; }
DataElementSet &GetDES() { return DES; }
void Clear() {
DES.clear();
gdcm_assert( DES.empty() );
}
SizeType Size() const {
return DES.size();
}
void Print(std::ostream &os, std::string const &indent = "") const {
ConstIterator it = DES.begin();
for( ; it != DES.end(); ++it)
{
os << indent << *it << "\n";
}
}
template <typename TDE>
unsigned int ComputeGroupLength(Tag const &tag) const
{
gdcm_assert( tag.GetElement() == 0x0 );
const DataElement r(tag);
ConstIterator it = DES.find(r);
unsigned int res = 0;
for( ++it; it != DES.end()
&& it->GetTag().GetGroup() == tag.GetGroup(); ++it)
{
gdcm_assert( it->GetTag().GetElement() != 0x0 );
gdcm_assert( it->GetTag().GetGroup() == tag.GetGroup() );
res += it->GetLength<TDE>();
}
return res;
}
template <typename TDE>
VL GetLength() const {
if( DES.empty() ) return 0;
gdcm_assert( !DES.empty() );
VL ll = 0;
gdcm_assert( ll == 0 );
ConstIterator it = DES.begin();
for( ; it != DES.end(); ++it)
{
gdcm_assert( !(it->GetLength<TDE>().IsUndefined()) );
if ( it->GetTag() != Tag(0xfffe,0xe00d) )
{
ll += it->GetLength<TDE>();
}
}
return ll;
}
void Insert(const DataElement& de) {
if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x4 )
{
if( de.GetTag() == Tag(0xfffe,0xe00d)
|| de.GetTag() == Tag(0xfffe,0xe0dd)
|| de.GetTag() == Tag(0xfffe,0xe000) )
{
}
else
{
InsertDataElement( de );
}
}
else
{
gdcmErrorMacro( "Cannot add element with group < 0x0008 and != 0x4 in the dataset: " << de.GetTag() );
}
}
void Replace(const DataElement& de) {
ConstIterator it = DES.find(de);
if( it != DES.end() )
{
gdcmAssertAlwaysMacro( &*it != &de );
DES.erase(it);
}
DES.insert(de);
}
void ReplaceEmpty(const DataElement& de) {
ConstIterator it = DES.find(de);
if( it != DES.end() && it->IsEmpty() )
{
gdcmAssertAlwaysMacro( &*it != &de );
DES.erase(it);
}
DES.insert(de);
}
SizeType Remove(const Tag& tag) {
DataElementSet::size_type count = DES.erase(tag);
gdcm_assert( count == 0 || count == 1 );
return count;
}
const DataElement& GetDataElement(const Tag &t) const {
const DataElement r(t);
ConstIterator it = DES.find(r);
if( it != DES.end() )
return *it;
return GetDEEnd();
}
const DataElement& operator[] (const Tag &t) const { return GetDataElement(t); }
const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); }
std::string GetPrivateCreator(const Tag &t) const;
PrivateTag GetPrivateTag(const Tag &t) const;
bool FindDataElement(const PrivateTag &t) const;
const DataElement& GetDataElement(const PrivateTag &t) const;
bool FindDataElement(const Tag &t) const {
const auto it = GetDataElement(t);
return it != GetDEEnd();
}
const DataElement& FindNextDataElement(const Tag &t) const {
const DataElement r(t);
ConstIterator it = DES.lower_bound(r);
if( it != DES.end() )
return *it;
return GetDEEnd();
}
bool IsEmpty() const { return DES.empty(); }
DataSet& operator=(DataSet const &)
= default;
template <typename TDE, typename TSwap>
std::istream &ReadNested(std::istream &is);
template <typename TDE, typename TSwap>
std::istream &Read(std::istream &is);
template <typename TDE, typename TSwap>
std::istream &ReadUpToTag(std::istream &is, const Tag &t, std::set<Tag> const & skiptags);
template <typename TDE, typename TSwap>
std::istream &ReadUpToTagWithLength(std::istream &is, const Tag &t, std::set<Tag> const & skiptags, VL & length);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedTags(std::istream &is, const std::set<Tag> & tags, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedTagsWithLength(std::istream &is, const std::set<Tag> & tags, VL & length, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedPrivateTags(std::istream &is, const std::set<PrivateTag> & tags, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedPrivateTagsWithLength(std::istream &is, const std::set<PrivateTag> & tags, VL & length, bool readvalues = true);
template <typename TDE, typename TSwap>
std::ostream const &Write(std::ostream &os) const;
template <typename TDE, typename TSwap>
std::istream &ReadWithLength(std::istream &is, VL &length);
MediaStorage GetMediaStorage() const;
protected:
const DataElement& GetDEEnd() const;
void InsertDataElement(const DataElement& de) {
#ifndef NDEBUG
std::pair<Iterator,bool> pr = DES.insert(de);
if( pr.second == false )
{
gdcmWarningMacro( "DataElement: " << de << " was already found, skipping duplicate entry.\n"
"Original entry kept is: " << *pr.first );
}
#else
DES.insert(de);
#endif
gdcm_assert( de.IsEmpty() || de.GetVL() == de.GetValue().GetLength() );
}
protected:
Tag ComputeDataElement(const PrivateTag & t) const;
private:
DataElementSet DES;
static DataElement DEEnd;
friend std::ostream& operator<<(std::ostream &_os, const DataSet &);
};
inline std::ostream& operator<<(std::ostream &os, const DataSet &val)
{
val.Print(os);
return os;
}
#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPHP)
class SWIGDataSet
{
public:
SWIGDataSet(DataSet &des):Internal(des),it(des.Begin()) {}
const DataElement& GetCurrent() const { return *it; }
void Start() { it = Internal.Begin(); }
bool IsAtEnd() const { return it == Internal.End(); }
void Next() { ++it; }
private:
DataSet & Internal;
DataSet::ConstIterator it;
};
#endif
}
#include "gdcmDataSet.txx"
#endif