1 /*
2  *
3  *  Copyright (C) 2007-2011, OFFIS e.V.
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation were developed by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module:  dcmdata
15  *
16  *  Author:  Marco Eichelberg
17  *
18  *  Purpose: file cache facility for DcmElement::getPartialValue
19  *
20  */
21 
22 
23 #ifndef DCWCACHE_H
24 #define DCWCACHE_H
25 
26 #include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
27 
28 #include "dcmtk/ofstd/oftypes.h"      /* for Uint8 */
29 #include "dcmtk/dcmdata/dcfcache.h"   /* for class DcmFileCache */
30 
31 class DcmElement;
32 class DcmOutputStream;
33 
34 #define DcmWriteCacheBufsize 65536    /* buffer size, in bytes */
35 
36 /** This class implements a buffering mechanism that is used when writing large
37  *  elements that reside in file into an output stream. DcmElement::getPartialValue
38  *  is used to fill the buffer maintained by this class, and the buffer content
39  *  is then copied to the output stream. The intermediate buffer is necessary
40  *  because both DcmElement::getPartialValue and DcmOutputStream::write expect
41  *  a buffer to write to and read from, respectively.
42  */
43 class DCMTK_DCMDATA_EXPORT DcmWriteCache
44 {
45 public:
46 
47   /// default constructor. Construction is cheap (no allocation of memory block).
DcmWriteCache()48   DcmWriteCache()
49   : fcache_()
50   , buf_(NULL)
51   , owner_(NULL)
52   , offset_(0)
53   , numBytes_(0)
54   , capacity_(0)
55   , fieldLength_(0)
56   , fieldOffset_(0)
57   , byteOrder_(EBO_unknown)
58   {
59   }
60 
61   /// destructor
~DcmWriteCache()62   ~DcmWriteCache()
63   {
64     delete[] buf_;
65   }
66 
67   /** initialize the buffer maintained by this class. Can safely be called multiple times.
68    *  @param owner current "owner" (DcmElement instance using this buffer)
69    *  @param fieldLength number of bytes of user data in DICOM element
70    *  @param bytesTransferred number of bytes of user data in DICOM element that have already been transferred
71    *  @param byteOrder byteOrder desired byte order in buffer
72    */
73   void init(void *owner, Uint32 fieldLength, Uint32 bytesTransferred, E_ByteOrder byteOrder);
74 
75   /** check whether the buffer is currently empty
76    *  @return true if buffer is empty, false otherwise
77    */
bufferIsEmpty()78   OFBool bufferIsEmpty() const { return (numBytes_ == 0); }
79 
80   /** return the number of bytes of user data currently in buffer
81    *  @return number of bytes of user data currently in buffer
82    */
contentLength()83   Uint32 contentLength() const { return numBytes_; }
84 
85   /** fill buffer from given DICOM element if buffer is currently empty.
86    *  This method uses DcmElement::getPartialValue to fill the buffer from the given
87    *  DICOM element at the given offset (which is updated to reflect the number of bytes
88    *  read into the buffer).
89    *  @param elem DICOM element to read from
90    *  @return EC_Normal if successful, an error code otherwise
91    */
92   OFCondition fillBuffer(DcmElement& elem);
93 
94   /** write buffer content to output stream
95    *  @param outStream output stream to write to
96    *  @return number of bytes written
97    */
98   Uint32 writeBuffer(DcmOutputStream &outStream);
99 
100 private:
101 
102   /// private undefined copy constructor
103   DcmWriteCache(const DcmWriteCache& arg);
104 
105   /// private undefined copy assignment operator
106   DcmWriteCache& operator=(const DcmWriteCache& arg);
107 
108   /// file cache object
109   DcmFileCache fcache_;
110 
111   /// write buffer
112   Uint8 *buf_;
113 
114   /// current "owner" (DcmElement instance using this buffer)
115   void *owner_;
116 
117   /// offset within buffer to first byte
118   Uint32 offset_;
119 
120   /// number of user data bytes currently in buffer
121   Uint32 numBytes_;
122 
123   /// buffer size in bytes
124   Uint32 capacity_;
125 
126   /// length of the current DICOM element, in bytes
127   Uint32 fieldLength_;
128 
129   /// offset within the current DICOM element, in bytes
130   Uint32 fieldOffset_;
131 
132   /// current output byte order
133   E_ByteOrder byteOrder_;
134 };
135 
136 #endif
137