+2004-11-15 Mathieu Malaterre <Mathieu.Malaterre@creatis.insa-lyon.fr>
+ * ENH: Slightly bigger patch:
+ 1. Getting toward full integration of JMR patch for writting dicom from scratch
+ 2. Update Test to test part of this patch: CreateUniqueUID
+ 3. File was not close properly in gdcmDict
+ 4. Use of typedef is to be prefered when possible (gdcmDict.cxx)
+ 5. Use of const ref instead of copy (speed issue)
+ 6. Remove temporary (duplicate) string in TranslateToKey
+ 7. Mark extremely dangerous code as such (gdcmDocument.cxx and AddEntry fallback case)
+ 8. Do not repeat virtual in subclasses
+ 9. Implemented in gdcm::Util two new function: GetIPAddress, and CreateUniqueUID
+
2004-11-15 Mathieu Malaterre <Mathieu.Malaterre@creatis.insa-lyon.fr>
* Apply first patch toward better string comparison when dealing with broken
DICOM files. Essentially the string could be padded with a space instead
int TestUtil(int , char * [])
{
+ std::cout << gdcm::Util::CreateUniqueUID("") << std::endl;
+
const char ref[] = "MONOCHROME1";
std::string a = "MONOCHROME1";
a += '\0';
Program: gdcm
Module: $RCSfile: gdcmDict.cxx,v $
Language: C++
- Date: $Date: 2004/11/03 18:08:56 $
- Version: $Revision: 1.51 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.52 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
const DictEntry newEntry(group, element, vr, fourth, name);
AddNewEntry(newEntry);
}
- from.close();
Filename = filename;
}
+ from.close();
}
/**
}
else
{
- KeyHt.insert(
- std::map<TagKey, DictEntry>::value_type
- (newEntry.GetKey(), newEntry));
- NameHt.insert(
- std::map<TagName, DictEntry>::value_type
- (newEntry.GetName(), newEntry ));
+ KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
+ NameHt.insert( TagNameHT::value_type(newEntry.GetName(), newEntry ));
return true;
}
}
{
if ( RemoveEntry(newEntry.GetKey()) )
{
- KeyHt.insert(
- std::map<TagKey, DictEntry>::value_type
- (newEntry.GetKey(), newEntry));
- NameHt.insert(
- std::map<TagName, DictEntry>::value_type
- (newEntry.GetName(), newEntry ));
+ KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
+ NameHt.insert( TagNameHT::value_type(newEntry.GetName(), newEntry ));
return true;
}
return false;
TagKeyHT::const_iterator it = KeyHt.find(key);
if(it != KeyHt.end())
{
- const DictEntry & entryToDelete = it->second;
+ const DictEntry& entryToDelete = it->second;
NameHt.erase(entryToDelete.GetName());
KeyHt.erase(key);
Program: gdcm
Module: $RCSfile: gdcmDict.h,v $
Language: C++
- Date: $Date: 2004/10/27 22:31:12 $
- Version: $Revision: 1.22 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.23 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
{
//-----------------------------------------------------------------------------
-typedef std::map<TagKey, DictEntry> TagKeyHT;
+typedef std::map<TagKey, DictEntry> TagKeyHT;
typedef std::map<TagName, DictEntry> TagNameHT;
-typedef std::list<std::string> EntryNamesList;
-typedef std::map<std::string, std::list<std::string> > EntryNamesByCatMap;
+typedef std::list<std::string> EntryNamesList;
+typedef std::map<std::string,
+ std::list<std::string> > EntryNamesByCatMap;
//-----------------------------------------------------------------------------
/*
* \defgroup Dict
Program: gdcm
Module: $RCSfile: gdcmDictEntry.cxx,v $
Language: C++
- Date: $Date: 2004/10/18 02:35:35 $
- Version: $Revision: 1.28 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.29 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
*/
TagKey DictEntry::TranslateToKey(uint16_t group, uint16_t element)
{
- TagKey key = Util::Format("%04x|%04x", group , element);
-
- return key;
+ return Util::Format("%04x|%04x", group, element);
}
//-----------------------------------------------------------------------------
Program: gdcm
Module: $RCSfile: gdcmDocument.cxx,v $
Language: C++
- Date: $Date: 2004/11/15 16:12:30 $
- Version: $Revision: 1.123 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.124 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
{
/////////////////////// ValEntry
ValEntry* newValEntry =
- new ValEntry( newDocEntry->GetDictEntry() );
+ new ValEntry( newDocEntry->GetDictEntry() ); //LEAK
newValEntry->Copy( newDocEntry );
// When "set" is a Document, then we are at the top of the
+ newValEntry->GetKey() );
}
- set->AddEntry( newValEntry );
+ if( !set->AddEntry( newValEntry ) )
+ {
+ // If here expect big troubles
+ delete newValEntry; //otherwise mem leak
+ }
LoadDocEntry( newValEntry );
if (newValEntry->IsItemDelimitor())
{
+ newBinEntry->GetKey() );
}
- set->AddEntry( newBinEntry );
+ if( !set->AddEntry( newBinEntry ) )
+ {
+ //Expect big troubles if here
+ delete newBinEntry;
+ }
LoadDocEntry( newBinEntry );
}
s << " x(" << std::hex << entry->GetLength() << ")";
binEntryPtr->SetValue(s.str());
}
- // Be carefull : a BinEntry IS_A ValEntry ...
+ // Be carefull : a BinEntry IS_A ValEntry ...
else if (ValEntry* valEntryPtr = dynamic_cast< ValEntry* >(entry) )
{
// s << "gdcm::NotLoaded. (ValEntry)";
Program: gdcm
Module: $RCSfile: gdcmDocument.h,v $
Language: C++
- Date: $Date: 2004/11/15 16:12:30 $
- Version: $Revision: 1.58 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.59 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
void BuildFlatHashTableRecurse( TagDocEntryHT& builtHT,
DocEntrySet* set );
- void HandleBrokenEndian(uint16_t group, uint16_t elem);
+ void HandleBrokenEndian(uint16_t group, uint16_t elem);
public:
// Accessors:
/// Accessor to \ref PrintLevel
Program: gdcm
Module: $RCSfile: gdcmElementSet.cxx,v $
Language: C++
- Date: $Date: 2004/11/05 21:23:46 $
- Version: $Revision: 1.26 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.27 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
*/
void ElementSet::Write(std::ofstream* fp, FileType filetype)
{
- for (TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i)
+ for (TagDocEntryHT::const_iterator i = TagHT.begin();
+ i != TagHT.end();
+ ++i)
{
i->second->Write(fp, filetype);
}
* \brief add a new Dicom Element pointer to the H Table
* @param newEntry entry to add
*/
-bool ElementSet::AddEntry( DocEntry* newEntry)
+bool ElementSet::AddEntry(DocEntry* newEntry)
{
- TagKey key = newEntry->GetKey();
+ const TagKey& key = newEntry->GetKey();
if( TagHT.count(key) == 1 )
{
}
else
{
- TagHT[newEntry->GetKey()] = newEntry;
+ TagHT.insert(TagDocEntryHT::value_type(newEntry->GetKey(), newEntry));
return true;
}
}
* \brief Clear the hash table from given entry BUT keep the entry.
* @param entryToRemove Entry to remove.
*/
-bool ElementSet::RemoveEntryNoDestroy( DocEntry* entryToRemove)
+bool ElementSet::RemoveEntryNoDestroy(DocEntry* entryToRemove)
{
- TagKey key = entryToRemove->GetKey();
+ const TagKey& key = entryToRemove->GetKey();
if( TagHT.count(key) == 1 )
{
TagHT.erase(key);
*/
bool ElementSet::RemoveEntry( DocEntry* entryToRemove)
{
- TagKey key = entryToRemove->GetKey();
+ const TagKey& key = entryToRemove->GetKey();
if( TagHT.count(key) == 1 )
{
TagHT.erase(key);
Program: gdcm
Module: $RCSfile: gdcmFile.cxx,v $
Language: C++
- Date: $Date: 2004/11/15 15:29:04 $
- Version: $Revision: 1.154 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.155 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
{
delete PixelConverter;
}
-
}
/**
Program: gdcm
Module: $RCSfile: gdcmSeqEntry.h,v $
Language: C++
- Date: $Date: 2004/10/25 03:03:45 $
- Version: $Revision: 1.22 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.23 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
{
public:
SeqEntry( DictEntry* );
- SeqEntry(DocEntry* d, int depth);
+ SeqEntry( DocEntry* d, int depth );
~SeqEntry();
- virtual void Print(std::ostream &os = std::cout);
- virtual void Write(std::ofstream *fp, FileType);
+ void Print(std::ostream &os = std::cout);
+ void Write(std::ofstream *fp, FileType filetype);
/// returns the SQITEM chained List for this SeQuence.
ListSQItem const & GetSQItems() const { return Items; }
/// Sets the delimitor mode
- void SetDelimitorMode(bool dm) { DelimitorMode = dm;}
+ void SetDelimitorMode(bool dm) { DelimitorMode = dm; }
/// Sets the Sequence Delimitation Item
void SetSequenceDelimitationItem(DocEntry * e) { SeqTerm = e;}
Program: gdcm
Module: $RCSfile: gdcmUtil.cxx,v $
Language: C++
- Date: $Date: 2004/11/16 02:04:00 $
- Version: $Revision: 1.63 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.64 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#include <stdarg.h> //only included in implementation file
#include <stdio.h> //only included in implementation file
+#include <unistd.h> // for gethostname
+#include <netdb.h> // for gethostbyname
+
namespace gdcm
{
bool Util::DicomStringEqual(const std::string& s1, const char *s2)
{
// s2 is the string from the DICOM reference: 'MONOCHROME1'
- std::string s1_even = s1; //Never directly change input parameter
+ std::string s1_even = s1; //Never change input parameter
std::string s2_even = DicomString( s2 );
if( s1_even[s1_even.size()-1] == ' ')
{
return s1_even == s2_even;
}
+/**
+ * \ingroup Util
+ * \brief Return the IP adress of the machine writting the DICOM image
+ */
+std::string Util::GetIPAddress()
+{
+ // This is a rip from http://www.codeguru.com/Cpp/I-N/internet/network/article.php/c3445/
+#ifndef HOST_NAME_MAX
+ // SUSv2 guarantees that `Host names are limited to 255 bytes'.
+ // POSIX 1003.1-2001 guarantees that `Host names (not including the
+ // terminating NUL) are limited to HOST_NAME_MAX bytes'.
+# define HOST_NAME_MAX 255
+ // In this case we should maybe check the string was not truncated.
+ // But I don't known how to check that...
+#endif //HOST_NAME_MAX
+
+ std::string str;
+ char szHostName[HOST_NAME_MAX+1];
+ int r = gethostname(szHostName, HOST_NAME_MAX);
+
+ if( r == 0 )
+ {
+ // Get host adresses
+ struct hostent * pHost = gethostbyname(szHostName);
+
+ for( int i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
+ {
+ for( int j = 0; j<pHost->h_length; j++ )
+ {
+ if( j > 0 ) str += ".";
+
+ str += Util::Format("%u",
+ (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);
+ }
+ // str now contains one local IP address
+ }
+ }
+ // If an error occur r == -1
+ // Most of the time it will return 127.0.0.1...
+ return str;
+}
+
+/**
+ * \ingroup Util
+ * \brief Creates a new UID. As stipulate in the DICOM ref
+ * each time a DICOM image is create it should have
+ * a unique identifier (URI)
+ */
+std::string Util::CreateUniqueUID(const std::string& root)
+{
+ // The code works as follow:
+ // echo "gdcm" | od -b
+ // 0000000 147 144 143 155 012
+ // Therefore we return
+ // radical + 147.144.143.155 + IP + time()
+ std::string radical = root;
+ if( !root.size() ) //anything better ?
+ {
+ radical = "0.0."; // Is this really usefull ?
+ }
+ // else
+ // A root was specified use it to forge our new UID:
+ radical += "147.144.143.155"; // gdcm
+ radical += ".";
+ radical += Util::GetIPAddress();
+ radical += ".";
+ radical += Util::GetCurrentDate();
+ radical += ".";
+ radical += Util::GetCurrentTime();
+
+ return radical;
+}
+
template <class T>
std::ostream& binary_write(std::ostream& os, const T& val)
{
Program: gdcm
Module: $RCSfile: gdcmUtil.h,v $
Language: C++
- Date: $Date: 2004/11/16 02:04:00 $
- Version: $Revision: 1.43 $
+ Date: $Date: 2004/11/16 02:54:35 $
+ Version: $Revision: 1.44 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
static std::string DicomString(const char* s, size_t l);
static std::string DicomString(const char* s);
static bool DicomStringEqual(const std::string& s1, const char *s2);
+ static std::string CreateUniqueUID(const std::string& root);
+
+private:
+ static std::string GetIPAddress(); //Do not expose this method
};
template <class T>