GDCM 2.2.1

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

gdcmByteValue.h
Go to the documentation of this file.
1 /*=========================================================================
2
3 Program: GDCM (Grassroots DICOM). A DICOM library
4
5 Copyright (c) 2006-2011 Mathieu Malaterre
6 All rights reserved.
7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notice for more information.
12
13 =========================================================================*/
14 #ifndef GDCMBYTEVALUE_H
15 #define GDCMBYTEVALUE_H
16
17 #include "gdcmValue.h"
18 #include "gdcmTrace.h"
19 #include "gdcmVL.h"
20
21 #include <vector>
22 #include <iterator>
23 #include <iomanip>
24
25 //#include <stdlib.h> // abort
26
27 namespace gdcm
28 {
33 class GDCM_EXPORT ByteValue : public Value
34 {
35 public:
36 ByteValue(const char* array = 0, VL const &vl = 0):
37 Internal(array, array+vl),Length(vl) {
38 if( vl.IsOdd() )
39 {
40 gdcmDebugMacro( "Odd length" );
41 Internal.resize(vl+1);
42 Length++;
43 }
44 }
45
47 ByteValue(std::vector<char> &v):Internal(v),Length((uint32_t)v.size()) {}
48 //ByteValue(std::ostringstream const &os) {
49 // (void)os;
50 // assert(0); // TODO
51 //}
52 ~ByteValue() {
53 Internal.clear();
54 }
55
56 // When 'dumping' dicom file we still have some information from
57 // Either the VR: eg LO (private tag)
58 void PrintASCII(std::ostream &os, VL maxlength ) const;
59
60 void PrintHex(std::ostream &os, VL maxlength) const;
61
62 // Either from Element Number (== 0x0000)
63 void PrintGroupLength(std::ostream &os) {
64 assert( Length == 2 );
65 (void)os;
66 }
67
68 bool IsEmpty() const {
69 if( Internal.empty() ) assert( Length == 0 );
70 return Internal.empty();
71 }
72 VL GetLength() const { return Length; }
73 // Does a reallocation
74 void SetLength(VL vl) {
75 VL l(vl);
76 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
77 // CompressedLossy.dcm
78 if( l.IsUndefined() ) throw Exception( "Impossible" );
79 if ( l.IsOdd() ) {
80 gdcmDebugMacro(
81 "BUGGY HEADER: Your dicom contain odd length value field." );
82 ++l;
83 }
84 #else
85 assert( !l.IsUndefined() && !l.IsOdd() );
86 #endif
87 // I cannot use reserve for now. I need to implement:
88 // STL - vector<> and istream
89 // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74
90 //#define SHORT_READ_HACK
91 try
92 {
93 #ifdef SHORT_READ_HACK
94 if( l <= 0xff )
95 #endif
96 Internal.resize(l);
97 //Internal.reserve(l);
98 }
99 catch(...)
100 {
101 //throw Exception("Impossible to allocate: " << l << " bytes." );
102 throw Exception("Impossible to allocate" );
103 }
104 // Keep the exact length
105 Length = vl;
106 }
107
108 operator const std::vector<char>& () const { return Internal; }
109
110 ByteValue &operator=(const ByteValue &val) {
111 Internal = val.Internal;
112 Length = val.Length;
113 return *this;
114 }
115
116 bool operator==(const ByteValue &val) const {
117 if( Length != val.Length )
118 return false;
119 if( Internal == val.Internal )
120 return true;
121 return false;
122 }
123 bool operator==(const Value &val) const
124 {
125 const ByteValue &bv = dynamic_cast<const ByteValue&>(val);
126 return Length == bv.Length && Internal == bv.Internal;
127 }
128
129
130 void Clear() {
131 Internal.clear();
132 }
133 // Use that only if you understand what you are doing
134 const char *GetPointer() const {
135 if(!Internal.empty()) return &Internal[0];
136 return 0;
137 }
138 void Fill(char c) {
139 //if( Internal.empty() ) return;
140 std::vector<char>::iterator it = Internal.begin();
141 for(; it != Internal.end(); ++it) *it = c;
142 }
143 bool GetBuffer(char *buffer, unsigned long length) const;
144 bool WriteBuffer(std::ostream &os) const {
145 if( Length ) {
146 //assert( Internal.size() <= Length );
147 assert( !(Internal.size() % 2) );
148 os.write(&Internal[0], Internal.size() );
149 }
150 return true;
151 }
152
153 template <typename TSwap, typename TType>
154 std::istream &Read(std::istream &is) {
155 // If Length is odd we have detected that in SetLength
156 // and calling std::vector::resize make sure to allocate *AND*
157 // initialize values to 0 so we are sure to have a \0 at the end
158 // even in this case
159 if(Length)
160 {
161 is.read(&Internal[0], Length);
162 assert( Internal.size() == Length || Internal.size() == Length + 1 );
163 TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) );
164 }
165 return is;
166 }
167
168 template <typename TSwap>
169 std::istream &Read(std::istream &is) {
170 return Read<TSwap,uint8_t>(is);
171 }
172
173
174 template <typename TSwap, typename TType>
175 std::ostream const &Write(std::ostream &os) const {
176 assert( !(Internal.size() % 2) );
177 if( !Internal.empty() ) {
178 //os.write(&Internal[0], Internal.size());
179 std::vector<char> copy = Internal;
180 TSwap::SwapArray((TType*)&copy[0], Internal.size() / sizeof(TType) );
181 os.write(&copy[0], copy.size());
182 }
183 return os;
184 }
185
186 template <typename TSwap>
187 std::ostream const &Write(std::ostream &os) const {
188 return Write<TSwap,uint8_t>(os);
189 }
190
197 bool IsPrintable(VL length) const {
198 assert( length <= Length );
199 for(unsigned int i=0; i<length; i++)
200 {
201 if ( i == (length-1) && Internal[i] == '\0') continue;
202 if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) )
203 {
204 //gdcmWarningMacro( "Cannot print :" << i );
205 return false;
206 }
207 }
208 return true;
209 }
210
211 protected:
212 void Print(std::ostream &os) const {
213 // This is perfectly valid to have a Length = 0 , so we cannot check
214 // the length for printing
215 if( !Internal.empty() )
216 {
217 if( IsPrintable(Length) )
218 {
219 // WARNING: Internal.end() != Internal.begin()+Length
220 std::vector<char>::size_type length = Length;
221 if( Internal.back() == 0 ) --length;
222 std::copy(Internal.begin(), Internal.begin()+length,
223 std::ostream_iterator<char>(os));
224 }
225 else
226 os << "Loaded:" << Internal.size();
227 }
228 else
229 {
230 //os << "Not Loaded";
231 os << "(no value available)";
232 }
233 }
234
235
236 private:
237 std::vector<char> Internal;
238
239 // WARNING Length IS NOT Internal.size() some *featured* DICOM
240 // implementation define odd length, we always load them as even number
241 // of byte, so we need to keep the right Length
242 VL Length;
243 };
244
245 } // end namespace gdcm
246
247 #endif //GDCMBYTEVALUE_H