GDCM  2.4.0
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  //}
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 0
70  if( Internal.empty() ) assert( Length == 0 );
71  return Internal.empty();
72 #else
73  return Length == 0;
74 #endif
75  }
76  VL GetLength() const { return Length; }
77 
78  VL ComputeLength() const { return Length + Length % 2; }
79  // Does a reallocation
80  void SetLength(VL vl) {
81  VL l(vl);
82 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
83  // CompressedLossy.dcm
84  if( l.IsUndefined() ) throw Exception( "Impossible" );
85  if ( l.IsOdd() ) {
87  "BUGGY HEADER: Your dicom contain odd length value field." );
88  ++l;
89  }
90 #else
91  assert( !l.IsUndefined() && !l.IsOdd() );
92 #endif
93  // I cannot use reserve for now. I need to implement:
94  // STL - vector<> and istream
95  // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74
96 //#define SHORT_READ_HACK
97  try
98  {
99 #ifdef SHORT_READ_HACK
100  if( l <= 0xff )
101 #endif
102  Internal.resize(l);
103  //Internal.reserve(l);
104  }
105  catch(...)
106  {
107  //throw Exception("Impossible to allocate: " << l << " bytes." );
108  throw Exception("Impossible to allocate" );
109  }
110  // Keep the exact length
111  Length = vl;
112  }
113 
114  operator const std::vector<char>& () const { return Internal; }
115 
117  Internal = val.Internal;
118  Length = val.Length;
119  return *this;
120  }
121 
122  bool operator==(const ByteValue &val) const {
123  if( Length != val.Length )
124  return false;
125  if( Internal == val.Internal )
126  return true;
127  return false;
128  }
129  bool operator==(const Value &val) const
130  {
131  const ByteValue &bv = dynamic_cast<const ByteValue&>(val);
132  return Length == bv.Length && Internal == bv.Internal;
133  }
134 
135 
136  void Clear() {
137  Internal.clear();
138  }
139  // Use that only if you understand what you are doing
140  const char *GetPointer() const {
141  if(!Internal.empty()) return &Internal[0];
142  return 0;
143  }
144  void Fill(char c) {
145  //if( Internal.empty() ) return;
146  std::vector<char>::iterator it = Internal.begin();
147  for(; it != Internal.end(); ++it) *it = c;
148  }
149  bool GetBuffer(char *buffer, unsigned long length) const;
150  bool WriteBuffer(std::ostream &os) const {
151  if( Length ) {
152  //assert( Internal.size() <= Length );
153  assert( !(Internal.size() % 2) );
154  os.write(&Internal[0], Internal.size() );
155  }
156  return true;
157  }
158 
159  template <typename TSwap, typename TType>
160  std::istream &Read(std::istream &is, bool readvalues = true) {
161  // If Length is odd we have detected that in SetLength
162  // and calling std::vector::resize make sure to allocate *AND*
163  // initialize values to 0 so we are sure to have a \0 at the end
164  // even in this case
165  if(Length)
166  {
167  if( readvalues )
168  {
169  is.read(&Internal[0], Length);
170  assert( Internal.size() == Length || Internal.size() == Length + 1 );
171  TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) );
172  }
173  else
174  {
175  is.seekg(Length, std::ios::cur);
176  }
177  }
178  return is;
179  }
180 
181  template <typename TSwap>
182  std::istream &Read(std::istream &is) {
183  return Read<TSwap,uint8_t>(is);
184  }
185 
186 
187  template <typename TSwap, typename TType>
188  std::ostream const &Write(std::ostream &os) const {
189  assert( !(Internal.size() % 2) );
190  if( !Internal.empty() ) {
191  //os.write(&Internal[0], Internal.size());
192  std::vector<char> copy = Internal;
193  TSwap::SwapArray((TType*)&copy[0], Internal.size() / sizeof(TType) );
194  os.write(&copy[0], copy.size());
195  }
196  return os;
197  }
198 
199  template <typename TSwap>
200  std::ostream const &Write(std::ostream &os) const {
201  return Write<TSwap,uint8_t>(os);
202  }
203 
210  bool IsPrintable(VL length) const {
211  assert( length <= Length );
212  for(unsigned int i=0; i<length; i++)
213  {
214  if ( i == (length-1) && Internal[i] == '\0') continue;
215  if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) )
216  {
217  //gdcmWarningMacro( "Cannot print :" << i );
218  return false;
219  }
220  }
221  return true;
222  }
223 
225  void PrintPNXML(std::ostream &os) const;
226  void PrintASCIIXML(std::ostream &os) const;
227  void PrintHexXML(std::ostream &os) const;
228 protected:
229  void Print(std::ostream &os) const {
230  // This is perfectly valid to have a Length = 0 , so we cannot check
231  // the length for printing
232  if( !Internal.empty() )
233  {
234  if( IsPrintable(Length) )
235  {
236  // WARNING: Internal.end() != Internal.begin()+Length
237  std::vector<char>::size_type length = Length;
238  if( Internal.back() == 0 ) --length;
239  std::copy(Internal.begin(), Internal.begin()+length,
240  std::ostream_iterator<char>(os));
241  }
242  else
243  os << "Loaded:" << Internal.size();
244  }
245  else
246  {
247  //os << "Not Loaded";
248  os << "(no value available)";
249  }
250  }
251 /*
252 //Introduce check for invalid XML characters
253 friend std::ostream& operator<<(std::ostream &os,const char c);
254 */
255 
256  void SetLengthOnly(VL vl) {
257  Length = vl;
258  }
259 
260 private:
261  std::vector<char> Internal;
262 
263  // WARNING Length IS NOT Internal.size() some *featured* DICOM
264  // implementation define odd length, we always load them as even number
265  // of byte, so we need to keep the right Length
266  VL Length;
267 };
268 
269 } // end namespace gdcm
270 
271 #endif //GDCMBYTEVALUE_H

Generated on Thu Oct 17 2013 10:05:56 for GDCM by doxygen 1.8.4
SourceForge.net Logo