comparison OrthancServer/ParsedDicomFile.cpp @ 794:437c4a83d2cc

refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 May 2014 10:52:20 +0200
parents 145604a97914
children 777b6b694da6
comparison
equal deleted inserted replaced
793:145604a97914 794:437c4a83d2cc
136 136
137 137
138 138
139 namespace Orthanc 139 namespace Orthanc
140 { 140 {
141 struct ParsedDicomFile::PImpl
142 {
143 std::auto_ptr<DcmFileFormat> file_;
144 };
145
146
147 // This method can only be called from the constructors!
141 void ParsedDicomFile::Setup(const char* buffer, size_t size) 148 void ParsedDicomFile::Setup(const char* buffer, size_t size)
142 { 149 {
143 DcmInputBufferStream is; 150 DcmInputBufferStream is;
144 if (size > 0) 151 if (size > 0)
145 { 152 {
146 is.setBuffer(buffer, size); 153 is.setBuffer(buffer, size);
147 } 154 }
148 is.setEos(); 155 is.setEos();
149 156
150 file_.reset(new DcmFileFormat); 157 pimpl_->file_.reset(new DcmFileFormat);
151 file_->transferInit(); 158 pimpl_->file_->transferInit();
152 if (!file_->read(is).good()) 159 if (!pimpl_->file_->read(is).good())
153 { 160 {
161 delete pimpl_; // Avoid a memory leak due to exception
162 // throwing, as we are in the constructor
163
154 throw OrthancException(ErrorCode_BadFileFormat); 164 throw OrthancException(ErrorCode_BadFileFormat);
155 } 165 }
156 file_->loadAllDataIntoMemory(); 166 pimpl_->file_->loadAllDataIntoMemory();
157 file_->transferEnd(); 167 pimpl_->file_->transferEnd();
158 } 168 }
159 169
160 170
161 static void SendPathValueForDictionary(RestApiOutput& output, 171 static void SendPathValueForDictionary(RestApiOutput& output,
162 DcmItem& dicom) 172 DcmItem& dicom)
391 } 401 }
392 402
393 void ParsedDicomFile::SendPathValue(RestApiOutput& output, 403 void ParsedDicomFile::SendPathValue(RestApiOutput& output,
394 const UriComponents& uri) 404 const UriComponents& uri)
395 { 405 {
396 DcmItem* dicom = file_->getDataset(); 406 DcmItem* dicom = pimpl_->file_->getDataset();
397 E_TransferSyntax transferSyntax = file_->getDataset()->getOriginalXfer(); 407 E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getOriginalXfer();
398 408
399 // Special case: Accessing the pixel data 409 // Special case: Accessing the pixel data
400 if (uri.size() == 1 || 410 if (uri.size() == 1 ||
401 uri.size() == 2) 411 uri.size() == 2)
402 { 412 {
727 737
728 738
729 void ParsedDicomFile::Remove(const DicomTag& tag) 739 void ParsedDicomFile::Remove(const DicomTag& tag)
730 { 740 {
731 DcmTagKey key(tag.GetGroup(), tag.GetElement()); 741 DcmTagKey key(tag.GetGroup(), tag.GetElement());
732 DcmElement* element = file_->getDataset()->remove(key); 742 DcmElement* element = pimpl_->file_->getDataset()->remove(key);
733 if (element != NULL) 743 if (element != NULL)
734 { 744 {
735 delete element; 745 delete element;
736 } 746 }
737 } 747 }
742 { 752 {
743 typedef std::list<DcmElement*> Tags; 753 typedef std::list<DcmElement*> Tags;
744 754
745 Tags privateTags; 755 Tags privateTags;
746 756
747 DcmDataset& dataset = *file_->getDataset(); 757 DcmDataset& dataset = *pimpl_->file_->getDataset();
748 for (unsigned long i = 0; i < dataset.card(); i++) 758 for (unsigned long i = 0; i < dataset.card(); i++)
749 { 759 {
750 DcmElement* element = dataset.getElement(i); 760 DcmElement* element = dataset.getElement(i);
751 DcmTag tag(element->getTag()); 761 DcmTag tag(element->getTag());
752 if (!strcmp("PrivateCreator", tag.getTagName()) || // TODO - This may change with future versions of DCMTK 762 if (!strcmp("PrivateCreator", tag.getTagName()) || // TODO - This may change with future versions of DCMTK
773 const std::string& value) 783 const std::string& value)
774 { 784 {
775 std::auto_ptr<DcmElement> element(CreateElementForTag(tag)); 785 std::auto_ptr<DcmElement> element(CreateElementForTag(tag));
776 FillElementWithString(*element, tag, value); 786 FillElementWithString(*element, tag, value);
777 787
778 if (!file_->getDataset()->insert(element.release(), false, false).good()) 788 if (!pimpl_->file_->getDataset()->insert(element.release(), false, false).good())
779 { 789 {
780 // This field already exists 790 // This field already exists
781 throw OrthancException(ErrorCode_InternalError); 791 throw OrthancException(ErrorCode_InternalError);
782 } 792 }
783 } 793 }
788 DicomReplaceMode mode) 798 DicomReplaceMode mode)
789 { 799 {
790 DcmTagKey key(tag.GetGroup(), tag.GetElement()); 800 DcmTagKey key(tag.GetGroup(), tag.GetElement());
791 DcmElement* element = NULL; 801 DcmElement* element = NULL;
792 802
793 if (!file_->getDataset()->findAndGetElement(key, element).good() || 803 if (!pimpl_->file_->getDataset()->findAndGetElement(key, element).good() ||
794 element == NULL) 804 element == NULL)
795 { 805 {
796 // This field does not exist, act wrt. the specified "mode" 806 // This field does not exist, act wrt. the specified "mode"
797 switch (mode) 807 switch (mode)
798 { 808 {
835 845
836 846
837 void ParsedDicomFile::Answer(RestApiOutput& output) 847 void ParsedDicomFile::Answer(RestApiOutput& output)
838 { 848 {
839 std::string serialized; 849 std::string serialized;
840 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, file_->getDataset())) 850 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, pimpl_->file_->getDataset()))
841 { 851 {
842 output.AnswerBuffer(serialized, CONTENT_TYPE_OCTET_STREAM); 852 output.AnswerBuffer(serialized, CONTENT_TYPE_OCTET_STREAM);
843 } 853 }
844 } 854 }
845 855
847 857
848 bool ParsedDicomFile::GetTagValue(std::string& value, 858 bool ParsedDicomFile::GetTagValue(std::string& value,
849 const DicomTag& tag) 859 const DicomTag& tag)
850 { 860 {
851 DcmTagKey k(tag.GetGroup(), tag.GetElement()); 861 DcmTagKey k(tag.GetGroup(), tag.GetElement());
852 DcmDataset& dataset = *file_->getDataset(); 862 DcmDataset& dataset = *pimpl_->file_->getDataset();
853 DcmElement* element = NULL; 863 DcmElement* element = NULL;
854 if (!dataset.findAndGetElement(k, element).good() || 864 if (!dataset.findAndGetElement(k, element).good() ||
855 element == NULL) 865 element == NULL)
856 { 866 {
857 return false; 867 return false;
1011 } 1021 }
1012 1022
1013 1023
1014 void ParsedDicomFile::SaveToMemoryBuffer(std::string& buffer) 1024 void ParsedDicomFile::SaveToMemoryBuffer(std::string& buffer)
1015 { 1025 {
1016 FromDcmtkBridge::SaveToMemoryBuffer(buffer, file_->getDataset()); 1026 FromDcmtkBridge::SaveToMemoryBuffer(buffer, pimpl_->file_->getDataset());
1017 } 1027 }
1018 1028
1019 1029
1020 void ParsedDicomFile::SaveToFile(const std::string& path) 1030 void ParsedDicomFile::SaveToFile(const std::string& path)
1021 { 1031 {
1024 SaveToMemoryBuffer(content); 1034 SaveToMemoryBuffer(content);
1025 Toolbox::WriteFile(content, path); 1035 Toolbox::WriteFile(content, path);
1026 } 1036 }
1027 1037
1028 1038
1029 ParsedDicomFile::ParsedDicomFile() 1039 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl)
1030 { 1040 {
1031 file_.reset(new DcmFileFormat); 1041 pimpl_->file_.reset(new DcmFileFormat);
1032 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); 1042 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient));
1033 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); 1043 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study));
1034 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); 1044 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series));
1035 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); 1045 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance));
1036 } 1046 }
1037 1047
1038 1048
1039 ParsedDicomFile::ParsedDicomFile(const char* content, 1049 ParsedDicomFile::ParsedDicomFile(const char* content, size_t size) : pimpl_(new PImpl)
1040 size_t size)
1041 { 1050 {
1042 Setup(content, size); 1051 Setup(content, size);
1043 } 1052 }
1044 1053
1045 ParsedDicomFile::ParsedDicomFile(const std::string& content) 1054 ParsedDicomFile::ParsedDicomFile(const std::string& content) : pimpl_(new PImpl)
1046 { 1055 {
1047 if (content.size() == 0) 1056 if (content.size() == 0)
1048 { 1057 {
1049 Setup(NULL, 0); 1058 Setup(NULL, 0);
1050 } 1059 }
1053 Setup(&content[0], content.size()); 1062 Setup(&content[0], content.size());
1054 } 1063 }
1055 } 1064 }
1056 1065
1057 1066
1058 ParsedDicomFile::ParsedDicomFile(DcmFileFormat& other) : 1067 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) :
1059 file_(dynamic_cast<DcmFileFormat*>(other.clone())) 1068 pimpl_(new PImpl)
1060 { 1069 {
1070 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone()));
1061 } 1071 }
1062 1072
1063 1073
1064 ParsedDicomFile::~ParsedDicomFile() 1074 ParsedDicomFile::~ParsedDicomFile()
1065 { 1075 {
1076 delete pimpl_;
1066 } 1077 }
1067 1078
1068 1079
1069 void* ParsedDicomFile::GetDcmtkObject() 1080 void* ParsedDicomFile::GetDcmtkObject()
1070 { 1081 {
1071 return file_.get(); 1082 return pimpl_->file_.get();
1072 } 1083 }
1073 1084
1074 1085
1075 ParsedDicomFile* ParsedDicomFile::Clone() 1086 ParsedDicomFile* ParsedDicomFile::Clone()
1076 { 1087 {
1077 return new ParsedDicomFile(*file_); 1088 return new ParsedDicomFile(*this);
1078 } 1089 }
1079 } 1090 }